check file contents; work with file extensions

This commit is contained in:
Jakob Ketterl 2021-02-11 00:20:17 +01:00
parent 64f827d235
commit 0fd172edc3
4 changed files with 51 additions and 25 deletions

View File

@ -24,8 +24,8 @@ $.fn.imageUpload = function() {
processData: false, processData: false,
contentType: 'application/octet-stream', contentType: 'application/octet-stream',
}).done(function(data){ }).done(function(data){
$input.val(data.uuid); $input.val(data.file);
$img.prop('src', "/imageupload?id=" + id + "&uuid=" + data.uuid); $img.prop('src', '/imageupload?file=' + data.file);
}).always(function(){ }).always(function(){
$uploadButton.prop('disabled', false); $uploadButton.prop('disabled', false);
}); });

View File

@ -78,7 +78,7 @@ class AssetsController(GzipMixin, ModificationAwareController, metaclass=ABCMeta
f.close() f.close()
if content_type is None: if content_type is None:
(content_type, encoding) = mimetypes.MimeTypes().guess_type(self.getFilePath(file)) (content_type, encoding) = mimetypes.guess_type(self.getFilePath(file))
self.send_response(data, content_type=content_type, last_modified=modified, max_age=3600) self.send_response(data, content_type=content_type, last_modified=modified, max_age=3600)
except FileNotFoundError: except FileNotFoundError:
self.send_response("file not found", code=404) self.send_response("file not found", code=404)
@ -96,9 +96,10 @@ class OwrxAssetsController(AssetsController):
} }
if file in mappedFiles and ("mapped" not in self.request.query or self.request.query["mapped"][0] != "false"): if file in mappedFiles and ("mapped" not in self.request.query or self.request.query["mapped"][0] != "false"):
config = CoreConfig() config = CoreConfig()
user_file = config.get_data_directory() + "/" + mappedFiles[file] for ext in ["png", "jpg"]:
if os.path.exists(user_file) and os.path.isfile(user_file): user_file = "{}/{}.{}".format(config.get_data_directory(), mappedFiles[file], ext)
return user_file if os.path.exists(user_file) and os.path.isfile(user_file):
return user_file
return pkg_resources.resource_filename("htdocs", file) return pkg_resources.resource_filename("htdocs", file)
@ -168,7 +169,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController):
contents = [self.getContents(f) for f in files] contents = [self.getContents(f) for f in files]
(content_type, encoding) = mimetypes.MimeTypes().guess_type(profileName) (content_type, encoding) = mimetypes.guess_type(profileName)
self.send_response("\n".join(contents), content_type=content_type, last_modified=modified, max_age=3600) self.send_response("\n".join(contents), content_type=content_type, last_modified=modified, max_age=3600)
def getContents(self, file): def getContents(self, file):

View File

@ -8,28 +8,43 @@ import json
class ImageUploadController(AuthorizationMixin, AssetsController): class ImageUploadController(AuthorizationMixin, AssetsController):
def __init__(self, handler, request, options): def __init__(self, handler, request, options):
super().__init__(handler, request, options) super().__init__(handler, request, options)
self.uuid = request.query["uuid"][0] if "uuid" in request.query else None self.file = request.query["file"][0] if "file" in request.query else None
self.id = request.query["id"][0] if "id" in request.query else None
def getFilePath(self, file=None): def getFilePath(self, file=None):
if self.uuid is None: if self.file is None:
raise FileNotFoundError("missing uuid") raise FileNotFoundError("missing filename")
if self.id is None: return "{tmp}/{file}".format(
raise FileNotFoundError("missing id")
return "{tmp}/{file}-{uuid}".format(
tmp=CoreConfig().get_temporary_directory(), tmp=CoreConfig().get_temporary_directory(),
file=self.id, file=self.file
uuid=self.uuid,
) )
def indexAction(self): def indexAction(self):
self.serve_file(None) self.serve_file(None)
def _is_png(self, contents):
return contents[0:8] == bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])
def _is_jpg(self, contents):
return contents[0:3] == bytes([0xFF, 0xD8, 0xFF])
def processImage(self): def processImage(self):
self.uuid = uuid.uuid4().hex if "id" not in self.request.query:
self.send_response("{}", content_type="application/json", code=400)
# TODO: limit file size # TODO: limit file size
# TODO: check image mime type, if possible
contents = self.get_body() contents = self.get_body()
with open(self.getFilePath(), 'wb') as f: filetype = None
f.write(contents) if self._is_png(contents):
self.send_response(json.dumps({"uuid": self.uuid}), content_type="application/json") filetype = "png"
if self._is_jpg(contents):
filetype = "jpg"
if filetype is None:
self.send_response("{}", content_type="application/json", code=400)
else:
self.file = "{id}-{uuid}.{ext}".format(
id=self.request.query["id"][0],
uuid=uuid.uuid4().hex,
ext=filetype,
)
with open(self.getFilePath(), "wb") as f:
f.write(contents)
self.send_response(json.dumps({"file": self.file}), content_type="application/json")

View File

@ -374,12 +374,22 @@ class GeneralSettingsController(AuthorizationMixin, WebpageController):
def handle_image(self, data, image_id): def handle_image(self, data, image_id):
if image_id in data: if image_id in data:
config = CoreConfig() config = CoreConfig()
data_file = config.get_data_directory() + "/" + image_id
if data[image_id] == "restore": if data[image_id] == "restore":
os.unlink(data_file) # remove all possible file extensions
for ext in ["png", "jpg"]:
try:
os.unlink("{}/{}.{}".format(config.get_data_directory(), image_id, ext))
except FileNotFoundError:
pass
elif data[image_id]: elif data[image_id]:
temporary_file = "{}/{}-{}".format(config.get_temporary_directory(), image_id, data[image_id]) if not data[image_id].startswith(image_id):
shutil.copy(temporary_file, data_file) logger.warning("invalid file name: %s", data[image_id])
else:
# get file extension (luckily, all options are three characters long)
ext = data[image_id][-3:]
data_file = "{}/{}.{}".format(config.get_data_directory(), image_id, ext)
temporary_file = "{}/{}".format(config.get_temporary_directory(), data[image_id])
shutil.copy(temporary_file, data_file)
del data[image_id] del data[image_id]
# remove any accumulated temporary files on save # remove any accumulated temporary files on save
for file in glob("{}/{}*".format(config.get_temporary_directory(), image_id)): for file in glob("{}/{}*".format(config.get_temporary_directory(), image_id)):