Exemple #1
0
    def get_user_profile_avatar(self, user_id, field='image_256', width=0, height=0, crop=False, **post):
        if field not in ('image_64', 'image_128', 'image_256'):
            return werkzeug.exceptions.Forbidden()

        can_sudo = self._check_avatar_access(user_id, **post)
        if can_sudo:
            status, headers, image_base64 = request.env['ir.http'].sudo().binary_content(
                model='res.users', id=user_id, field=field,
                default_mimetype='image/png')
        else:
            status, headers, image_base64 = request.env['ir.http'].binary_content(
                model='res.users', id=user_id, field=field,
                default_mimetype='image/png')
        if status == 301:
            return request.env['ir.http']._response_by_status(status, headers, image_base64)
        if status == 304:
            return werkzeug.wrappers.Response(status=304)

        if not image_base64:
            image_base64 = self._get_default_avatar()
            if not (width or height):
                width, height = tools.image_guess_size_from_field_name(field)

        image_base64 = tools.image_process(image_base64, size=(int(width), int(height)), crop=crop)

        content = base64.b64decode(image_base64)
        headers = http.set_safe_image_headers(headers, content)
        response = request.make_response(content, headers)
        response.status_code = status
        return response
Exemple #2
0
    def slide_get_image(self, slide_id, field='image_medium', width=0, height=0, crop=False):
        # Protect infographics by limiting access to 256px (large) images
        if field not in ('image_small', 'image_medium', 'image_large'):
            return werkzeug.exceptions.Forbidden()

        slide = request.env['slide.slide'].sudo().browse(slide_id).exists()
        if not slide:
            raise werkzeug.exceptions.NotFound()

        status, headers, image_base64 = request.env['ir.http'].sudo().binary_content(
            model='slide.slide', id=slide.id, field=field,
            default_mimetype='image/png')
        if status == 301:
            return request.env['ir.http']._response_by_status(status, headers, image_base64)
        if status == 304:
            return werkzeug.wrappers.Response(status=304)

        if not image_base64:
            image_base64 = self._get_default_avatar()
            if not (width or height):
                width, height = tools.image_guess_size_from_field_name(field)

        image_base64 = tools.image_process(image_base64, (width, height), crop=crop)

        content = base64.b64decode(image_base64)
        headers = http.set_safe_image_headers(headers, content)
        response = request.make_response(content, headers)
        response.status_code = status
        return response
Exemple #3
0
    def slide_get_image(self, slide_id, field='image_128', width=0, height=0, crop=False):
        # Protect infographics by limiting access to 256px (large) images
        if field not in ('image_128', 'image_256', 'image_512', 'image_1024', 'image_1920'):
            return werkzeug.exceptions.Forbidden()

        slide = request.env['slide.slide'].sudo().browse(slide_id).exists()
        if not slide:
            raise werkzeug.exceptions.NotFound()

        status, headers, image_base64 = request.env['ir.http'].sudo().binary_content(
            model='slide.slide', id=slide.id, field=field,
            default_mimetype='image/png')
        if status == 301:
            return request.env['ir.http']._response_by_status(status, headers, image_base64)
        if status == 304:
            return werkzeug.wrappers.Response(status=304)

        if not image_base64:
            image_base64 = self._get_default_avatar()
            if not (width or height):
                width, height = tools.image_guess_size_from_field_name(field)

        image_base64 = tools.image_process(image_base64, size=(int(width), int(height)), crop=crop)

        content = base64.b64decode(image_base64)
        headers = http.set_safe_image_headers(headers, content)
        response = request.make_response(content, headers)
        response.status_code = status
        return response
Exemple #4
0
    def _content_image(
        self,
        xmlid=None,
        model="ir.attachment",
        id=None,
        field="datas",
        filename_field="name",
        unique=None,
        filename=None,
        mimetype=None,
        download=None,
        width=0,
        height=0,
        crop=False,
        quality=0,
        access_token=None,
        placeholder="placeholder.png",
        **kwargs
    ):
        status, headers, image_base64 = request.env["ir.http"].binary_content(
            xmlid=xmlid,
            model=model,
            id=id,
            field=field,
            unique=unique,
            filename=filename,
            filename_field=filename_field,
            download=download,
            mimetype=mimetype,
            default_mimetype="image/png",
            access_token=access_token,
        )

        if status in [301, 302, 304] or (
            status != 200 and download
        ):  # em230418: added 302 only
            return request.env["ir.http"]._response_by_status(
                status, headers, image_base64
            )
        if not image_base64:
            # Since we set a placeholder for any missing image, the status must be 200. In case one
            # wants to configure a specific 404 page (e.g. though nginx), a 404 status will cause
            # troubles.
            status = 200
            image_base64 = base64.b64encode(self.placeholder(image=placeholder))
            if not (width or height):
                width, height = odoo.tools.image_guess_size_from_field_name(field)

        image_base64 = image_process(
            image_base64,
            size=(int(width), int(height)),
            crop=crop,
            quality=int(quality),
        )

        content = base64.b64decode(image_base64)
        headers = http.set_safe_image_headers(headers, content)
        response = request.make_response(content, headers)
        response.status_code = status
        return response
Exemple #5
0
    def get_user_profile_avatar(self, user_id, field='image_large', width=0, height=0, crop=False, **post):
        if field not in ('image_small', 'image_medium', 'image_large'):
            return werkzeug.exceptions.Forbidden()

        can_sudo = self._check_avatar_access(user_id, **post)
        if can_sudo:
            status, headers, image_base64 = request.env['ir.http'].sudo().binary_content(
                model='res.users', id=user_id, field=field,
                default_mimetype='image/png')
        else:
            status, headers, image_base64 = request.env['ir.http'].binary_content(
                model='res.users', id=user_id, field=field,
                default_mimetype='image/png')
        if status == 301:
            return request.env['ir.http']._response_by_status(status, headers, image_base64)
        if status == 304:
            return werkzeug.wrappers.Response(status=304)

        if not image_base64:
            image_base64 = self._get_default_avatar()
            if not (width or height):
                width, height = tools.image_guess_size_from_field_name(field)

        image_base64 = tools.image_process(image_base64, (width, height), crop=crop)

        content = base64.b64decode(image_base64)
        headers = http.set_safe_image_headers(headers, content)
        response = request.make_response(content, headers)
        response.status_code = status
        return response
Exemple #6
0
    def content_image(self,
                      id=None,
                      field='datas',
                      share_id=None,
                      width=0,
                      height=0,
                      crop=False,
                      share_token=None,
                      unique=False,
                      **kwargs):
        status, headers, image_base64 = self.binary_content(
            id=id,
            field=field,
            share_id=share_id,
            share_token=share_token,
            unique=unique)
        if status != 200:
            return request.env['ir.http']._response_by_status(
                status, headers, image_base64)

        try:
            image_base64 = image_process(image_base64,
                                         size=(int(width), int(height)),
                                         crop=crop)
        except Exception:
            return request.not_found()

        if not image_base64:
            return request.not_found()

        content = base64.b64decode(image_base64)
        headers = http.set_safe_image_headers(headers, content)
        response = request.make_response(content, headers)
        response.status_code = status
        return response
Exemple #7
0
 def _content_image_get_response(self, status, headers, image_base64, model='ir.attachment',
         field='datas', download=None, width=0, height=0, crop=False, quality=0):
     if status in [301, 304] or (status != 200 and download):
         return self._response_by_status(status, headers, image_base64)
     if not image_base64:
         placeholder_filename = False
         if model in self.env:
             placeholder_filename = self.env[model]._get_placeholder_filename(field)
         placeholder_content = self._placeholder(image=placeholder_filename)
         # Since we set a placeholder for any missing image, the status must be 200. In case one
         # wants to configure a specific 404 page (e.g. though nginx), a 404 status will cause
         # troubles.
         status = 200
         image_base64 = base64.b64encode(placeholder_content)
         if not (width or height):
             width, height = odoo.tools.image_guess_size_from_field_name(field)
     try:
         image_base64 = image_process(image_base64, size=(int(width), int(height)), crop=crop, quality=int(quality))
     except Exception:
         return request.not_found()
     content = base64.b64decode(image_base64)
     headers = http.set_safe_image_headers(headers, content)
     response = request.make_response(content, headers)
     response.status_code = status
     return response
Exemple #8
0
 def _placeholder_image_get_response(self, content):
     headers = http.set_safe_image_headers([], content)
     response = request.make_response(content, headers)
     response.status_code = 200
     return response
Exemple #9
0
 def _placeholder_image_get_response(self, placeholder_base64):
     content = base64.b64decode(placeholder_base64)
     headers = http.set_safe_image_headers([], content)
     response = request.make_response(content, headers)
     response.status_code = 200
     return response
Exemple #10
0
    def _content_image(self,
                       xmlid=None,
                       model='ir.attachment',
                       id=None,
                       field='datas',
                       filename_field='name',
                       unique=None,
                       filename=None,
                       mimetype=None,
                       download=None,
                       width=0,
                       height=0,
                       crop=False,
                       quality=0,
                       access_token=None,
                       placeholder='placeholder.png',
                       **kwargs):
        webp_support = check_webp_support(request)
        is_webp = False

        if model and model == 'ir.attachment' and id:
            attachment = request.env[model].sudo().search([('id', '=', id)])
        else:
            attachment = request.env['ir.attachment'].sudo().search(
                [('res_model', '=', model), ('res_id', '=', id),
                 ('res_field', '=', field)],
                limit=1)

        if attachment and attachment.mimetype == "image/webp":
            is_webp = True

        status, headers, image_base64 = request.env['ir.http'].binary_content(
            xmlid=xmlid,
            model=model,
            id=id,
            field=field,
            unique=unique,
            filename=filename,
            filename_field=filename_field,
            download=download,
            mimetype=mimetype,
            default_mimetype='image/png',
            access_token=access_token)

        if status in [301, 304] or (status != 200 and download):
            return request.env['ir.http']._response_by_status(
                status, headers, image_base64)
        if not image_base64:
            status = 200
            image_base64 = base64.b64encode(
                Binary().placeholder(image=placeholder))
            if not (width or height):
                width, height = odoo.tools.image_guess_size_from_field_name(
                    field)

        if not is_webp:
            image_base64 = image_process(image_base64,
                                         size=(int(width), int(height)),
                                         crop=crop,
                                         quality=quality)
        else:
            if webp_support:
                width = width or height or 0
                height = height or width or 0

                webp_data = webp.WebPData.from_buffer(
                    base64.b64decode(image_base64))
                arr = webp_data.decode()
                source_image = Image.fromarray(arr, 'RGBA')

                if width or height:
                    source_image.thumbnail((width, height))

                pic = webp.WebPPicture.from_pil(source_image)
                config = webp.WebPConfig.new(
                    preset=webp.WebPPreset.PHOTO,
                    quality=quality
                    or int(request.session.get('webp_image_quality', 95))
                    or 95)
                image_base64 = base64.b64encode(pic.encode(config).buffer())

        img_data = base64.b64decode(image_base64)
        headers = http.set_safe_image_headers(headers, img_data)

        if headers and dict(headers).get('Content-Type',
                                         '') != 'image/svg+xml':
            width = width or height or 0
            height = height or width or 0

            if webp_support:
                quality = quality or int(
                    request.session.get('webp_image_quality', 95)) or 95

                if not is_webp:
                    source_image = Image.open(
                        io.BytesIO(img_data)).convert("RGBA")
                    pic = webp.WebPPicture.from_pil(source_image)
                    config = webp.WebPConfig.new(preset=webp.WebPPreset.PHOTO,
                                                 quality=quality)
                    img_data = pic.encode(config).buffer()
            else:
                if is_webp:
                    webp_data = webp.WebPData.from_buffer(img_data)
                    arr = webp_data.decode()
                    source_image = Image.fromarray(arr, 'RGBA')

                    if width or height:
                        source_image.thumbnail((width, height))

                    convert_to_png = io.BytesIO()
                    source_image.save(convert_to_png, 'PNG')
                    img_data = convert_to_png.getvalue()

            for key, item in enumerate(headers):
                if item[0] == 'Content-Type':
                    headers[key] = ('Content-Type',
                                    webp_support and 'image/webp'
                                    or 'image/png')
                    break

        response = request.make_response(img_data, headers)
        response.status_code = status
        return response