Source code for univention.lib.umc_module

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Univention common Python library with
helper functions for MIME type handling.
"""
# Copyright 2013-2022 Univention GmbH
#
# https://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <https://www.gnu.org/licenses/>.

import bz2
import zlib
from PIL import Image
import io
import magic
from typing import Any, Callable, Optional, Tuple  # noqa: F401

MIME_TYPE = magic.open(magic.MAGIC_MIME_TYPE)
MIME_TYPE.load()
MIME_DESCRIPTION = magic.open(magic.MAGIC_NONE)
MIME_DESCRIPTION.load()

UMC_ICON_BASEDIR = "/usr/share/univention-management-console-frontend/js/dijit/themes/umc/icons"

compression_mime_type_handlers = {
	"application/x-gzip": lambda x: zlib.decompress(x, 16 + zlib.MAX_WBITS),
	#"application/gzip": lambda x: zlib.decompress(x, 16 + zlib.MAX_WBITS),  # TODO: enable Bug #51594
	"application/x-bzip2": bz2.decompress,
	"application/bzip2": bz2.decompress,
}


[docs]def get_mime_type(data): # type: (bytes) -> str """ Guess |MIME| type of data. :param bytes data: Some data. :returns: The |MIME| type string. :rtype: str """ return MIME_TYPE.buffer(data)
[docs]def get_mime_description(data): # type: (bytes) -> str """ Guess type of data silimar to :command:`file`. :param bytes data: Some data. :returns: A descriptive string. :rtype: str """ return MIME_DESCRIPTION.buffer(data)
[docs]def compression_mime_type_of_buffer(data): # type: (bytes) -> Tuple[str, Callable[[Any], bytes]] """ Guess |MIME| type of compressed data. :param bytes data: Some compressed data. :returns: A 2-tuple (mime_type, uncompress_function). :rtype: tuple[str, str] :raises univention.admin.uexceptions.valueError: if the compression format is not recognized. """ mime_type = get_mime_type(data) if mime_type in compression_mime_type_handlers: return (mime_type, compression_mime_type_handlers[mime_type]) else: import univention.admin.uexceptions raise univention.admin.uexceptions.valueError("Not a supported compression format: %s" % (mime_type,))
[docs]def uncompress_buffer(data): # type: (bytes) -> Tuple[Optional[str], bytes] """ Return uncompressed data and its |MIME| type. :param bytes data: Some compressed data. :returns: A 2-tuple (mime_type, uncompressed_data). On errors `mime_type` is `None` and `uncompressed_data` is `data`. :rtype: tuple[str, bytes] """ import univention.admin.uexceptions try: (mime_type, compression_mime_type_handler) = compression_mime_type_of_buffer(data) return (mime_type, compression_mime_type_handler(data)) except univention.admin.uexceptions.valueError: return (None, data)
[docs]def uncompress_file(filename): # type: (str) -> Tuple[Optional[str], bytes] """ Return uncompressed file content and its |MIME| type. :param str filename: The name of the file. :returns: A 2-tuple (mime_type, uncompressed_data). On errors `mime_type` is `None` and `uncompressed_data` is `data`. :rtype: tuple[str, bytes] """ with open(filename, 'rb') as f: return uncompress_buffer(f.read())
[docs]def image_mime_type_of_buffer(data): # type: (bytes) -> str """ Guess |MIME| type of image. :param bytes data: Some image data. :returns: The |MIME| type string. :rtype: str :raises univention.admin.uexceptions.valueError: if the image format is not supported. """ mime_type = get_mime_type(data) if mime_type in ('image/jpeg', 'image/png', 'image/svg+xml', 'application/x-gzip'): return mime_type else: import univention.admin.uexceptions raise univention.admin.uexceptions.valueError("Not a supported image format: %s" % (mime_type,))
[docs]def imagedimensions_of_buffer(data): # type: (bytes) -> Tuple[int, int] """ Return image dimension of image. :param bytes data: Some image data. :returns: A 2-tuple (width, height) :rtype: tuple[int, int] """ fp = io.BytesIO(data) im = Image.open(fp) return im.size
[docs]def imagecategory_of_buffer(data): # type: (bytes) -> Optional[Tuple[str, Optional[str], str]] """ Return |MIME| types and size information for image. :strparam bytes data: Some (compressed) image data. :returns: a 3-tuple (image_mime_type, compression_mime_type, dimension) where `dimension` is `{width}x{height}` or `scalable`. `None` if the format is not recognized. :rtype: tuple[str, str, str] """ (compression_mime_type, uncompressed_data) = uncompress_buffer(data) mime_type = image_mime_type_of_buffer(uncompressed_data) if mime_type in ('image/jpeg', 'image/png'): return (mime_type, compression_mime_type, "%sx%s" % imagedimensions_of_buffer(uncompressed_data)) elif mime_type in ('image/svg+xml', 'application/x-gzip'): return (mime_type, compression_mime_type, "scalable")
[docs]def default_filename_suffix_for_mime_type(mime_type, compression_mime_type): # type: (str, str) -> Optional[str] """ Return default file name suffix for image. :param str mime_type: The |MIME| type of the image. :param str compression_mime_type: The |MIME| type of the compression. :returns: A suffix string or `None` if the image format is not supported. :rytpe: str """ if mime_type == 'image/svg+xml': if not compression_mime_type: return '.svg' elif compression_mime_type == 'application/x-gzip': return '.svgz' elif mime_type == 'image/png': return '.png' elif mime_type == 'image/jpeg': return '.jpg' return None