We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Certain templates can be force loaded
There are certain templates which are accessible because of the static_html handler. This isn't a vulnerability because it appears like no sensitive information is loaded but it should be fixed. 

It's possible that the template handler itself should just be entirely removed. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `CTFd/views.py`
Content:
```
1 import os
2 import re
3 
4 from flask import current_app as app, render_template, request, redirect, abort, jsonify, url_for, session, Blueprint, Response, send_file
5 from flask.helpers import safe_join
6 from jinja2.exceptions import TemplateNotFound
7 from passlib.hash import bcrypt_sha256
8 
9 from CTFd.models import db, Teams, Solves, Awards, Files, Pages
10 from CTFd.utils import cache, markdown
11 from CTFd import utils
12 
13 views = Blueprint('views', __name__)
14 
15 
16 @views.route('/setup', methods=['GET', 'POST'])
17 def setup():
18     # with app.app_context():
19         # admin = Teams.query.filter_by(admin=True).first()
20 
21     if not utils.is_setup():
22         if not session.get('nonce'):
23             session['nonce'] = utils.sha512(os.urandom(10))
24         if request.method == 'POST':
25             ctf_name = request.form['ctf_name']
26             ctf_name = utils.set_config('ctf_name', ctf_name)
27 
28             # CSS
29             css = utils.set_config('start', '')
30 
31             # Admin user
32             name = request.form['name']
33             email = request.form['email']
34             password = request.form['password']
35             admin = Teams(name, email, password)
36             admin.admin = True
37             admin.banned = True
38 
39             # Index page
40 
41             index = """<div class="row">
42     <div class="col-md-6 offset-md-3">
43         <img class="w-100 mx-auto d-block" style="max-width: 500px;padding: 50px;padding-top: 14vh;" src="themes/core/static/img/logo.png" />
44         <h3 class="text-center">
45             <p>A cool CTF platform from <a href="https://ctfd.io">ctfd.io</a></p>
46             <p>Follow us on social media:</p>
47             <a href="https://twitter.com/ctfdio"><i class="fab fa-twitter fa-2x" aria-hidden="true"></i></a>&nbsp;
48             <a href="https://facebook.com/ctfdio"><i class="fab fa-facebook fa-2x" aria-hidden="true"></i></a>&nbsp;
49             <a href="https://github.com/ctfd"><i class="fab fa-github fa-2x" aria-hidden="true"></i></a>
50         </h3>
51         <br>
52         <h4 class="text-center">
53             <a href="admin">Click here</a> to login and setup your CTF
54         </h4>
55     </div>
56 </div>""".format(request.script_root)
57 
58             page = Pages(title=None, route='index', html=index, draft=False)
59 
60             # max attempts per challenge
61             max_tries = utils.set_config('max_tries', 0)
62 
63             # Start time
64             start = utils.set_config('start', None)
65             end = utils.set_config('end', None)
66             freeze = utils.set_config('freeze', None)
67 
68             # Challenges cannot be viewed by unregistered users
69             view_challenges_unregistered = utils.set_config('view_challenges_unregistered', None)
70 
71             # Allow/Disallow registration
72             prevent_registration = utils.set_config('prevent_registration', None)
73 
74             # Verify emails
75             verify_emails = utils.set_config('verify_emails', None)
76 
77             mail_server = utils.set_config('mail_server', None)
78             mail_port = utils.set_config('mail_port', None)
79             mail_tls = utils.set_config('mail_tls', None)
80             mail_ssl = utils.set_config('mail_ssl', None)
81             mail_username = utils.set_config('mail_username', None)
82             mail_password = utils.set_config('mail_password', None)
83             mail_useauth = utils.set_config('mail_useauth', None)
84 
85             setup = utils.set_config('setup', True)
86 
87             db.session.add(page)
88             db.session.add(admin)
89             db.session.commit()
90 
91             session['username'] = admin.name
92             session['id'] = admin.id
93             session['admin'] = admin.admin
94             session['nonce'] = utils.sha512(os.urandom(10))
95 
96             db.session.close()
97             app.setup = False
98             with app.app_context():
99                 cache.clear()
100 
101             return redirect(url_for('views.static_html'))
102         return render_template('setup.html', nonce=session.get('nonce'))
103     return redirect(url_for('views.static_html'))
104 
105 
106 # Custom CSS handler
107 @views.route('/static/user.css')
108 def custom_css():
109     return Response(utils.get_config('css'), mimetype='text/css')
110 
111 
112 # Static HTML files
113 @views.route("/", defaults={'template': 'index'})
114 @views.route("/<path:template>")
115 def static_html(template):
116     page = utils.get_page(template)
117     if page is None:
118         try:
119             return render_template('%s.html' % template)
120         except TemplateNotFound:
121             abort(404)
122     else:
123         if page.auth_required and utils.authed() is False:
124             return redirect(url_for('auth.login', next=request.path))
125 
126         return render_template('page.html', content=markdown(page.html))
127 
128 
129 @views.route('/teams', defaults={'page': '1'})
130 @views.route('/teams/<int:page>')
131 def teams(page):
132     if utils.get_config('workshop_mode'):
133         abort(404)
134     page = abs(int(page))
135     results_per_page = 50
136     page_start = results_per_page * (page - 1)
137     page_end = results_per_page * (page - 1) + results_per_page
138 
139     if utils.get_config('verify_emails'):
140         count = Teams.query.filter_by(verified=True, banned=False).count()
141         teams = Teams.query.filter_by(verified=True, banned=False).slice(page_start, page_end).all()
142     else:
143         count = Teams.query.filter_by(banned=False).count()
144         teams = Teams.query.filter_by(banned=False).slice(page_start, page_end).all()
145     pages = int(count / results_per_page) + (count % results_per_page > 0)
146     return render_template('teams.html', teams=teams, team_pages=pages, curr_page=page)
147 
148 
149 @views.route('/team', methods=['GET'])
150 def private_team():
151     if utils.authed():
152         teamid = session['id']
153 
154         freeze = utils.get_config('freeze')
155         user = Teams.query.filter_by(id=teamid).first_or_404()
156         solves = Solves.query.filter_by(teamid=teamid)
157         awards = Awards.query.filter_by(teamid=teamid)
158 
159         place = user.place()
160         score = user.score()
161 
162         if freeze:
163             freeze = utils.unix_time_to_utc(freeze)
164             if teamid != session.get('id'):
165                 solves = solves.filter(Solves.date < freeze)
166                 awards = awards.filter(Awards.date < freeze)
167 
168         solves = solves.all()
169         awards = awards.all()
170 
171         return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen())
172     else:
173         return redirect(url_for('auth.login'))
174 
175 
176 @views.route('/team/<int:teamid>', methods=['GET', 'POST'])
177 def team(teamid):
178     if utils.get_config('workshop_mode'):
179         abort(404)
180 
181     if utils.get_config('view_scoreboard_if_utils.authed') and not utils.authed():
182         return redirect(url_for('auth.login', next=request.path))
183     errors = []
184     freeze = utils.get_config('freeze')
185     user = Teams.query.filter_by(id=teamid).first_or_404()
186     solves = Solves.query.filter_by(teamid=teamid)
187     awards = Awards.query.filter_by(teamid=teamid)
188 
189     place = user.place()
190     score = user.score()
191 
192     if freeze:
193         freeze = utils.unix_time_to_utc(freeze)
194         if teamid != session.get('id'):
195             solves = solves.filter(Solves.date < freeze)
196             awards = awards.filter(Awards.date < freeze)
197 
198     solves = solves.all()
199     awards = awards.all()
200 
201     db.session.close()
202 
203     if utils.hide_scores() and teamid != session.get('id'):
204         errors.append('Scores are currently hidden')
205 
206     if errors:
207         return render_template('team.html', team=user, errors=errors)
208 
209     if request.method == 'GET':
210         return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen())
211     elif request.method == 'POST':
212         json = {'solves': []}
213         for x in solves:
214             json['solves'].append({'id': x.id, 'chal': x.chalid, 'team': x.teamid})
215         return jsonify(json)
216 
217 
218 @views.route('/profile', methods=['POST', 'GET'])
219 def profile():
220     if utils.authed():
221         if request.method == "POST":
222             errors = []
223 
224             name = request.form.get('name').strip()
225             email = request.form.get('email').strip()
226             website = request.form.get('website').strip()
227             affiliation = request.form.get('affiliation').strip()
228             country = request.form.get('country').strip()
229 
230             user = Teams.query.filter_by(id=session['id']).first()
231 
232             if not utils.get_config('prevent_name_change'):
233                 names = Teams.query.filter_by(name=name).first()
234                 name_len = len(request.form['name']) == 0
235 
236             emails = Teams.query.filter_by(email=email).first()
237             valid_email = utils.check_email_format(email)
238 
239             if utils.check_email_format(name) is True:
240                 errors.append('Team name cannot be an email address')
241 
242             if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \
243                     (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):
244                 errors.append("Your old password doesn't match what we have.")
245             if not valid_email:
246                 errors.append("That email doesn't look right")
247             if not utils.get_config('prevent_name_change') and names and name != session['username']:
248                 errors.append('That team name is already taken')
249             if emails and emails.id != session['id']:
250                 errors.append('That email has already been used')
251             if not utils.get_config('prevent_name_change') and name_len:
252                 errors.append('Pick a longer team name')
253             if website.strip() and not utils.validate_url(website):
254                 errors.append("That doesn't look like a valid URL")
255 
256             if len(errors) > 0:
257                 return render_template('profile.html', name=name, email=email, website=website,
258                                        affiliation=affiliation, country=country, errors=errors)
259             else:
260                 team = Teams.query.filter_by(id=session['id']).first()
261                 if team.name != name:
262                     if not utils.get_config('prevent_name_change'):
263                         team.name = name
264                         session['username'] = team.name
265                 if team.email != email.lower():
266                     team.email = email.lower()
267                     if utils.get_config('verify_emails'):
268                         team.verified = False
269 
270                 if 'password' in request.form.keys() and not len(request.form['password']) == 0:
271                     team.password = bcrypt_sha256.encrypt(request.form.get('password'))
272                 team.website = website
273                 team.affiliation = affiliation
274                 team.country = country
275                 db.session.commit()
276                 db.session.close()
277                 return redirect(url_for('views.profile'))
278         else:
279             user = Teams.query.filter_by(id=session['id']).first()
280             name = user.name
281             email = user.email
282             website = user.website
283             affiliation = user.affiliation
284             country = user.country
285             prevent_name_change = utils.get_config('prevent_name_change')
286             confirm_email = utils.get_config('verify_emails') and not user.verified
287             return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation,
288                                    country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email)
289     else:
290         return redirect(url_for('auth.login'))
291 
292 
293 @views.route('/files', defaults={'path': ''})
294 @views.route('/files/<path:path>')
295 def file_handler(path):
296     f = Files.query.filter_by(location=path).first_or_404()
297     if f.chal:
298         if not utils.is_admin():
299             if not utils.ctftime():
300                 if utils.view_after_ctf() and utils.ctf_started():
301                     pass
302                 else:
303                     abort(403)
304     upload_folder = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'])
305     return send_file(safe_join(upload_folder, f.location))
306 
307 
308 @views.route('/themes/<theme>/static/<path:path>')
309 def themes_handler(theme, path):
310     filename = safe_join(app.root_path, 'themes', theme, 'static', path)
311     if os.path.isfile(filename):
312         return send_file(filename)
313     else:
314         abort(404)
315
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/CTFd/views.py b/CTFd/views.py
--- a/CTFd/views.py
+++ b/CTFd/views.py
@@ -115,10 +115,7 @@
 def static_html(template):
     page = utils.get_page(template)
     if page is None:
-        try:
-            return render_template('%s.html' % template)
-        except TemplateNotFound:
-            abort(404)
+        abort(404)
     else:
         if page.auth_required and utils.authed() is False:
             return redirect(url_for('auth.login', next=request.path))

{"golden_diff": "diff --git a/CTFd/views.py b/CTFd/views.py\n--- a/CTFd/views.py\n+++ b/CTFd/views.py\n@@ -115,10 +115,7 @@\n def static_html(template):\n     page = utils.get_page(template)\n     if page is None:\n-        try:\n-            return render_template('%s.html' % template)\n-        except TemplateNotFound:\n-            abort(404)\n+        abort(404)\n     else:\n         if page.auth_required and utils.authed() is False:\n             return redirect(url_for('auth.login', next=request.path))\n", "issue": "Certain templates can be force loaded\nThere are certain templates which are accessible because of the static_html handler. This isn't a vulnerability because it appears like no sensitive information is loaded but it should be fixed. \r\n\r\nIt's possible that the template handler itself should just be entirely removed. \n", "before_files": [{"content": "import os\nimport re\n\nfrom flask import current_app as app, render_template, request, redirect, abort, jsonify, url_for, session, Blueprint, Response, send_file\nfrom flask.helpers import safe_join\nfrom jinja2.exceptions import TemplateNotFound\nfrom passlib.hash import bcrypt_sha256\n\nfrom CTFd.models import db, Teams, Solves, Awards, Files, Pages\nfrom CTFd.utils import cache, markdown\nfrom CTFd import utils\n\nviews = Blueprint('views', __name__)\n\n\n@views.route('/setup', methods=['GET', 'POST'])\ndef setup():\n    # with app.app_context():\n        # admin = Teams.query.filter_by(admin=True).first()\n\n    if not utils.is_setup():\n        if not session.get('nonce'):\n            session['nonce'] = utils.sha512(os.urandom(10))\n        if request.method == 'POST':\n            ctf_name = request.form['ctf_name']\n            ctf_name = utils.set_config('ctf_name', ctf_name)\n\n            # CSS\n            css = utils.set_config('start', '')\n\n            # Admin user\n            name = request.form['name']\n            email = request.form['email']\n            password = request.form['password']\n            admin = Teams(name, email, password)\n            admin.admin = True\n            admin.banned = True\n\n            # Index page\n\n            index = \"\"\"<div class=\"row\">\n    <div class=\"col-md-6 offset-md-3\">\n        <img class=\"w-100 mx-auto d-block\" style=\"max-width: 500px;padding: 50px;padding-top: 14vh;\" src=\"themes/core/static/img/logo.png\" />\n        <h3 class=\"text-center\">\n            <p>A cool CTF platform from <a href=\"https://ctfd.io\">ctfd.io</a></p>\n            <p>Follow us on social media:</p>\n            <a href=\"https://twitter.com/ctfdio\"><i class=\"fab fa-twitter fa-2x\" aria-hidden=\"true\"></i></a>&nbsp;\n            <a href=\"https://facebook.com/ctfdio\"><i class=\"fab fa-facebook fa-2x\" aria-hidden=\"true\"></i></a>&nbsp;\n            <a href=\"https://github.com/ctfd\"><i class=\"fab fa-github fa-2x\" aria-hidden=\"true\"></i></a>\n        </h3>\n        <br>\n        <h4 class=\"text-center\">\n            <a href=\"admin\">Click here</a> to login and setup your CTF\n        </h4>\n    </div>\n</div>\"\"\".format(request.script_root)\n\n            page = Pages(title=None, route='index', html=index, draft=False)\n\n            # max attempts per challenge\n            max_tries = utils.set_config('max_tries', 0)\n\n            # Start time\n            start = utils.set_config('start', None)\n            end = utils.set_config('end', None)\n            freeze = utils.set_config('freeze', None)\n\n            # Challenges cannot be viewed by unregistered users\n            view_challenges_unregistered = utils.set_config('view_challenges_unregistered', None)\n\n            # Allow/Disallow registration\n            prevent_registration = utils.set_config('prevent_registration', None)\n\n            # Verify emails\n            verify_emails = utils.set_config('verify_emails', None)\n\n            mail_server = utils.set_config('mail_server', None)\n            mail_port = utils.set_config('mail_port', None)\n            mail_tls = utils.set_config('mail_tls', None)\n            mail_ssl = utils.set_config('mail_ssl', None)\n            mail_username = utils.set_config('mail_username', None)\n            mail_password = utils.set_config('mail_password', None)\n            mail_useauth = utils.set_config('mail_useauth', None)\n\n            setup = utils.set_config('setup', True)\n\n            db.session.add(page)\n            db.session.add(admin)\n            db.session.commit()\n\n            session['username'] = admin.name\n            session['id'] = admin.id\n            session['admin'] = admin.admin\n            session['nonce'] = utils.sha512(os.urandom(10))\n\n            db.session.close()\n            app.setup = False\n            with app.app_context():\n                cache.clear()\n\n            return redirect(url_for('views.static_html'))\n        return render_template('setup.html', nonce=session.get('nonce'))\n    return redirect(url_for('views.static_html'))\n\n\n# Custom CSS handler\n@views.route('/static/user.css')\ndef custom_css():\n    return Response(utils.get_config('css'), mimetype='text/css')\n\n\n# Static HTML files\n@views.route(\"/\", defaults={'template': 'index'})\n@views.route(\"/<path:template>\")\ndef static_html(template):\n    page = utils.get_page(template)\n    if page is None:\n        try:\n            return render_template('%s.html' % template)\n        except TemplateNotFound:\n            abort(404)\n    else:\n        if page.auth_required and utils.authed() is False:\n            return redirect(url_for('auth.login', next=request.path))\n\n        return render_template('page.html', content=markdown(page.html))\n\n\n@views.route('/teams', defaults={'page': '1'})\n@views.route('/teams/<int:page>')\ndef teams(page):\n    if utils.get_config('workshop_mode'):\n        abort(404)\n    page = abs(int(page))\n    results_per_page = 50\n    page_start = results_per_page * (page - 1)\n    page_end = results_per_page * (page - 1) + results_per_page\n\n    if utils.get_config('verify_emails'):\n        count = Teams.query.filter_by(verified=True, banned=False).count()\n        teams = Teams.query.filter_by(verified=True, banned=False).slice(page_start, page_end).all()\n    else:\n        count = Teams.query.filter_by(banned=False).count()\n        teams = Teams.query.filter_by(banned=False).slice(page_start, page_end).all()\n    pages = int(count / results_per_page) + (count % results_per_page > 0)\n    return render_template('teams.html', teams=teams, team_pages=pages, curr_page=page)\n\n\n@views.route('/team', methods=['GET'])\ndef private_team():\n    if utils.authed():\n        teamid = session['id']\n\n        freeze = utils.get_config('freeze')\n        user = Teams.query.filter_by(id=teamid).first_or_404()\n        solves = Solves.query.filter_by(teamid=teamid)\n        awards = Awards.query.filter_by(teamid=teamid)\n\n        place = user.place()\n        score = user.score()\n\n        if freeze:\n            freeze = utils.unix_time_to_utc(freeze)\n            if teamid != session.get('id'):\n                solves = solves.filter(Solves.date < freeze)\n                awards = awards.filter(Awards.date < freeze)\n\n        solves = solves.all()\n        awards = awards.all()\n\n        return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen())\n    else:\n        return redirect(url_for('auth.login'))\n\n\n@views.route('/team/<int:teamid>', methods=['GET', 'POST'])\ndef team(teamid):\n    if utils.get_config('workshop_mode'):\n        abort(404)\n\n    if utils.get_config('view_scoreboard_if_utils.authed') and not utils.authed():\n        return redirect(url_for('auth.login', next=request.path))\n    errors = []\n    freeze = utils.get_config('freeze')\n    user = Teams.query.filter_by(id=teamid).first_or_404()\n    solves = Solves.query.filter_by(teamid=teamid)\n    awards = Awards.query.filter_by(teamid=teamid)\n\n    place = user.place()\n    score = user.score()\n\n    if freeze:\n        freeze = utils.unix_time_to_utc(freeze)\n        if teamid != session.get('id'):\n            solves = solves.filter(Solves.date < freeze)\n            awards = awards.filter(Awards.date < freeze)\n\n    solves = solves.all()\n    awards = awards.all()\n\n    db.session.close()\n\n    if utils.hide_scores() and teamid != session.get('id'):\n        errors.append('Scores are currently hidden')\n\n    if errors:\n        return render_template('team.html', team=user, errors=errors)\n\n    if request.method == 'GET':\n        return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen())\n    elif request.method == 'POST':\n        json = {'solves': []}\n        for x in solves:\n            json['solves'].append({'id': x.id, 'chal': x.chalid, 'team': x.teamid})\n        return jsonify(json)\n\n\n@views.route('/profile', methods=['POST', 'GET'])\ndef profile():\n    if utils.authed():\n        if request.method == \"POST\":\n            errors = []\n\n            name = request.form.get('name').strip()\n            email = request.form.get('email').strip()\n            website = request.form.get('website').strip()\n            affiliation = request.form.get('affiliation').strip()\n            country = request.form.get('country').strip()\n\n            user = Teams.query.filter_by(id=session['id']).first()\n\n            if not utils.get_config('prevent_name_change'):\n                names = Teams.query.filter_by(name=name).first()\n                name_len = len(request.form['name']) == 0\n\n            emails = Teams.query.filter_by(email=email).first()\n            valid_email = utils.check_email_format(email)\n\n            if utils.check_email_format(name) is True:\n                errors.append('Team name cannot be an email address')\n\n            if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \\\n                    (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):\n                errors.append(\"Your old password doesn't match what we have.\")\n            if not valid_email:\n                errors.append(\"That email doesn't look right\")\n            if not utils.get_config('prevent_name_change') and names and name != session['username']:\n                errors.append('That team name is already taken')\n            if emails and emails.id != session['id']:\n                errors.append('That email has already been used')\n            if not utils.get_config('prevent_name_change') and name_len:\n                errors.append('Pick a longer team name')\n            if website.strip() and not utils.validate_url(website):\n                errors.append(\"That doesn't look like a valid URL\")\n\n            if len(errors) > 0:\n                return render_template('profile.html', name=name, email=email, website=website,\n                                       affiliation=affiliation, country=country, errors=errors)\n            else:\n                team = Teams.query.filter_by(id=session['id']).first()\n                if team.name != name:\n                    if not utils.get_config('prevent_name_change'):\n                        team.name = name\n                        session['username'] = team.name\n                if team.email != email.lower():\n                    team.email = email.lower()\n                    if utils.get_config('verify_emails'):\n                        team.verified = False\n\n                if 'password' in request.form.keys() and not len(request.form['password']) == 0:\n                    team.password = bcrypt_sha256.encrypt(request.form.get('password'))\n                team.website = website\n                team.affiliation = affiliation\n                team.country = country\n                db.session.commit()\n                db.session.close()\n                return redirect(url_for('views.profile'))\n        else:\n            user = Teams.query.filter_by(id=session['id']).first()\n            name = user.name\n            email = user.email\n            website = user.website\n            affiliation = user.affiliation\n            country = user.country\n            prevent_name_change = utils.get_config('prevent_name_change')\n            confirm_email = utils.get_config('verify_emails') and not user.verified\n            return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation,\n                                   country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email)\n    else:\n        return redirect(url_for('auth.login'))\n\n\n@views.route('/files', defaults={'path': ''})\n@views.route('/files/<path:path>')\ndef file_handler(path):\n    f = Files.query.filter_by(location=path).first_or_404()\n    if f.chal:\n        if not utils.is_admin():\n            if not utils.ctftime():\n                if utils.view_after_ctf() and utils.ctf_started():\n                    pass\n                else:\n                    abort(403)\n    upload_folder = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'])\n    return send_file(safe_join(upload_folder, f.location))\n\n\n@views.route('/themes/<theme>/static/<path:path>')\ndef themes_handler(theme, path):\n    filename = safe_join(app.root_path, 'themes', theme, 'static', path)\n    if os.path.isfile(filename):\n        return send_file(filename)\n    else:\n        abort(404)\n", "path": "CTFd/views.py"}], "after_files": [{"content": "import os\nimport re\n\nfrom flask import current_app as app, render_template, request, redirect, abort, jsonify, url_for, session, Blueprint, Response, send_file\nfrom flask.helpers import safe_join\nfrom jinja2.exceptions import TemplateNotFound\nfrom passlib.hash import bcrypt_sha256\n\nfrom CTFd.models import db, Teams, Solves, Awards, Files, Pages\nfrom CTFd.utils import cache, markdown\nfrom CTFd import utils\n\nviews = Blueprint('views', __name__)\n\n\n@views.route('/setup', methods=['GET', 'POST'])\ndef setup():\n    # with app.app_context():\n        # admin = Teams.query.filter_by(admin=True).first()\n\n    if not utils.is_setup():\n        if not session.get('nonce'):\n            session['nonce'] = utils.sha512(os.urandom(10))\n        if request.method == 'POST':\n            ctf_name = request.form['ctf_name']\n            ctf_name = utils.set_config('ctf_name', ctf_name)\n\n            # CSS\n            css = utils.set_config('start', '')\n\n            # Admin user\n            name = request.form['name']\n            email = request.form['email']\n            password = request.form['password']\n            admin = Teams(name, email, password)\n            admin.admin = True\n            admin.banned = True\n\n            # Index page\n\n            index = \"\"\"<div class=\"row\">\n    <div class=\"col-md-6 offset-md-3\">\n        <img class=\"w-100 mx-auto d-block\" style=\"max-width: 500px;padding: 50px;padding-top: 14vh;\" src=\"themes/core/static/img/logo.png\" />\n        <h3 class=\"text-center\">\n            <p>A cool CTF platform from <a href=\"https://ctfd.io\">ctfd.io</a></p>\n            <p>Follow us on social media:</p>\n            <a href=\"https://twitter.com/ctfdio\"><i class=\"fab fa-twitter fa-2x\" aria-hidden=\"true\"></i></a>&nbsp;\n            <a href=\"https://facebook.com/ctfdio\"><i class=\"fab fa-facebook fa-2x\" aria-hidden=\"true\"></i></a>&nbsp;\n            <a href=\"https://github.com/ctfd\"><i class=\"fab fa-github fa-2x\" aria-hidden=\"true\"></i></a>\n        </h3>\n        <br>\n        <h4 class=\"text-center\">\n            <a href=\"admin\">Click here</a> to login and setup your CTF\n        </h4>\n    </div>\n</div>\"\"\".format(request.script_root)\n\n            page = Pages(title=None, route='index', html=index, draft=False)\n\n            # max attempts per challenge\n            max_tries = utils.set_config('max_tries', 0)\n\n            # Start time\n            start = utils.set_config('start', None)\n            end = utils.set_config('end', None)\n            freeze = utils.set_config('freeze', None)\n\n            # Challenges cannot be viewed by unregistered users\n            view_challenges_unregistered = utils.set_config('view_challenges_unregistered', None)\n\n            # Allow/Disallow registration\n            prevent_registration = utils.set_config('prevent_registration', None)\n\n            # Verify emails\n            verify_emails = utils.set_config('verify_emails', None)\n\n            mail_server = utils.set_config('mail_server', None)\n            mail_port = utils.set_config('mail_port', None)\n            mail_tls = utils.set_config('mail_tls', None)\n            mail_ssl = utils.set_config('mail_ssl', None)\n            mail_username = utils.set_config('mail_username', None)\n            mail_password = utils.set_config('mail_password', None)\n            mail_useauth = utils.set_config('mail_useauth', None)\n\n            setup = utils.set_config('setup', True)\n\n            db.session.add(page)\n            db.session.add(admin)\n            db.session.commit()\n\n            session['username'] = admin.name\n            session['id'] = admin.id\n            session['admin'] = admin.admin\n            session['nonce'] = utils.sha512(os.urandom(10))\n\n            db.session.close()\n            app.setup = False\n            with app.app_context():\n                cache.clear()\n\n            return redirect(url_for('views.static_html'))\n        return render_template('setup.html', nonce=session.get('nonce'))\n    return redirect(url_for('views.static_html'))\n\n\n# Custom CSS handler\n@views.route('/static/user.css')\ndef custom_css():\n    return Response(utils.get_config('css'), mimetype='text/css')\n\n\n# Static HTML files\n@views.route(\"/\", defaults={'template': 'index'})\n@views.route(\"/<path:template>\")\ndef static_html(template):\n    page = utils.get_page(template)\n    if page is None:\n        abort(404)\n    else:\n        if page.auth_required and utils.authed() is False:\n            return redirect(url_for('auth.login', next=request.path))\n\n        return render_template('page.html', content=markdown(page.html))\n\n\n@views.route('/teams', defaults={'page': '1'})\n@views.route('/teams/<int:page>')\ndef teams(page):\n    if utils.get_config('workshop_mode'):\n        abort(404)\n    page = abs(int(page))\n    results_per_page = 50\n    page_start = results_per_page * (page - 1)\n    page_end = results_per_page * (page - 1) + results_per_page\n\n    if utils.get_config('verify_emails'):\n        count = Teams.query.filter_by(verified=True, banned=False).count()\n        teams = Teams.query.filter_by(verified=True, banned=False).slice(page_start, page_end).all()\n    else:\n        count = Teams.query.filter_by(banned=False).count()\n        teams = Teams.query.filter_by(banned=False).slice(page_start, page_end).all()\n    pages = int(count / results_per_page) + (count % results_per_page > 0)\n    return render_template('teams.html', teams=teams, team_pages=pages, curr_page=page)\n\n\n@views.route('/team', methods=['GET'])\ndef private_team():\n    if utils.authed():\n        teamid = session['id']\n\n        freeze = utils.get_config('freeze')\n        user = Teams.query.filter_by(id=teamid).first_or_404()\n        solves = Solves.query.filter_by(teamid=teamid)\n        awards = Awards.query.filter_by(teamid=teamid)\n\n        place = user.place()\n        score = user.score()\n\n        if freeze:\n            freeze = utils.unix_time_to_utc(freeze)\n            if teamid != session.get('id'):\n                solves = solves.filter(Solves.date < freeze)\n                awards = awards.filter(Awards.date < freeze)\n\n        solves = solves.all()\n        awards = awards.all()\n\n        return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen())\n    else:\n        return redirect(url_for('auth.login'))\n\n\n@views.route('/team/<int:teamid>', methods=['GET', 'POST'])\ndef team(teamid):\n    if utils.get_config('workshop_mode'):\n        abort(404)\n\n    if utils.get_config('view_scoreboard_if_utils.authed') and not utils.authed():\n        return redirect(url_for('auth.login', next=request.path))\n    errors = []\n    freeze = utils.get_config('freeze')\n    user = Teams.query.filter_by(id=teamid).first_or_404()\n    solves = Solves.query.filter_by(teamid=teamid)\n    awards = Awards.query.filter_by(teamid=teamid)\n\n    place = user.place()\n    score = user.score()\n\n    if freeze:\n        freeze = utils.unix_time_to_utc(freeze)\n        if teamid != session.get('id'):\n            solves = solves.filter(Solves.date < freeze)\n            awards = awards.filter(Awards.date < freeze)\n\n    solves = solves.all()\n    awards = awards.all()\n\n    db.session.close()\n\n    if utils.hide_scores() and teamid != session.get('id'):\n        errors.append('Scores are currently hidden')\n\n    if errors:\n        return render_template('team.html', team=user, errors=errors)\n\n    if request.method == 'GET':\n        return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen())\n    elif request.method == 'POST':\n        json = {'solves': []}\n        for x in solves:\n            json['solves'].append({'id': x.id, 'chal': x.chalid, 'team': x.teamid})\n        return jsonify(json)\n\n\n@views.route('/profile', methods=['POST', 'GET'])\ndef profile():\n    if utils.authed():\n        if request.method == \"POST\":\n            errors = []\n\n            name = request.form.get('name').strip()\n            email = request.form.get('email').strip()\n            website = request.form.get('website').strip()\n            affiliation = request.form.get('affiliation').strip()\n            country = request.form.get('country').strip()\n\n            user = Teams.query.filter_by(id=session['id']).first()\n\n            if not utils.get_config('prevent_name_change'):\n                names = Teams.query.filter_by(name=name).first()\n                name_len = len(request.form['name']) == 0\n\n            emails = Teams.query.filter_by(email=email).first()\n            valid_email = utils.check_email_format(email)\n\n            if utils.check_email_format(name) is True:\n                errors.append('Team name cannot be an email address')\n\n            if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \\\n                    (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):\n                errors.append(\"Your old password doesn't match what we have.\")\n            if not valid_email:\n                errors.append(\"That email doesn't look right\")\n            if not utils.get_config('prevent_name_change') and names and name != session['username']:\n                errors.append('That team name is already taken')\n            if emails and emails.id != session['id']:\n                errors.append('That email has already been used')\n            if not utils.get_config('prevent_name_change') and name_len:\n                errors.append('Pick a longer team name')\n            if website.strip() and not utils.validate_url(website):\n                errors.append(\"That doesn't look like a valid URL\")\n\n            if len(errors) > 0:\n                return render_template('profile.html', name=name, email=email, website=website,\n                                       affiliation=affiliation, country=country, errors=errors)\n            else:\n                team = Teams.query.filter_by(id=session['id']).first()\n                if team.name != name:\n                    if not utils.get_config('prevent_name_change'):\n                        team.name = name\n                        session['username'] = team.name\n                if team.email != email.lower():\n                    team.email = email.lower()\n                    if utils.get_config('verify_emails'):\n                        team.verified = False\n\n                if 'password' in request.form.keys() and not len(request.form['password']) == 0:\n                    team.password = bcrypt_sha256.encrypt(request.form.get('password'))\n                team.website = website\n                team.affiliation = affiliation\n                team.country = country\n                db.session.commit()\n                db.session.close()\n                return redirect(url_for('views.profile'))\n        else:\n            user = Teams.query.filter_by(id=session['id']).first()\n            name = user.name\n            email = user.email\n            website = user.website\n            affiliation = user.affiliation\n            country = user.country\n            prevent_name_change = utils.get_config('prevent_name_change')\n            confirm_email = utils.get_config('verify_emails') and not user.verified\n            return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation,\n                                   country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email)\n    else:\n        return redirect(url_for('auth.login'))\n\n\n@views.route('/files', defaults={'path': ''})\n@views.route('/files/<path:path>')\ndef file_handler(path):\n    f = Files.query.filter_by(location=path).first_or_404()\n    if f.chal:\n        if not utils.is_admin():\n            if not utils.ctftime():\n                if utils.view_after_ctf() and utils.ctf_started():\n                    pass\n                else:\n                    abort(403)\n    upload_folder = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'])\n    return send_file(safe_join(upload_folder, f.location))\n\n\n@views.route('/themes/<theme>/static/<path:path>')\ndef themes_handler(theme, path):\n    filename = safe_join(app.root_path, 'themes', theme, 'static', path)\n    if os.path.isfile(filename):\n        return send_file(filename)\n    else:\n        abort(404)\n", "path": "CTFd/views.py"}]}