|  | from __future__ import print_function, absolute_import, unicode_literals | 
        
          |  |  | 
        
          |  | from base64 import urlsafe_b64encode, urlsafe_b64decode | 
        
          |  | from mimetypes import types_map | 
        
          |  | from io import BytesIO | 
        
          |  |  | 
        
          |  | from flask import Blueprint, current_app, send_file, url_for, jsonify | 
        
          |  | from qrcode import QRCode | 
        
          |  | from itsdangerous import Signer | 
        
          |  |  | 
        
          |  |  | 
        
          |  | __all__ = ['make_qrcode_image'] | 
        
          |  |  | 
        
          |  |  | 
        
          |  | bp = Blueprint('qrcode', __name__, url_prefix='/_qrcode') | 
        
          |  |  | 
        
          |  |  | 
        
          |  | @bp.route('/<url>/<signature>') | 
        
          |  | def qrcode_image(url, signature): | 
        
          |  | """The endpoint for generated QRCode image.""" | 
        
          |  | try: | 
        
          |  | url = urlsafe_b64decode(url.encode('ascii')) | 
        
          |  | except (ValueError, UnicodeEncodeError): | 
        
          |  | return jsonify(r=False, error='invalid_data'), 404 | 
        
          |  |  | 
        
          |  | signer = get_qrcode_signer() | 
        
          |  | if not signer.verify_signature(url, signature): | 
        
          |  | return jsonify(r=False, error='invalid_signature'), 404 | 
        
          |  |  | 
        
          |  | image = make_qrcode_image(url, border=0) | 
        
          |  | response = make_image_response(image, kind='png') | 
        
          |  | return response | 
        
          |  |  | 
        
          |  |  | 
        
          |  | def get_qrcode_signer(app=None): | 
        
          |  | """Creates a signer by the secret key of current app.""" | 
        
          |  | app = app or current_app | 
        
          |  | if 'qrcode.signer' not in app.extensions: | 
        
          |  | app.extensions['qrcode.signer'] = Signer(app.secret_key) | 
        
          |  | return app.extensions['qrcode.signer'] | 
        
          |  |  | 
        
          |  |  | 
        
          |  | def make_qrcode_image(data, **kwargs): | 
        
          |  | """Creates a QRCode image from given data.""" | 
        
          |  | qrcode = QRCode(**kwargs) | 
        
          |  | qrcode.add_data(data) | 
        
          |  | return qrcode.make_image() | 
        
          |  |  | 
        
          |  |  | 
        
          |  | def make_image_response(image, kind): | 
        
          |  | """Creates a cacheable response from given image.""" | 
        
          |  | mimetype = types_map['.' + kind.lower()] | 
        
          |  | io = BytesIO() | 
        
          |  | image.save(io, kind.upper()) | 
        
          |  | io.seek(0) | 
        
          |  | return send_file(io, mimetype=mimetype, conditional=True) | 
        
          |  |  | 
        
          |  |  | 
        
          |  | def make_qrcode_url(url): | 
        
          |  | """Creates a signed URL which pointed to a QRCode image.""" | 
        
          |  | signer = get_qrcode_signer() | 
        
          |  | signature = signer.get_signature(url) | 
        
          |  | url = urlsafe_b64encode(url.strip().encode('utf-8')) | 
        
          |  | return url_for('jqrcode.qrcode_image', url=url, signature=signature) |