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