Пример #1
0
def fetch_file(args):
    vanity = args.vanity.split('.').pop(0)
    fobj = File.get_or_none(vanity=vanity)
    if fobj is None:
        raise UnknownFile()

    ip = request.remote_addr
    if FileView.get_or_none(file=fobj, ip=ip) is None:
        FileView.create(file=fobj, ip=ip)
        fobj.view_count += 1
        fobj.save()

    return ApiResponse(fobj.to_dict())
Пример #2
0
def create_file(args):
    fingerprint = user = None
    if args.authorization is not None:
        try:
            user = helpers.get_user(args.authorization)
        except:
            raise ApiError('Invalid Authentication')

    if args.fingerprint is not None and user is None:
        fingerprint = args.fingerprint

    min_vanity = max_vanity = args.vanity.count('/')
    for part in args.vanity.split('/'):
        minv, maxv = parse_vanity_part(part)
        min_vanity += minv
        max_vanity += maxv

    if min_vanity < MIN_VANITY_LENGTH or MAX_VANITY_LENGTH < max_vanity:
        raise ApiError(
            'Vanity has to be at least or in between {} and {} characters long'
            .format(MIN_VANITY_LENGTH, MAX_VANITY_LENGTH))

    fextension = None
    if args.type == 'multipart':
        storage = next(request.files.values(), None)
        if storage is None:
            raise ApiError('A file must be uploaded')
        if args.filename is None:
            args.filename = storage.filename
        else:
            # get original extension from uploaded file
            # just incase we generate filename in future
            if '.' in storage.filename:
                fextension = storage.filename.split('.')[-1]
        mimetype = storage.mimetype
        stream = storage.stream
        stream.seek(0, 2)
        fsize = stream.tell()
        stream.seek(0)
    elif args.type == 'raw':
        mimetype = request.mimetype
        stream = request.stream
        fsize = request.content_length
    else:
        raise ApiError('Invalid Upload Type')

    #check filesize

    fname = None
    if args.filename is None:
        fname = [generate_vanity()]
    else:
        fname = args.filename.split('.')

    if 1 < len(fname):
        # do we want to use the original filename's extension all the time?
        if fextension is None:
            fextension = fname.pop(-1)
        elif fextension.lower() == fname[-1].lower():
            fextension = fname.pop(-1)

    mime = Mimetype.get_or_none(id=mimetype)
    if mime is None:
        if fextension is None:
            raise InvalidMimetype()
        mextension = MimetypeExtension.get_or_none(
            extension=fextension.lower())
        if mextension is None:
            raise InvalidMimetype()
        # mime = mextension.mime
        mimetype = mextension.mimetype_id
    else:
        # use extension to determine filetype
        if mime.id == 'application/octet-stream':
            if fextension is not None:
                mextension = MimetypeExtension.get_or_none(
                    extension=fextension.lower())
                if mextension is not None:
                    mimetype = mextension.mimetype_id
    # check flags

    if fextension is not None:
        mextension = MimetypeExtension.get_or_none(
            mimetype=mimetype, extension=fextension.lower())
        # keep extension incase its not found
        if mextension is None:
            fname.append(fextension)
            fextension = None
        else:
            # set it to the stored version, just this or fextension.lower()
            fextension = mextension.extension

    if fextension is None:
        mextension = (MimetypeExtension.select().where(
            MimetypeExtension.mimetype == mimetype).order_by(
                MimetypeExtension.priority.desc()).limit(1).execute())
        if mextension:
            fextension = mextension[0].extension
        else:
            if mimetype.endswith('+json'):
                fextension = 'json'
            elif mimetype.endswith('+xml'):
                fextension = 'xml'

    fname = '.'.join(fname)[:256]  # just incase they send a huge text lol
    while '{random}' in fname:
        fname = fname.replace('{random}', generate_vanity(), 1)
    fname = re.sub(FILENAME_REGEX, '_', fname[:128])

    # we read the filedata now to get the hashes of it
    fdata = stream.read(fsize)

    hblake2b = hashlib.blake2b(fdata).hexdigest()
    hmd5 = hashlib.md5(fdata).hexdigest()
    hsha1 = hashlib.sha1(fdata).hexdigest()

    fid = Snowflake.generate()
    fhash = FileHash.get_or_none(blake2b=hblake2b, md5=hmd5, sha1=hsha1)
    if fhash is None:
        fhash = FileHash.create(
            id=Snowflake.generate(),
            blake2b=hblake2b,
            md5=hmd5,
            sha1=hsha1,
            size=fsize,
        )
        # upload it now
        bucket = current_app.gcs.get_bucket(current_app.config.storage_bucket)
        blob = bucket.blob('files/{}'.format(fhash.id))
        blob.upload_from_string(fdata,
                                content_type='application/octet-stream',
                                predefined_acl='publicRead')

    unique = False
    while not unique:
        fvanity = generate_vanity(args.vanity)
        unique = bool(File.get_or_none(vanity=fvanity) is None)

    fobj = File.create(
        id=fid,
        vanity=fvanity,
        mimetype=mimetype,
        extension=fextension,
        filename=fname,
        hash=fhash,
        user=user,
        fingerprint=fingerprint,
    )
    return ApiResponse(fobj.to_dict())