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())
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())