diff --git a/photoapp/daemon.py b/photoapp/daemon.py index eed48ce..ed63579 100644 --- a/photoapp/daemon.py +++ b/photoapp/daemon.py @@ -5,12 +5,12 @@ import cherrypy from urllib.parse import urlparse from datetime import datetime, timedelta from photoapp.thumb import ThumbGenerator -from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus, User +from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus, User, mime2ext from photoapp.dbsession import DatabaseSession from photoapp.common import pwhash from photoapp.api import PhotosApi, LibraryManager from photoapp.dbutils import SAEnginePlugin, SATool, db, get_db_engine, date_format -from photoapp.utils import mime2ext, auth, require_auth, photoset_auth_filter, slugify +from photoapp.utils import auth, require_auth, photoset_auth_filter, slugify from photoapp.storage import uri_to_storage from jinja2 import Environment, FileSystemLoader, select_autoescape from sqlalchemy import desc, func, and_, or_ diff --git a/photoapp/types.py b/photoapp/types.py index 236de0c..e5e2a92 100644 --- a/photoapp/types.py +++ b/photoapp/types.py @@ -3,31 +3,79 @@ from sqlalchemy.orm import relationship from sqlalchemy.schema import UniqueConstraint from photoapp.dbutils import Base from datetime import datetime +import enum as py_enum import uuid import enum +class fcategory(py_enum.Enum): + image = 0 + raw = 1 + video = 2 + + +ftypes = dict(jpg=dict(category=fcategory.image, + extensions={"jpeg"}, + mimes={"image/jpeg"}), + png=dict(category=fcategory.image, + mimes={"image/png"}), + gif=dict(category=fcategory.image, + mimes={"image/gif"}), + cr2=dict(category=fcategory.raw, + mimes={"image/x-canon-cr2"}), + xmp=dict(category=fcategory.raw, + mimes={"application/octet-stream-xmp"}), + psd=dict(category=fcategory.raw, + mimes={"image/vnd.adobe.photoshop"}), + mp4=dict(category=fcategory.video, + mimes={"audio/mp4", + "video/mp4"}), + mov=dict(category=fcategory.video, + mimes={"video/quicktime"})) + +# set various defaults in ftypes +# it should look like: +# ftypes = { +# : { +# "category": , # required, fcategory type +# "extensions": {<*default_extension|optional extensions>}, # optional, defaults to set([]) +# "mimes": { # required, mimes mapped to this type +# +# }, +# "type": , # optional, defaults to str("image") +# }, +# } +for extension, entry in ftypes.items(): + entry["extensions"] = entry.get("extensions", set()) | set([extension]) + entry["type"] = entry.get("type", "image") + + # file extensions we allow -known_extensions = ["jpg", "png", "cr2", "xmp", "mp4", "mov"] - -# categorizaiton of media type based on extension -regular_images = ["jpg", "png"] # we can pull metadata out of these -files_raw = ["cr2", "xmp"] # treated as black boxes -files_video = ["mp4", "mov"] - -# extensions with well-known aliases -mapped_extensions = {"jpg": {"jpeg", }} # target: aliases +known_extensions = set.union(*[i["extensions"] for i in ftypes.values()]) # allowed file types (based on magic identification) -# TODO enforce this -known_mimes = {"image/png", - "image/jpeg", - "image/gif", - "application/octet-stream-xmp", - "image/x-canon-cr2", - "audio/mp4", - "video/mp4", - "video/quicktime"} +known_mimes = set.union(*[i["mimes"] for i in ftypes.values()]) + +# categorizaiton of media type based on extension +# we can pull metadata out of these +# jpg, png, gif etc +regular_images = set([extension for extension, ftype in ftypes.items() if ftype["category"] == fcategory.image]) +# "derived" files, treated as black boxes, we can't open them because proprietary +# cr2, xmp, etc +files_raw = set([extension for extension, ftype in ftypes.items() if ftype["category"] == fcategory.raw]) +# video types +# mp4, mov, etc +files_video = set([extension for extension, ftype in ftypes.items() if ftype["category"] == fcategory.video]) + + +def mime2ext(mime): + """ + Given a mime type return the canonical file extension + """ + for ext, ftype in ftypes.items(): + if mime in ftype["mimes"]: + return ext + raise Exception(f"Unknown mime: '{mime}'") def genuuid(): @@ -35,10 +83,10 @@ def genuuid(): def map_extension(ext): - for target, aliases in mapped_extensions.items(): - if ext in aliases: - return target - return ext + for known_ext, ftype in ftypes.items(): + if ext in ftype["extensions"]: + return known_ext + raise Exception(f"Unknown extension: '{ext}'") def generate_storage_path(timestamp, sha, extension): diff --git a/photoapp/utils.py b/photoapp/utils.py index 900eade..f71ee70 100644 --- a/photoapp/utils.py +++ b/photoapp/utils.py @@ -25,20 +25,6 @@ def shasum(fpin): return sha.hexdigest() -def mime2ext(mime): - """ - Given a mime type return the canonical file extension - """ - return {"image/png": "png", - "image/jpeg": "jpg", - "image/gif": "gif", - "application/octet-stream-xmp": "xmp", - "image/x-canon-cr2": "cr2", - "audio/mp4": "mp4", - "video/mp4": "mp4", - "video/quicktime": "mov"}[mime] - - def get_extension(fname): parts = os.path.basename(fname).split(".") if len(parts) == 1: