Skip to content
module.py 81.3 KiB
Newer Older
    elif user.get( 'password', None ) != None:
        return jsonify( {
            'error': True,
            'message': "password already set"
        } )
    
    ############################################################################
    
    password = pbkdf2( password, random_data( 65 ), 50000 ).hash()
    
    q = config.db.query( "UPDATE users SET password = %s WHERE username = %s", ( password, username, ) )
    config.db.commit()
    
    session[ 'username' ] = username
    
    ############################################################################
    
    return jsonify( {
        'error': False
    } )

@app.route( baseurl + '/config/donor/<h>' )
def config_new_user_donor( h ):
    session.clear()
    
    sql = "SELECT id, username, email FROM users WHERE type = 2 AND password IS NULL"
    for r in config.db.query_fetchall( sql ):
        if h == hashlib.sha512( r[ 'email' ] ).hexdigest():
            user = r
            break
    
    else:
        return redirect( url_for( "home" ) )
    
    session[ 'email_hash' ] = h
    session[ 'user_id' ] = user[ 'id' ]
    
    return render_template( 
        "users/config.html",
        baseurl = baseurl,
        js = config.cdnjs,
        css = config.cdncss,
        session_timeout = config.session_timeout,
        envtype = envtype,
        next_step = "do_config_new_donor",
        hash = h
    )

@app.route( baseurl + '/do_config/donor', methods = [ 'POST' ] )
def do_config_new_donor():
    username = request.form.get( "username" )
    password = request.form.get( "password" )
    password = pbkdf2( password, random_data( 100 ), 50000 ).hash()
    h = request.form.get( "hash" )
    
    sql = "SELECT id FROM users WHERE username = %s"
    user_id = config.db.query_fetchone( sql, ( username, ) )[ 'id' ]
    
    session[ 'username' ] = username
    
    if session[ "email_hash" ] == h and session[ "user_id" ] == user_id:
        q = config.db.query( "UPDATE users SET password = %s WHERE username = %s", ( password, username, ) )
        config.db.commit()
        
        return jsonify( {
            "error": False
        } )
    
    else:
        return jsonify( {
            "error": True,
            "message": "Invalid parameters"
        } )

Marco De Donno's avatar
Marco De Donno committed
@app.route( baseurl + '/totp_help' )
def totp_help():
    return render_template( 
        "totp_help.html",
        baseurl = baseurl,
        js = config.cdnjs,
        css = config.cdncss,
        envtype = envtype
################################################################################
#    QR Code generation

def renew_secret():
Marco De Donno's avatar
Marco De Donno committed
    secret = pyotp.random_base32( 40 )
    session[ 'secret' ] = secret
    
    return secret

def get_secret():
    secret = session.get( "secret", None )
    if secret == None:
        secret = renew_secret()
    
    return secret

@app.route( baseurl + '/set_secret' )
def set_secret():
    config.db.query( "UPDATE users SET totp = %s WHERE username = %s", ( session[ 'secret' ], session[ 'username' ], ) )
    config.db.commit()
    
    return jsonify( {
        'error': False
    } )

@app.route( baseurl + '/secret' )
def request_secret():
    get_secret()
    
    return jsonify( {
        'error': False,
        'secret': session[ 'secret' ]
    } )

@app.route( baseurl + '/new_secret' )
def request_renew_secret():
    renew_secret()
    
    return jsonify( {
        'error': False,
        'secret': session[ 'secret' ]
    } )

@app.route( baseurl + '/qrcode' )
def send_qrcode():
    if 'username' in session:
        qrcode_value = 'otpauth://totp/ICNML%20' + session[ 'username' ] + '?secret=' + get_secret()
    else:
        qrcode_value = 'otpauth://totp/ICNML?secret=' + get_secret()
    
    img = qrcode.make( qrcode_value )
    
    temp = StringIO()
    img.save( temp, format = "png" )
    temp.seek( 0 )
    
    return send_file( temp, mimetype = 'image/png' )
    
@app.route( baseurl + '/user_qrcode' )
def serve_qrcode():
    return render_template( 
        "qrcode.html",
        baseurl = baseurl,
        secret = get_secret(),
        js = config.cdnjs,
        css = config.cdncss,
        session_timeout = config.session_timeout,
        envtype = envtype
################################################################################
#    Data decryption

def do_decrypt( data ):
        data = AESCipher( session[ 'password' ] ).decrypt( data )
        
        if data.startswith( encryption_prefix ):
            return data[ len( encryption_prefix ): ]
        else:
            return "-"
    

def do_encrypt( data ):
    return AESCipher( session[ 'password' ] ).encrypt( encryption_prefix + data )
Marco De Donno's avatar
Marco De Donno committed
################################################################################
#    File upload

@app.route( baseurl + '/upload', methods = [ 'GET', 'POST' ] )
@login_required
def upload_file():
    upload_type = request.form.get( "upload_type", None )
    
    if upload_type == None:
Marco De Donno's avatar
Marco De Donno committed
        return jsonify( {
            'error': True,
            'msg': 'Must specify a file type to upload a file'
        } )
    
    if request.method == 'POST':
        if 'file' not in request.files:
            return jsonify( { 'error': True, 'msg': 'No file in the POST request' } )
        elif 'upload_id' not in request.form:
            return jsonify( { 'error': True, 'msg': 'No upload_id' } )
                upload_uuid = request.form.get( "upload_id" )
                sql = "SELECT id FROM submissions WHERE uuid = %s"
                upload_id = r.fetchone()[ 'id' ]
                
            except:
                return jsonify( {
                    'error': True
                } )
            
            file = request.files[ 'file' ]
            filename = do_encrypt( file.filename )
            file_uuid = str( uuid4() )
            
            fp = StringIO()
            
            file.save( fp )
            file_size = fp.tell()
            
            fp.seek( 0 )
            
            if upload_type in [ 'latent_target', 'latent_incidental', 'tenprint_card_front', 'tenprint_card_back' ]:
                img = Image.open( fp )
                img_format = img.format
                width, height = img.size
                res = int( img.info[ 'dpi' ][ 0 ] )
                img = rotate_image_upon_exif( img )
                
                buff = StringIO()
                img.save( buff, format = img_format )
                buff.seek( 0 )
                file_data = buff.getvalue()
                
                if upload_type in [ 'tenprint_card_front', 'tenprint_card_back' ]:
                    create_thumbnail( file_uuid, img )
            file_data = base64.b64encode( file_data )
            
            sql = "SELECT id FROM files_type WHERE name = %s"
            upload_type_id = config.db.query( sql, ( upload_type, ) ).fetchone()[ 0 ]
            ####################################################################
            
            if upload_type == "consent_form":
                sql = "SELECT email_aes FROM submissions WHERE uuid = %s"
                email = config.db.query_fetchone( sql, ( upload_uuid, ) )[ 'email_aes' ]
                email = do_decrypt( email )
                sql = "SELECT username, email FROM users WHERE type = 2 ORDER BY id DESC"
                for username_db, email_db in config.db.query_fetchall( sql ):
                    if pbkdf2( email, email_db ).verify():
                        username = username_db
                        url_hash = hashlib.sha512( email_db ).hexdigest()
                        break
                else:
                    return jsonify( {
                        "error": True,
                        "message": "user not found"
                    } )
                # Email for the donor
                email_content = render_jinja_html( 
                    "templates/email", "donor.html",
                    username = username,
                    url = "https://icnml.unil.ch" + url_for( 'config_new_user_donor', h = url_hash )
                )
                
                msg = MIMEMultipart()
                
                msg[ "Subject" ] = "ICNML - You have been added as donor"
                msg[ "From" ] = config.sender
                msg[ "To" ] = email
                
                msg.attach( MIMEText( email_content, "html" ) )
                
                part = MIMEApplication( file_data_r, Name = "consent_form.pdf" )
                part[ "Content-Disposition" ] = "attachment; filename=consent_form.pdf"
                msg.attach( part )
                 
                try:
                    s = smtplib.SMTP( config.smtpserver )
                    s.sendmail( config.sender, [ email ], msg.as_string() )
                    s.quit()
                
                except:
                    return jsonify( {
                        "error": True,
                        "message": "Can not send the email to the user"
                    } )
                
                else:
                    # Consent form save
                    file_data = base64.b64encode( file_data )
                    file_data = gpg.encrypt( file_data, *config.gpg_key )
                    file_data = str( file_data )
                    file_data = base64.b64encode( file_data )
                    
                    sql = "INSERT INTO cf ( uuid, data, email ) VALUES ( %s, %s, %s )"
                    config.db.query( sql , ( file_uuid, file_data, pbkdf2( email, iterations = 100000 ).hash(), ) )
                    
                    sql = "UPDATE submissions SET consent_form = true WHERE uuid = %s"
                    config.db.query( sql, ( upload_uuid, ) )
                    
                    config.db.commit()
                
            else:
                sql = "INSERT INTO files ( folder, creator, filename, type, format, size, width, height, resolution, uuid, data ) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )"
                data = ( upload_id, session[ 'user_id' ], filename, upload_type_id, img_format, file_size, width, height, res, file_uuid, file_data )
                config.db.query( sql, data )
                config.db.commit()
            
            return jsonify( {
                'error': False,
                'filesize': file_size,
                'uuid': file_uuid
            } )
    
    else:
        return abort( 403 )
################################################################################
Marco De Donno's avatar
Marco De Donno committed
#    Submission of a new donor
@app.route( baseurl + '/submission/new' )
def submission_new():
    return render_template( 
        "submission/new.html",
        baseurl = baseurl,
        js = config.cdnjs,
        css = config.cdncss,
        session_timeout = config.session_timeout,
        session_security_key = session.get( "session_security_key" ),
        envtype = envtype
@app.route( baseurl + '/submission/do_new', methods = [ "GET", "POST" ] )
@login_required
def submission_do_new():
    email = request.form.get( "email", False )
    email = email.lower()
        # Check for duplicate base upon the email data
        sql = "SELECT id, email_hash FROM submissions WHERE submitter_id = %s"
        r = config.db.query( sql, ( session[ 'user_id' ], ) )
        for case in r.fetchall():
            if pbkdf2( email, case[ 'email_hash' ] ).verify():
                return jsonify( {
                    'error': True,
                    'msg': "Email already used"
                } )
                
                break
Marco De Donno's avatar
Marco De Donno committed
            # Insert the new donor
            id = str( uuid4() )
            
            email_aes = do_encrypt( email )
            email_hash = pbkdf2( email, iterations = 50000 ).hash()
            
            upload_nickname = request.form.get( "upload_nickname", None )
            upload_nickname = do_encrypt( upload_nickname )
            submitter_id = session[ 'user_id' ]
            
            status = "pending"
            
            sql = "INSERT INTO submissions ( uuid, email_aes, email_hash, nickname, status, submitter_id ) VALUES ( %s, %s, %s, %s, %s, %s ) RETURNING id"
            data = ( id, email_aes, email_hash, upload_nickname, status, submitter_id, )
            config.db.query( sql, data )
            config.db.commit()
            userid = config.db.query_fetchone( "SELECT nextval( 'username_donor_seq' ) as id" )[ 'id' ]
            username = "donor_%d" % userid
            sql = "INSERT INTO users ( username, email, type ) VALUES ( %s, %s, %s )"
            data = ( username, email_hash, 2 )
            config.db.query( sql, data )
            config.db.commit()
            
            return jsonify( {
                'error': False,
                'id': id
            } )
        
    else:
        return jsonify( {
            'error': True,
            'msg': "Email not provided"
        } )

@app.route( baseurl + '/submission/<id>/add_files' )
def submission_upload_tplp( id ):
        sql = """
            SELECT email_aes as email, nickname, created_time, consent_form
            FROM submissions
            WHERE submitter_id = %s AND uuid = %s
        """
        r = config.db.query( sql, ( session[ 'user_id' ], id ) )
        user = r.fetchone()
        
        if user[ 'consent_form' ]:
            for key in [ 'email', 'nickname' ]:
                user[ key ] = do_decrypt( user[ key ] )
            
            return render_template( 
                "submission/add_files.html",
                baseurl = baseurl,
                js = config.cdnjs,
                css = config.cdncss,
                session_timeout = config.session_timeout,
                upload_id = id,
                session_security_key = session.get( "session_security_key" ),
                envtype = envtype,
                **user
            )
        else:
            return redirect( url_for( 'submission_consent_form', id = id ) )
        
    except:
        return jsonify( {
            'error': True,
            'msg': "Case not found"
        } )

@app.route( baseurl + '/submission/<id>/consent_form' )
@login_required
def submission_consent_form( id ):
    sql = "SELECT email_aes as email, nickname, created_time FROM submissions WHERE submitter_id = %s AND uuid = %s"
    r = config.db.query( sql, ( session[ 'user_id' ], id ) )
    user = r.fetchone()
    
    if user != None:
        for key in [ 'email', 'nickname' ]:
            user[ key ] = do_decrypt( user[ key ] )
        
        return render_template( 
            "submission/consent_form.html",
            baseurl = baseurl,
            js = config.cdnjs,
            css = config.cdncss,
            session_timeout = config.session_timeout,
            upload_id = id,
            session_security_key = session.get( "session_security_key" ),
            envtype = envtype,
@app.route( baseurl + '/submission/<id>/set/nickname', methods = [ 'POST' ] )
@login_required
def submission_update_nickname( id ):
    nickname = request.form.get( "nickname", None )
    
    if nickname != None and len( nickname ) != 0:
        try:
            nickname = do_encrypt( nickname )
            
            sql = "UPDATE submissions SET nickname = %s WHERE uuid = %s"
            config.db.query( sql, ( nickname, id, ) )
            config.db.commit()
            
            return jsonify( {
                'error': False
            } )
        
        except:
            return jsonify( {
                'error': True,
                'message': "DB error"
            } )
    
    else:
        return jsonify( {
            'error': True,
            'message': "No new nickname in the POST request"
        } )

@app.route( baseurl + '/submission/list' )
@login_required
def submission_list():
    sql = "SELECT * FROM submissions WHERE submitter_id = %s ORDER BY created_time DESC"
    r = config.db.query( sql, ( session[ 'user_id' ], ) )
    q = r.fetchall()
    
Marco De Donno's avatar
Marco De Donno committed
    donors = []
    for donor in q:
        donors.append( {
            'id': donor.get( "id", None ),
            'email': do_decrypt( donor.get( "email_aes", None ) ),
            'nickname': do_decrypt( donor.get( "nickname", None ) ),
            'uuid': donor.get( "uuid", None )
        } )
    
    return render_template( 
        "submission/list.html",
        baseurl = baseurl,
        js = config.cdnjs,
        css = config.cdncss,
        session_timeout = config.session_timeout,
        session_security_key = session.get( "session_security_key" ),
        envtype = envtype
Marco De Donno's avatar
Marco De Donno committed
@app.route( baseurl + '/submission/<id>/latent/list' )
@app.route( baseurl + '/submission/<id>/latent/list/<ltype>' )
def submission_latent_list( id, ltype = 'all' ):
    if ltype in [ 'target', 'incidental', 'all' ]:
        sql = "SELECT id, nickname FROM submissions WHERE uuid = %s AND submitter_id = %s"
        r = config.db.query( sql, ( id, session[ 'user_id' ], ) )
        case_id, nickname = r.fetchone()
        nickname = do_decrypt( nickname )
        
        sql = """
            SELECT files.uuid, files.filename, files.size, files.creation_time
            FROM files
            LEFT JOIN files_type ON files.type = files_type.id
            WHERE folder = %s AND
        """
        if ltype == "target":
            sql += " files_type.name = 'latent_target'"
        elif ltype == "incidental":
            sql += " files_type.name = 'latent_incidental'"
        elif ltype == "all":
            sql += " ( files_type.name = 'latent_target' OR files_type.name = 'latent_incidental' )"
        
        sql += " ORDER BY files.id DESC"
        r = config.db.query( sql, ( case_id, ) )
        files = r.fetchall()
        
        for i, v in enumerate( files ):
            v[ 'filename' ] = do_decrypt( v[ 'filename' ] )
            v[ 'size' ] = round( ( float( v[ 'size' ] ) / ( 1024 * 1024 ) ) * 100 ) / 100
        
        return render_template( 
            "submission/latent_list.html",
            baseurl = baseurl,
            js = config.cdnjs,
            css = config.cdncss,
            session_timeout = config.session_timeout,
            submission_id = id,
            latent_type = ltype,
            files = files,
            nickname = nickname,
            session_security_key = session.get( "session_security_key" ),
            envtype = envtype
@app.route( baseurl + '/submission/<id>/latent/<lid>' )
@login_required
def submission_latent( id, lid ):
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    r = config.db.query( sql, ( id, ) )
    submission_id, nickname = r.fetchone()
    nickname = do_decrypt( nickname )
            files.uuid, files.filename, files.note,
            files.format, files.resolution, files.width, files.height, files.size,
            files.creation_time, files.type,
            files_type.name as file_type
        LEFT JOIN files_type ON files.type = files_type.id
    r = config.db.query( sql, ( submission_id, lid, ) )
    file = r.fetchone()
    file[ 'size' ] = round( 100 * float( file[ 'size' ] ) / ( 1024 * 1024 ) ) / 100
    file[ 'filename' ] = do_decrypt( file[ 'filename' ] )
    file[ 'note' ] = do_decrypt( file[ 'note' ] )
    file[ 'file_type' ] = file[ 'file_type' ].replace( "latent_", "" ) 
    
    return render_template( 
        "submission/latent.html",
        baseurl = baseurl,
        js = config.cdnjs,
        css = config.cdncss,
        session_timeout = config.session_timeout,
        submission_id = id,
        nickname = nickname,
        session_security_key = session.get( "session_security_key" ),
        envtype = envtype
@app.route( baseurl + '/submission/<id>/latent/<lid>/pfsp' )
@login_required
def submission_latent_pfsp( id, lid ):
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    r = config.db.query( sql, ( id, ) )
    submission_id, nickname = r.fetchone()
    nickname = do_decrypt( nickname )
    
    sql = """
        SELECT
            files.uuid, files.filename, files.note,
            files.format, files.resolution, files.width, files.height, files.size,
            files.creation_time, files.type,
            files_type.name as file_type
        
        FROM files
        LEFT JOIN files_type ON files.type = files_type.id
        WHERE
            folder = %s AND
            files.uuid = %s
    """
    
    r = config.db.query( sql, ( submission_id, lid, ) )
    file = r.fetchone()
    file[ 'size' ] = round( 100 * float( file[ 'size' ] ) / ( 1024 * 1024 ) ) / 100
    file[ 'filename' ] = do_decrypt( file[ 'filename' ] )
    file[ 'note' ] = do_decrypt( file[ 'note' ] )
    file[ 'file_type' ] = file[ 'file_type' ].replace( "latent_", "" ) 
    
    sql = "SELECT pfsp FROM latent_info WHERE uuid = %s"
    try:
        current_pfsp = config.db.query( sql, ( lid, ) ).fetchone()[ 0 ]
    except:
        current_pfsp = None
    
    for z in pfsp.zones:
        if z[ 'desc' ] == current_pfsp:
            current_pfsp = ",".join( z[ 'sel' ] )
    
    return render_template( 
        "submission/latent_pfsp.html",
        baseurl = baseurl,
        js = config.cdnjs,
        css = config.cdncss,
        session_timeout = config.session_timeout,
        submission_id = id,
        nickname = nickname,
        file = file,
        pfsp_zones = pfsp.zones,
        session_security_key = session.get( "session_security_key" ),
        envtype = envtype
@app.route( baseurl + '/submission/<id>/latent/<lid>/set/pfsp', methods = [ 'POST' ] )
@login_required
def submission_latent_pfsp_set( id, lid ):
    pfsp = request.form.get( "pfsp" )
    
    sql = "SELECT id FROM latent_info WHERE uuid = %s"
    q = config.db.query( sql, ( lid, ) ).fetchone()
    
    if q == None:
        sql = "INSERT INTO latent_info ( uuid, pfsp ) values ( %s, %s )"
        config.db.query( sql, ( lid, pfsp, ) )
    
    else:
        sql = "UPDATE latent_info SET pfsp = %s WHERE uuid = %s"
        config.db.query( sql, ( pfsp, lid, ) )
    
    config.db.commit()
    
    return jsonify( {
        'error': False
    } )

@app.route( baseurl + '/submission/<id>/latent/<lid>/delete' )
@login_required
def submission_latent_delete( id, lid ):
    sql = "SELECT id FROM submissions WHERE submitter_id = %s AND uuid = %s"
    q = config.db.query( sql, ( session[ 'user_id' ], id, ) )
    
    if q != None:
        sql = "DELETE FROM files WHERE creator = %s AND uuid = %s"
        config.db.query( sql, ( session[ 'user_id' ], lid, ) )
        config.db.commit()
        
        return jsonify( {
            'error': False
        } )
    
    else:
        return jsonify( {
            'error': True
        } )

################################################################################
#    Image processing

@app.route( baseurl + '/image/file/<id>/preview' )
@login_required
def image_file_serve( id ):
    img, _ = image_serve( "thumbnails", id )
    
    if img == None:
        img, _ = image_serve( "files", id )
        
        if img == None:
            return abort( 404 )
        
        img = create_thumbnail( id, img )
    
    buff = pil2buffer( img, "PNG" )
    return send_file( buff, mimetype = "image/png" )

@app.route( baseurl + '/image/segment/<tid>/<pc>' )
@login_required
def image_segment_serve( tid, pc ):
    img, id = image_serve( "files_segments", ( tid, pc ) )
    img = create_thumbnail( id, img )
    
    buff = pil2buffer( img, "PNG" )
    return send_file( buff, mimetype = "image/png" )

@app.route( baseurl + '/image/template/<tid>/<t>' )
@app.route( baseurl + '/image/template/<tid>/<t>/<action>' )
@login_required
def image_tp_template( tid, t, action = "full" ):
    if t in [ 'front', 'back' ]:
        img, _ = image_serve( "tenprint_cards", ( tid, t ) )
        if action == "preview":
            img.thumbnail( ( 500, 500 ) )
        
        buff = pil2buffer( img, "PNG" )
        return send_file( buff, mimetype = "image/png" )
    
    else:
        return abort( 403 )

def image_serve( db, id ):
    if db == "files_segments":
        if isinstance( id, tuple ):
            tp, pc = id
            sql = "SELECT data, uuid FROM " + db + " WHERE tenprint = %s AND pc = %s"
            p = ( tp, pc, )
        else:
            sql = "SELECT data, uuid FROM " + db + " WHERE uuid = %s"
            p = ( id, )
    
    elif db in [ "files", "thumbnails" ]:
        sql = "SELECT data, uuid FROM " + db + " WHERE uuid = %s"
        p = ( id, )
    
    elif db == "tenprint_cards":
        id, t = id
        sql = "SELECT image_" + t + ", id FROM " + db + " WHERE id = %s"
        p = ( id, )
    
    else:
        raise Exception( "table not authorized" )
    
    data = config.db.query( sql, p ).fetchone()
    if data == None:
        return None, None
    
        img, rid = data
        img = str2img( img )
        return img, rid

def str2img( data ):
    if data == None:
        return None
    
    else:
        img = base64.b64decode( data )
        buff = StringIO()
        buff.write( img )
        buff.seek( 0 )
        img = Image.open( buff )
        
        return img

Marco De Donno's avatar
Marco De Donno committed
@app.route( baseurl + '/image/file/<id>/info' )
@login_required
def img_info( id ):
    d = do_img_info( id )
    
    if d != None:
        return jsonify( d )
    else:
        return abort( 404 )

def do_img_info( id ):
    sql = "SELECT size, width, height, resolution, format FROM files WHERE uuid = %s"
    r = config.db.query( sql, ( id, ) )
    d = r.fetchone()
    
    if d != None:
        return dict( d )
    else:
        return None

def create_thumbnail( file_uuid, img ):
    img.thumbnail( ( 1000, 1000 ) )
    width, height = img.size
    file_format = img.format
    
    buff = StringIO()
    img.save( buff, format = img.format )
    img_size = buff.tell()
    buff.seek( 0 )
    
    img_data = buff.getvalue()
    img_data = base64.b64encode( img_data )
    
    sql = "INSERT INTO thumbnails ( uuid, width, height, size, format, data ) VALUES ( %s, %s, %s, %s, %s, %s )"
    data = ( file_uuid, width, height, img_size, img.format, img_data, )
    config.db.query( sql, data )
    config.db.commit()
    
Marco De Donno's avatar
Marco De Donno committed
@app.route( baseurl + '/image/segment/<id>/start' )
@login_required
def image_tenprint_segmentation( id ):
    ret = do_image_tenprint_segmentation( id )
    
    return jsonify( {
        'error': False,
        'data': ret
    } )

def do_image_tenprint_segmentation( id ):
    sql = "SELECT size, resolution, type, format, data FROM files WHERE uuid = %s"
    r = config.db.query( sql, ( id, ) )
    img = r.fetchone()
    
    res = img[ 'resolution' ]
    img_format = img[ 'format' ]
    t = {
        1: 'front',
        2: 'back'
    }[ img[ 'type' ] ]
     
    img = base64.b64decode( img[ 'data' ] )
    buff = StringIO()
    buff.write( img )
    buff.seek( 0 )
    img = Image.open( buff )
    
    sql = "SELECT template FROM file_template WHERE file = %s"
    r = config.db.query( sql, ( id, ) )
    template_id = r.fetchone()[ 'template' ]
    
    zones = get_tenprint_template_zones( template_id, t )
    
    for z in zones:
        tl_x, tl_y, br_x, br_y = map( lambda v: v * res / 2.54 , [ z[ "tl_x" ], z[ "tl_y" ], z[ "br_x" ], z[ "br_y" ] ] )
        tmp = img.crop( ( tl_x, tl_y, br_x, br_y ) )
        buff = StringIO()
        tmp.save( buff, format = img_format )
        buff.seek( 0 )
        file_data = buff.getvalue()
        file_data = base64.b64encode( file_data )
        
        sql = "SELECT id FROM files_segments WHERE tenprint = %s AND pc = %s"
        q = config.db.query( sql, ( id, z[ 'pc' ], ) ).fetchone()
        
        if q == None:
            sql = "INSERT INTO files_segments ( tenprint, uuid, pc, data ) VALUES ( %s, %s, %s, %s )"
            data = ( id, str( uuid4() ), z[ 'pc' ], file_data )
            config.db.query( sql, data )
        
        else:
            sql = "UPDATE files_segments SET data = %s WHERE tenprint = %s AND pc = %s"
            data = ( file_data, id, z[ 'pc' ] )
################################################################################
Marco De Donno's avatar
Marco De Donno committed
#    Donor tenprints
@app.route( baseurl + '/submission/<id>/tenprint/list' )
def submission_tenprint_list( id ):
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    submission_id, nickname = r.fetchone()
    nickname = do_decrypt( nickname )
    sql = """
        SELECT
            id, filename, uuid, type, creation_time
        FROM files
        WHERE folder = %s AND ( type = 1 OR type = 2 )
        ORDER BY creation_time DESC
    """
    
    r = config.db.query( sql, ( submission_id, ) )
    q = r.fetchall()
    
    tenprint_cards = {
        '1': [],
        '2': []
    }
        tenprint_cards[ str( tenprint[ 'type' ] ) ].append( {
            'id': tenprint.get( "id", None ),
            'filename': do_decrypt( tenprint.get( "filename", None ) ),
            'uuid': tenprint.get( "uuid", None ),
            'type': tenprint.get( "type", None )
        "submission/tenprint_list.html",
        baseurl = baseurl,
        js = config.cdnjs,
        css = config.cdncss,
        session_timeout = config.session_timeout,
        tenprint_cards_front = tenprint_cards[ '1' ],
        tenprint_cards_back = tenprint_cards[ '2' ],
        submission_id = id,
        session_security_key = session.get( "session_security_key" ),
        envtype = envtype
@app.route( baseurl + '/submission/<id>/tenprint/<tid>' )
def submission_tenprint( id, tid ):
    sql = "SELECT id, nickname FROM submissions WHERE uuid = %s"
    submission_id, nickname = r.fetchone()
    nickname = do_decrypt( nickname )
            files.uuid, files.filename, files.note,
            files.format, files.resolution, files.width, files.height, files.size,
            files.creation_time, files.type,
        LEFT JOIN file_template ON files.uuid = file_template.file
    r = config.db.query( sql, ( submission_id, tid, ) )
    file = r.fetchone()
    file[ 'size' ] = round( 100 * float( file[ 'size' ] ) / ( 1024 * 1024 ) ) / 100
    file[ 'filename' ] = do_decrypt( file[ 'filename' ] )
    file[ 'note' ] = do_decrypt( file[ 'note' ] )
    
    if file[ 'type' ] == 1:
        t = 'front'
    elif file[ 'type' ] == 2:
        t = 'back'
    
    ############################################################################
    
    try:
        sql = 'SELECT width, height, image_resolution FROM tenprint_cards WHERE id = %s LIMIT 1'
        r = config.db.query( sql, ( file[ 'template' ], ) )
        tmp = r.fetchone()
        
        card_info = {
            'width': int( round( float( tmp[ 'width' ] ) / 2.54 * tmp[ 'image_resolution' ] ) ),
            'height': int( round( float( tmp[ 'height' ] ) / 2.54 * tmp[ 'image_resolution' ] ) ),
            'width_cm': tmp[ 'width' ],
            'height_cm': tmp[ 'height' ]
        }
    except:
        card_info = {
            'width': 0,
            'height': 0,
            'width_cm': 0,
            'height_cm': 0
        }
    ############################################################################
    
    sql = "SELECT id, country_code, name, width, height, size_display FROM tenprint_cards ORDER BY country_code"
    tenprint_templates = config.db.query( sql ).fetchall()
    
    ############################################################################
    
    zones = get_tenprint_template_zones( file[ 'template' ], t )
    datacolumns = [ 'tl_x', 'tl_y', 'br_x', 'br_y', 'angle' ]
    
    ############################################################################