|
|
|
"""Authentication routes"""
|
|
|
|
# pylint: disable=invalid-name
|
|
|
|
|
|
|
|
import os
|
|
|
|
import io
|
|
|
|
import base64
|
|
|
|
from urllib.parse import urlparse
|
|
|
|
|
|
|
|
from PIL import Image
|
|
|
|
from flask import Blueprint, render_template, session, redirect, url_for, \
|
|
|
|
request, flash, current_app, abort, send_from_directory
|
|
|
|
|
|
|
|
from app import db
|
|
|
|
from app.models import Tile
|
|
|
|
|
|
|
|
tiles_bp = Blueprint('tiles', __name__)
|
|
|
|
|
|
|
|
|
|
|
|
def valid_tile(z, x, y):
|
|
|
|
"""Returns true if the tile coordinates are valid"""
|
|
|
|
# check z in [0, 22]
|
|
|
|
if z < 0 or z > 22:
|
|
|
|
return False
|
|
|
|
# check x in [0, 2^zoom[
|
|
|
|
if x < 0 or x >= 2**z:
|
|
|
|
return False
|
|
|
|
# check y in [0, 2^zoom[
|
|
|
|
if y < 0 or y >= 2 ** z:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
@tiles_bp.route('/tiles/upload')
|
|
|
|
def upload():
|
|
|
|
"""Render an upload form"""
|
|
|
|
return '''
|
|
|
|
<!doctype html>
|
|
|
|
<title>Upload new File</title>
|
|
|
|
<h1>Upload new File</h1>
|
|
|
|
<form action="/tiles/1/0/1" method=post enctype=multipart/form-data>
|
|
|
|
<input type=file name=file>
|
|
|
|
<input type=submit value=Upload>
|
|
|
|
</form>
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
@tiles_bp.route('/tiles/<int:z>/<int:x>/<int:y>', methods=['GET'])
|
|
|
|
def get_tile(z, x, y):
|
|
|
|
"""Serves a tile"""
|
|
|
|
if not valid_tile(z, x, y):
|
|
|
|
return abort(404)
|
|
|
|
folder = current_app.config['UPLOAD_FOLDER']
|
|
|
|
filename = f'{z}-{x}-{y}.png'
|
|
|
|
|
|
|
|
if not os.path.isfile(os.path.join(folder, filename)):
|
|
|
|
return send_from_directory('static', 'missing.png')
|
|
|
|
|
|
|
|
return send_from_directory('../' + folder, filename)
|
|
|
|
|
|
|
|
|
|
|
|
@tiles_bp.route('/tiles/<int:z>/<int:x>/<int:y>', methods=['POST'])
|
|
|
|
def create_tile(z, x, y):
|
|
|
|
if not valid_tile(z, x, y):
|
|
|
|
return abort(404)
|
|
|
|
|
|
|
|
image_bytes = None
|
|
|
|
# try to read file from request.files (byte-stream)
|
|
|
|
if 'file' in request.files:
|
|
|
|
image_bytes = request.files['file'].stream
|
|
|
|
# try to read file from form (base64 encoded dataURL)
|
|
|
|
if image_bytes is None and ('file' in request.form):
|
|
|
|
parsed_url = urlparse(request.form['file'])
|
|
|
|
head, data = parsed_url.path.split(',', 1)
|
|
|
|
image_bytes = io.BytesIO(base64.b64decode(data))
|
|
|
|
|
|
|
|
if image_bytes is None:
|
|
|
|
flash('No file part')
|
|
|
|
return redirect(url_for('index'))
|
|
|
|
|
|
|
|
try:
|
|
|
|
image = Image.open(image_bytes)
|
|
|
|
image = image.resize((256, 256))
|
|
|
|
except OSError:
|
|
|
|
flash('cannot read image')
|
|
|
|
return redirect(url_for('index'))
|
|
|
|
|
|
|
|
folder = current_app.config['UPLOAD_FOLDER']
|
|
|
|
filename = f'{z}-{x}-{y}.png'
|
|
|
|
image.save(os.path.join(folder, filename))
|
|
|
|
|
|
|
|
flash('Uploaded tile successfully')
|
|
|
|
return redirect(url_for('index'))
|