def test_mimetype_svg(self): content = base64.b64decode(SVG) mimetype = guess_mimetype(content, default='test') self.assertTrue(mimetype.startswith('image/svg')) # Tests that whitespace padded SVG are not detected as SVG mimetype = guess_mimetype(b" " + content, default='test') self.assertNotIn("svg", mimetype)
def _binary_ir_attachment_redirect_content(cls, record, default_mimetype='application/octet-stream'): # mainly used for theme images attachemnts status = content = filename = filehash = None mimetype = getattr(record, 'mimetype', False) if record.type == 'url' and record.url: # if url in in the form /somehint server locally url_match = re.match("^/(\w+)/(.+)$", record.url) if url_match: module = url_match.group(1) module_path = get_module_path(module) module_resource_path = get_resource_path(module, url_match.group(2)) if module_path and module_resource_path: module_path = os.path.join(os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath(module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, 'rb') as f: content = base64.b64encode(f.read()) status = 200 filename = os.path.basename(module_resource_path) mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) filehash = '"%s"' % hashlib.md5(pycompat.to_text(content).encode('utf-8')).hexdigest() else: status = 301 content = record.url return status, content, filename, mimetype, filehash
def _binary_record_content( self, record, field='datas', filename=None, filename_field='datas_fname', default_mimetype='application/octet-stream'): model = record._name mimetype = 'mimetype' in record and record.mimetype or False content = None filehash = 'checksum' in record and record['checksum'] or False field_def = record._fields[field] if field_def.type == 'binary' and field_def.attachment: field_attachment = self.env['ir.attachment'].search_read(domain=[('res_model', '=', model), ('res_id', '=', record.id), ('res_field', '=', field)], fields=['datas', 'mimetype', 'checksum'], limit=1) if field_attachment: mimetype = field_attachment[0]['mimetype'] content = field_attachment[0]['datas'] filehash = field_attachment[0]['checksum'] if not content: content = record[field] or '' # filename if not filename: if filename_field in record: filename = record[filename_field] else: filename = "%s-%s-%s" % (record._name, record.id, field) if not mimetype: mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) if not filehash: filehash = '"%s"' % hashlib.md5(pycompat.to_text(content).encode('utf-8')).hexdigest() status = 200 if content else 404 return status, content, filename, mimetype, filehash
def _compute_mimetype(self, values): """ compute the mimetype of the given values :param values : dict of values to create or write an ir_attachment :return mime : string indicating the mimetype, or application/octet-stream by default """ mimetype = 'application/octet-stream' if values.get('datas_fname'): mimetype = mimetypes.guess_type(values['datas_fname'])[0] if values.get('url'): mimetype = mimetypes.guess_type(values['url'])[0] if values.get('datas') and (not mimetype or mimetype == 'application/octet-stream'): mimetype = guess_mimetype(values['datas'].decode('base64')) return mimetype
def _compute_mimetype(self, values): """ compute the mimetype of the given values :param values : dict of values to create or write an ir_attachment :return mime : string indicating the mimetype, or application/octet-stream by default """ mimetype = None if values.get("mimetype"): mimetype = values["mimetype"] if not mimetype and values.get("datas_fname"): mimetype = mimetypes.guess_type(values["datas_fname"])[0] if not mimetype and values.get("url"): mimetype = mimetypes.guess_type(values["url"])[0] if values.get("datas") and (not mimetype or mimetype == "application/octet-stream"): mimetype = guess_mimetype(values["datas"].decode("base64")) return mimetype or "application/octet-stream"
def get_mimetype_and_optional_content_by_url(url): mimetype = mimetypes.guess_type(url)[0] content = None # head request for content-type header getting if not mimetype: with requests.head(url, timeout=5) as r: mimetype = getattr(r, 'headers', {}).get('Content-Type') index_content = mimetype and mimetype.split('/')[0] if not mimetype or index_content == 'text': with requests.get(url, timeout=5) as r: content = getattr(r, 'content') if not mimetype and content: mimetype = guess_mimetype(content) return mimetype, content
def add_data(self, name, data, is_image, quality=0, width=0, height=0, res_id=False, res_model='ir.ui.view', **kwargs): if is_image: format_error_msg = _("Uploaded image's format is not supported. Try with: %s", ', '.join(SUPPORTED_IMAGE_EXTENSIONS)) try: data = tools.image_process(b64decode(data), size=(width, height), quality=quality, verify_resolution=True) mimetype = guess_mimetype(data) if mimetype not in SUPPORTED_IMAGE_MIMETYPES: return {'error': format_error_msg} except UserError: # considered as an image by the browser file input, but not # recognized as such by PIL, eg .webp return {'error': format_error_msg} except ValueError as e: return {'error': e.args[0]} self._clean_context() attachment = self._attachment_create(name=name, data=data, res_id=res_id, res_model=res_model) return attachment._get_media_info()
def _check_file_requirements(self, content): content_encoded = content.encode('utf8') mimetype = guess_mimetype(base64.b64decode(content_encoded)) file_size = len(content_encoded) # Document requirements: https://docs.adyen.com/platforms/verification-checks/photo-id-check#requirements if mimetype not in ['image/jpeg', 'image/png', 'application/pdf']: raise ValidationError( _('Allowed file formats for photo IDs are jpeg, jpg, pdf or png' )) if file_size < (100 * 1024) or (file_size < 1024 and mimetype == 'application/pdf'): raise ValidationError( _('Minimum allowed size for photo ID: 1 KB for PDF, 100 KB for other formats.' )) if file_size > (4 * 1024 * 1024): raise ValidationError( _('Maximum allowed size for photo ID: 4 MB.'))
def _binary_record_content(self, record, field='datas', filename=None, filename_field='datas_fname', default_mimetype='application/octet-stream'): model = record._name mimetype = 'mimetype' in record and record.mimetype or False content = None filehash = 'checksum' in record and record['checksum'] or False field_def = record._fields[field] if field_def.type == 'binary' and field_def.attachment: field_attachment = self.env['ir.attachment'].search_read( domain=[('res_model', '=', model), ('res_id', '=', record.id), ('res_field', '=', field)], fields=['datas', 'mimetype', 'checksum'], limit=1) if field_attachment: mimetype = field_attachment[0]['mimetype'] content = field_attachment[0]['datas'] filehash = field_attachment[0]['checksum'] if not content: content = record[field] or '' # filename if not filename: if filename_field in record: filename = record[filename_field] else: filename = "%s-%s-%s" % (record._name, record.id, field) if not mimetype: mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) if not filehash: filehash = '"%s"' % hashlib.md5( pycompat.to_text(content).encode('utf-8')).hexdigest() status = 200 if content else 404 return status, content, filename, mimetype, filehash
def upload_image(self, value): mimetype = guess_mimetype(base64.b64decode(value)) cloud_url = False if not 'image' in mimetype: return cloud_url cloudinary.config( cloud_name = "phanmemqlhs", api_key = "681918874796123", api_secret = "9XXvTpVNH8ADgcw3T7XfXRfWsxE" ) encoded_string = value encoded_string = encoded_string.decode('utf-8') try: encoded_string ='data:%s;base64,'%mimetype + encoded_string rs = cloudinary.uploader.upload(encoded_string) cloud_url = rs['url'] print ('***tra ve cloud_url', cloud_url) except: pass return cloud_url
def _compute_mimetype(self, values): """ compute the mimetype of the given values :param values : dict of values to create or write an ir_attachment :return mime : string indicating the mimetype, or application/octet-stream by default """ mimetype = None if values.get('mimetype'): mimetype = values['mimetype'] if not mimetype and values.get('name'): mimetype = mimetypes.guess_type(values['name'])[0] if not mimetype and values.get('url'): mimetype = mimetypes.guess_type(values['url'])[0] if not mimetype or mimetype == 'application/octet-stream': raw = None if values.get('raw'): raw = values['raw'] elif values.get('datas'): raw = base64.b64decode(values['datas']) if raw: mimetype = guess_mimetype(raw) return mimetype or 'application/octet-stream'
def binary_to_form(self, value, **req_values): _value = { # 'value': '', # 'raw_value': '', # 'mimetype': '', } if value: if isinstance(value, werkzeug.datastructures.FileStorage): # value from request, we cannot set a value for input field value = '' mimetype = '' else: mimetype = guess_mimetype(value.decode('base64')) _value = { 'value': value, 'raw_value': value, 'mimetype': mimetype, } if mimetype.startswith('image/'): _value['value'] = 'data:{};base64,{}'.format(mimetype, value) return _value
def llenaConceptosDev(self): if(self.archivoXMLDevoluciones): f2=base64.b64decode(self.archivoXMLDevoluciones) H=StringIO(f2) mimetype = guess_mimetype(f2 or b'') if(mimetype=='image/svg+xml' or mimetype=='application/octet-stream'): tree = minidom.parse(H) conceptos=tree.getElementsByTagName("cfdi:Concepto") # _logger.info("|llenaConceptos|/|-: "+str(conceptos)) vals = [] for concepto in conceptos: unidad=concepto.getAttribute("unidad") descripcion=concepto.getAttribute("descripcion") valorUnitario=concepto.getAttribute("valorUnitario") vals.append((0, 0, { 'concepto': str(unidad), 'descripcion': str(descripcion), 'montoPagado': str(valorUnitario), 'archivoXML' : self.archivoXMLDevoluciones })) self.update({'pagos': vals})
def _get_company_image_response(self, dbname, field, placeholders, default_mimetype, company=None): placeholder = self._get_company_image_placeholder() if request.session.db: dbname = request.session.db uid = request.session.uid elif dbname is None: dbname = http.db_monodb() if not dbname: response = http.send_file(placeholder(placeholders[0])) else: uid = uid if uid else SUPERUSER_ID company_data = self._get_company_image_data(dbname, uid, field, company) if company_data and company_data[0]: image_data = base64.b64decode(company_data[0]) mimetype = guess_mimetype(image_data, default=default_mimetype) extension = mimetypes.guess_extension(mimetype) response = http.send_file( io.BytesIO(image_data), filename=('logo%s' % extension), mimetype=mimetype, mtime=company_data[1] ) else: response = http.send_file(placeholder(placeholders[1])) return response
def upload_image(instance, image_data, image_name, mime_type=False): ''' :param instance: Woo-active instance :param image_data: Image Binary Data :param image_name: Image Name :param mime_type: Image Mime Type If Image have set. :return: Its pass request of image in woo-commerce ''' if not image_data or not image_name: return {} client = base.Client('%s/xmlrpc.php' % (instance.woo_host), instance.woo_admin_username, instance.woo_admin_password, transport=SpecialTransport()) # data = base64.decodebytes(image_data) # create a temporary file, and save the image fobj = tempfile.NamedTemporaryFile(delete=False) filename = fobj.name # image=fobj.write(data) fobj.close() if not mime_type: mime_type = guess_mimetype(base64.b64decode(image_data)) # prepare metadata data = { 'name': '%s_%s.%s' % (image_name, instance.id, mime_type.split("/")[1]), 'type': mime_type, # mimetype } # read the binary file and let the XMLRPC library encode it into base64 with open(filename, 'rb') as img: data['bits'] = compat.xmlrpc_client.Binary(img.read()) res = client.call(media.UploadFile(data)) return res
def export_product_image(self, instance): """"Export Product Image to Magento""" image_stream = io.BytesIO(codecs.decode(self.image, 'base64')) image = Image.open(image_stream) filename = image.filename or ("%s.%s") % (self.default_code, image.format.lower()) vals = { "entry": { "mediaType": "image", "label": filename, "disabled": "false", "types": ["image", "small_image", "thumbnail"], "file": "string", "content": { "base64_encoded_data": self.image.decode("utf-8"), "type": guess_mimetype(base64.b64decode(self.image)), "name": filename } } } url = "%s%s%s" % ("/rest/V1/products/", self.default_code, "/media") response = instance.magento_api(url, 'POST', vals) return response
def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas', unique=False, filename=None, filename_field='datas_fname', download=False, mimetype=None, default_mimetype='application/octet-stream', access_token=None, related_id=None, access_mode=None, env=None): res_status, res_headers, res_content = super(IrHttp, cls).binary_content( xmlid=xmlid, model=model, id=id, field=field, unique=unique, filename=filename, mimetype=mimetype, filename_field=filename_field, download=download, access_mode=access_mode, related_id=related_id, default_mimetype=default_mimetype, access_token=access_token, env=env) if res_status == 200: env = env or request.env if model == "muk_dms.file" and field != 'content': obj = cls._xmlid_to_obj(env, xmlid) if xmlid else env[model].browse(int(id)) filename = obj[filename_field] if not filename and filename_field in obj else filename mimetype = filename and mimetypes.guess_type(filename)[0] if not mimetype: mimetype = guess_mimetype(base64.b64decode(res_content), default=default_mimetype) headers = [] for header in res_headers: if header[0] == 'Content-Type': headers.append(('Content-Type', mimetype)) else: headers.append(header) return res_status, headers, res_content return res_status, res_headers, res_content
def _read_file(self, options): """ Dispatch to specific method to read file content, according to its mimetype or file type :param options : dict of reading options (quoting, separator, ...) """ self.ensure_one() # guess mimetype from file content mimetype = guess_mimetype(self.file) (file_extension, handler, req) = FILE_TYPE_DICT.get(mimetype, (None, None, None)) if handler: try: return getattr(self, '_read_' + file_extension)(options) except Exception: _logger.warn("Failed to read file '%s' (transient id %d) using guessed mimetype %s", self.file_name or '<unknown>', self.id, mimetype) # try reading with user-provided mimetype (file_extension, handler, req) = FILE_TYPE_DICT.get(self.file_type, (None, None, None)) if handler: try: return getattr(self, '_read_' + file_extension)(options) except Exception: _logger.warn("Failed to read file '%s' (transient id %d) using user-provided mimetype %s", self.file_name or '<unknown>', self.id, self.file_type) # fallback on file extensions as mime types can be unreliable (e.g. # software setting incorrect mime types, or non-installed software # leading to browser not sending mime types) if self.file_name: p, ext = os.path.splitext(self.file_name) if ext in EXTENSIONS: try: return getattr(self, '_read_' + ext[1:])(options) except Exception: _logger.warn("Failed to read file '%s' (transient id %s) using file extension", self.file_name, self.id) if req: raise ImportError(_("Unable to load \"{extension}\" file: requires Python module \"{modname}\"").format(extension=file_extension, modname=req)) raise ValueError(_("Unsupported file format \"{}\", import only supports CSV, ODS, XLS and XLSX").format(self.file_type))
def import_product_and_inventory_from_file(self): self.ensure_one() if not self.import_file: raise Warning("Please select the file first.") p, ext = os.path.splitext(self.file_name) if ext[1:] not in ['xls','xlsx']: raise Warning(_("Unsupported file format \"{}\", import only supports XLS, XLSX").format(self.file_name)) # guess mimetype from file content options = {u'datetime_format': u'', u'date_format': u'', u'keep_matches': False, u'encoding': u'utf-8', u'fields': [], u'quoting': u'"', u'headers': True, u'separator': u',', u'float_thousand_separator': u',', u'float_decimal_separator': u'.', u'advanced': False} import_file = base64.b64decode(self.import_file) mimetype = guess_mimetype(import_file) (file_extension, handler, req) = FILE_TYPE_DICT.get(mimetype, (None, None, None)) rows = [] result = [] if handler: result = getattr(self, '_read_' + file_extension)(options,import_file) if not result and self.file_name: p, ext = os.path.splitext(self.file_name) if ext in EXTENSIONS: result = getattr(self, '_read_' + ext[1:])(options,import_file) if not result and req: raise Warning(_("Unable to load \"{extension}\" file: requires Python module \"{modname}\"").format(extension=file_extension, modname=req)) import_batch_obj = self.env['product.import.batch'] for sheet_name,rows in result: if rows: index = 1 for split_rows in self.split_rows(rows,500): import_batch_obj.create({'inventory_option':self.inventory_option,'name':sheet_name+' '+str(index),'sheet_name':sheet_name+' '+str(index),'state':'pending','data':json.dumps(split_rows)}) index += 1 if result: self._cr.commit() raise Warning('Please wait a moment, system will import product in batch.') #return {'type': 'ir.actions.act_window_close'} raise ValueError(_("Unsupported file format \"{}\", import only supports XLS and XLSX").format(self.file_name))
def _binary_ir_attachment_redirect_content( cls, record, default_mimetype='application/octet-stream'): # mainly used for theme images attachemnts status = content = filename = filehash = None mimetype = getattr(record, 'mimetype', False) if record.type == 'url' and record.url: # if url in in the form /somehint server locally url_match = re.match("^/(\w+)/(.+)$", record.url) if url_match: module = url_match.group(1) module_path = get_module_path(module) module_resource_path = get_resource_path( module, url_match.group(2)) if module_path and module_resource_path: module_path = os.path.join( os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath( module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, 'rb') as f: content = base64.b64encode(f.read()) status = 200 filename = os.path.basename(module_resource_path) mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) filehash = '"%s"' % hashlib.md5( pycompat.to_text(content).encode( 'utf-8')).hexdigest() if not content: status = 301 content = record.url return status, content, filename, mimetype, filehash
def test_zip(self): self.assertEqual( guess_mimetype(contents('zip')), 'application/zip' )
def _binary_record_content(self, record, field='datas', filename=None, filename_field='name', default_mimetype='application/octet-stream'): model = record._name mimetype = 'mimetype' in record and record.mimetype or False content = None filehash = 'checksum' in record and record['checksum'] or False field_def = record._fields[field] if field_def.type == 'binary' and field_def.attachment: if model != 'ir.attachment': field_attachment = self.env['ir.attachment'].sudo( ).search_read(domain=[('res_model', '=', model), ('res_id', '=', record.id), ('res_field', '=', field)], fields=['datas', 'mimetype', 'checksum'], limit=1) if field_attachment: mimetype = field_attachment[0]['mimetype'] content = field_attachment[0]['datas'] filehash = field_attachment[0]['checksum'] else: mimetype = record['mimetype'] content = record['datas'] filehash = record['checksum'] if not content: content = record[field] or '' # filename default_filename = False if not filename: if filename_field in record: filename = record[filename_field] if not filename: default_filename = True filename = "%s-%s-%s" % (record._name, record.id, field) if not mimetype: try: decoded_content = base64.b64decode(content) except base64.binascii.Error: # if we could not decode it, no need to pass it down: it would crash elsewhere... return (404, [], None) mimetype = guess_mimetype(decoded_content, default=default_mimetype) # extension _, existing_extension = os.path.splitext(filename) if not existing_extension or default_filename: extension = mimetypes.guess_extension(mimetype) if extension: filename = "%s%s" % (filename, extension) if not filehash: filehash = '"%s"' % hashlib.md5( pycompat.to_text(content).encode('utf-8')).hexdigest() status = 200 if content else 404 return status, content, filename, mimetype, filehash
def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas', unique=False, filename=None, filename_field='datas_fname', download=False, mimetype=None, default_mimetype='application/octet-stream', env=None): """ Get file, attachment or downloadable content If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the binary field (via ``default_get``), otherwise fetches the field for that precise record. :param str xmlid: xmlid of the record :param str model: name of the model to fetch the binary from :param int id: id of the record from which to fetch the binary :param str field: binary field :param bool unique: add a max-age for the cache control :param str filename: choose a filename :param str filename_field: if not create an filename with model-id-field :param bool download: apply headers to download the file :param str mimetype: mintype of the field (for headers) :param str default_mimetype: default mintype if no mintype found :param Environment env: by default use request.env :returns: (status, headers, content) """ env = env or request.env # get object and content obj = None if xmlid: obj = env.ref(xmlid, False) elif id and model in env.registry: obj = env[model].browse(int(id)) # obj exists if not obj or not obj.exists() or field not in obj: return (404, [], None) # check read access try: last_update = obj['__last_update'] except AccessError: return (403, [], None) status, headers, content = None, [], None # attachment by url check module_resource_path = None if model == 'ir.attachment' and obj.type == 'url' and obj.url: url_match = re.match("^/(\w+)/(.+)$", obj.url) if url_match: module = url_match.group(1) module_path = get_module_path(module) module_resource_path = get_resource_path(module, url_match.group(2)) if module_path and module_resource_path: module_path = os.path.join(os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath(module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, 'rb') as f: content = base64.b64encode(f.read()) last_update = pycompat.text_type(os.path.getmtime(module_resource_path)) if not module_resource_path: module_resource_path = obj.url if not content: status = 301 content = module_resource_path else: content = obj[field] or '' # filename if not filename: if filename_field in obj: filename = obj[filename_field] elif module_resource_path: filename = os.path.basename(module_resource_path) else: filename = "%s-%s-%s" % (obj._name, obj.id, field) # mimetype mimetype = 'mimetype' in obj and obj.mimetype or False if not mimetype: if filename: mimetype = mimetypes.guess_type(filename)[0] if not mimetype and getattr(env[model]._fields[field], 'attachment', False): # for binary fields, fetch the ir_attachement for mimetype check attach_mimetype = env['ir.attachment'].search_read(domain=[('res_model', '=', model), ('res_id', '=', id), ('res_field', '=', field)], fields=['mimetype'], limit=1) mimetype = attach_mimetype and attach_mimetype[0]['mimetype'] if not mimetype: mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')] # cache etag = bool(request) and request.httprequest.headers.get('If-None-Match') retag = '"%s"' % hashlib.md5(last_update.encode('utf-8')).hexdigest() status = status or (304 if etag == retag else 200) headers.append(('ETag', retag)) headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0))) # content-disposition default name if download: headers.append(('Content-Disposition', cls.content_disposition(filename))) return (status, headers, content)
def test_mimetype_jpg(self): content = base64.b64decode(JPG) mimetype = guess_mimetype(content, default='test') self.assertEqual(mimetype, 'image/jpeg')
def test_mimetype_gif(self): content = base64.b64decode(GIF) mimetype = guess_mimetype(content, default='test') self.assertEqual(mimetype, 'image/gif')
def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas', unique=False, filename=None, filename_field='datas_fname', download=False, mimetype=None, default_mimetype='application/octet-stream', env=None): """ Get file, attachment or downloadable content If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the binary field (via ``default_get``), otherwise fetches the field for that precise record. :param str xmlid: xmlid of the record :param str model: name of the model to fetch the binary from :param int id: id of the record from which to fetch the binary :param str field: binary field :param bool unique: add a max-age for the cache control :param str filename: choose a filename :param str filename_field: if not create an filename with model-id-field :param bool download: apply headers to download the file :param str mimetype: mintype of the field (for headers) :param str default_mimetype: default mintype if no mintype found :param Environment env: by default use request.env :returns: (status, headers, content) """ env = env or request.env # get object and content obj = None if xmlid: obj = env.ref(xmlid, False) elif id and model in env.registry: obj = env[model].browse(int(id)) # obj exists if not obj or not obj.exists() or field not in obj: return (404, [], None) # check read access try: last_update = obj['__last_update'] except AccessError: return (403, [], None) status, headers, content = None, [], None # attachment by url check module_resource_path = None if model == 'ir.attachment' and obj.type == 'url' and obj.url: url_match = re.match(r"^/(\w+)/(.+)$", obj.url) if url_match: module = url_match.group(1) module_path = get_module_path(module) module_resource_path = get_resource_path( module, url_match.group(2)) if module_path and module_resource_path: module_path = os.path.join( os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath( module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, 'rb') as f: content = base64.b64encode(f.read()) last_update = str( os.path.getmtime(module_resource_path)) if not module_resource_path: module_resource_path = obj.url if not content: status = 301 content = module_resource_path else: # begin redefined part of original binary_content of odoo/base/addons/ir/ir_http is_attachment = env[model]._fields[field].attachment if is_attachment: domain = [ ('res_model', '=', model), ('res_field', '=', field), ('res_id', '=', obj.id), ('type', '=', 'url'), ] att = env['ir.attachment'].sudo().search(domain) if att: content = att.url status = 301 if not content: content = obj[field] or '' # end redefined part of original binary_content # filename if not filename: if filename_field in obj: filename = obj[filename_field] elif module_resource_path: filename = os.path.basename(module_resource_path) else: filename = "%s-%s-%s" % (obj._name, obj.id, field) # mimetype mimetype = 'mimetype' in obj and obj.mimetype or False if not mimetype: if filename: mimetype = mimetypes.guess_type(filename)[0] if not mimetype and getattr(env[model]._fields[field], 'attachment', False): # for binary fields, fetch the ir_attachement for mimetype check attach_mimetype = env['ir.attachment'].search_read( domain=[('res_model', '=', model), ('res_id', '=', id), ('res_field', '=', field)], fields=['mimetype'], limit=1) mimetype = attach_mimetype and attach_mimetype[0]['mimetype'] if not mimetype: mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')] # cache etag = hasattr( request, 'httprequest') and request.httprequest.headers.get('If-None-Match') retag = '"%s"' % hashlib.md5(last_update).hexdigest() status = status or (304 if etag == retag else 200) headers.append(('ETag', retag)) headers.append( ('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0))) # content-disposition default name if download: headers.append( ('Content-Disposition', cls.content_disposition(filename))) return (status, headers, content)
def export_direct_in_woo(self, product_templates): """ Creates new product or updates existing product in Woo layer. @author: Haresh Mori on Date 14-Apr-2020. """ woo_template_id = False woo_template_obj = self.env["woo.product.template.ept"] woo_product_obj = self.env["woo.product.product.ept"] woo_product_image_obj = self.env["woo.product.image.ept"] woo_category_dict = {} variants = product_templates.product_variant_ids woo_instance = self.woo_instance_id for variant in variants: if not variant.default_code: continue product_template = variant.product_tmpl_id if product_template.attribute_line_ids and len( product_template.attribute_line_ids.filtered( lambda x: x.attribute_id.create_variant == "always") ) > 0: product_type = 'variable' else: product_type = 'simple' woo_template = woo_template_obj.search([ ("woo_instance_id", "=", woo_instance.id), ("product_tmpl_id", "=", product_template.id) ]) woo_product_template_vals = ({ 'product_tmpl_id': product_template.id, 'woo_instance_id': woo_instance.id, 'name': product_template.name, 'woo_product_type': product_type }) if self.env["ir.config_parameter"].sudo().get_param( "woo_commerce_ept.set_sales_description"): woo_product_template_vals.update({ "woo_description": product_template.description_sale, "woo_short_description": product_template.description }) if product_template.categ_id: woo_category_dict = self.create_categ_in_woo( product_template.categ_id, woo_instance.id, woo_category_dict) # create category woo_categ_id = self.update_category_info( product_template.categ_id, woo_instance.id) woo_categ_ids = [(6, 0, woo_categ_id.ids)] woo_product_template_vals.update( {'woo_categ_ids': woo_categ_ids}) if not woo_template: woo_template = woo_template_obj.create( woo_product_template_vals) woo_template_id = woo_template.id else: if woo_template_id != woo_template.id: woo_template.write(woo_product_template_vals) woo_template_id = woo_template.id # For adding all odoo images into Woo layer. woo_product_image_list = [] product_template = woo_template.product_tmpl_id for odoo_image in product_template.ept_image_ids.filtered( lambda x: not x.product_id): woo_product_image = woo_product_image_obj.search_read( [("woo_template_id", "=", woo_template_id), ("odoo_image_id", "=", odoo_image.id)], ["id"]) if woo_product_image: mimetype = guess_mimetype( base64.b64decode(woo_product_image.image)) woo_product_image.write({'image_mime_type': mimetype}) if not woo_product_image: mimetype = guess_mimetype( base64.b64decode(odoo_image.image)) woo_product_image_list.append({ "odoo_image_id": odoo_image.id, "woo_template_id": woo_template_id, "image_mime_type": mimetype }) if woo_product_image_list: woo_product_image_obj.create(woo_product_image_list) woo_variant = woo_product_obj.search([ ('woo_instance_id', '=', woo_instance.id), ('product_id', '=', variant.id), ('woo_template_id', '=', woo_template.id) ]) woo_variant_vals = ({ 'woo_instance_id': woo_instance.id, 'product_id': variant.id, 'woo_template_id': woo_template.id, 'default_code': variant.default_code, 'name': variant.name, }) if not woo_variant: woo_variant = woo_product_obj.create(woo_variant_vals) else: woo_variant.write(woo_variant_vals) # For adding all odoo images into Woo layer. product_id = woo_variant.product_id odoo_image = product_id.ept_image_ids if odoo_image: woo_product_image = woo_product_image_obj.search_read( [("woo_template_id", "=", woo_template_id), ("woo_variant_id", "=", woo_variant.id), ("odoo_image_id", "=", odoo_image[0].id)], ["id"]) if woo_product_image: mimetype = guess_mimetype( base64.b64decode(woo_product_image.image)) woo_product_image.write({'image_mime_type': mimetype}) if not woo_product_image: mimetype = guess_mimetype( base64.b64decode(odoo_image[0].image)) woo_product_image_obj.create({ "odoo_image_id": odoo_image[0].id, "woo_variant_id": woo_variant.id, "woo_template_id": woo_template_id, "image_mime_type": mimetype }) # pricelist_item = self.env['product.pricelist.item'].search( # [('pricelist_id', '=', woo_instance.woo_pricelist_id.id), # ('product_id', '=', variant.id)], limit=1) # # price = woo_variant.product_id.lst_price # if not pricelist_item: # woo_instance.woo_pricelist_id.write({ # 'item_ids': [(0, 0, { # 'applied_on': '0_product_variant', # 'product_id': variant.id, # 'compute_price': 'fixed', # 'fixed_price': price # })] # }) # else: # if pricelist_item.currency_id.id != woo_template.product_tmpl_id.company_id.currency_id.id: # instance_currency = pricelist_item.currency_id # product_company_currency = woo_template.product_tmpl_id.company_id.currency_id # price = instance_currency.compute(float(woo_variant.product_id.lst_price), # product_company_currency) # pricelist_item.write({'fixed_price': price}) return True
def test_xls(self): self.assertEqual( guess_mimetype(contents('xls')), 'application/vnd.ms-excel' )
def test_docx(self): self.assertEqual( guess_mimetype(contents('docx')), 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' )
def test_xlsx(self): self.assertEqual( guess_mimetype(contents('xlsx')), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' )
def test_odt(self): self.assertEqual( guess_mimetype(contents('odt')), 'application/vnd.oasis.opendocument.text' )
def _get_stream_from( self, record, field_name='raw', filename=None, filename_field='name', mimetype=None, default_mimetype='application/octet-stream', ): """ Create a :class:odoo.http.Stream: from a record's binary field. :param record: the record where to load the data from. :param str field_name: the binary field where to load the data from. :param Optional[str] filename: when the stream is downloaded by a browser, what filename it should have on disk. By default it is ``{model}-{id}-{field}.{extension}``, the extension is determined thanks to mimetype. :param Optional[str] filename_field: like ``filename`` but use one of the record's char field as filename. :param Optional[str] mimetype: the data mimetype to use instead of the stored one (attachment) or the one determined by magic. :param str default_mimetype: the mimetype to use when the mimetype couldn't be determined. By default it is ``application/octet-stream``. :rtype: odoo.http.Stream """ with replace_exceptions(ValueError, by=UserError(f'Expected singleton: {record}')): record.ensure_one() try: field_def = record._fields[field_name] except KeyError: raise UserError(f"Record has no field {field_name!r}.") if field_def.type != 'binary': raise UserError( f"Field {field_def!r} is type {field_def.type!r} but " f"it is only possible to stream Binary or Image fields.") stream = self._record_to_stream(record, field_name) if stream.type in ('data', 'path'): if mimetype: stream.mimetype = mimetype elif not stream.mimetype: if stream.type == 'data': head = stream.data[:1024] else: with open(stream.path, 'rb') as file: head = file.read(1024) stream.mimetype = guess_mimetype(head, default=default_mimetype) if filename: stream.download_name = filename elif filename_field in record: stream.download_name = record[filename_field] if not stream.download_name: stream.download_name = f'{record._table}-{record.id}-{field_name}' if (not get_extension(stream.download_name) and stream.mimetype != 'application/octet-stream'): stream.download_name += guess_extension(stream.mimetype) or '' return stream
def test_ods(self): self.assertEqual( guess_mimetype(contents('ods')), 'application/vnd.oasis.opendocument.spreadsheet' )
def _compute_mimetype(self): for record in self: record.res_mimetype = guess_mimetype(record.content or b"")
def import_products_from_csv(self): """ This method used to import product using csv file in Woo @param : self : It contain the current class instance @author: Dipak Gogiya @Emipro Technologies Pvt. Ltd :return: It will return the True the process is completed. """ woo_product_template = self.env['woo.product.template.ept'] woo_product_obj = self.env['woo.product.product.ept'] woo_common_log_obj = self.env["common.log.book.ept"] common_log_line_obj = self.env["common.log.lines.ept"] product_tmpl_obj = self.env['product.template'] category_obj = self.env['product.category'] woo_product_image_obj = self.env['woo.product.image.ept'] instance_id = self.woo_instance_id woo_category_dict = {} if not self.choose_file: raise Warning( _('Please Select The file for Start process The Product Sync')) if self.file_name and not self.file_name.lower().endswith('.csv'): raise Warning(_("Please provide only CSV File to Import Products")) file_data = self.read_file() woo_common_log_id = woo_common_log_obj.create({ 'type': 'import', 'module': 'woocommerce_ept', 'woo_instance_id': instance_id.id, 'active': True, }) required_field = [ 'template_name', 'product_name', 'product_default_code', 'woo_product_default_code', 'product_description', 'sale_description', 'PRODUCT_TEMPLATE_ID', 'PRODUCT_ID', 'CATEGORY_ID' ] for required_field in required_field: if not required_field in file_data.fieldnames: raise Warning( _("Required Column %s Is Not Available In CSV File") % (required_field)) row_no = 0 model_id = common_log_line_obj.get_model_id( "woo.process.import.export") woo_template_id = False for record in file_data: woo_categ_ids = [(6, 0, [])] if not record['PRODUCT_TEMPLATE_ID'] or not record['PRODUCT_ID']: message = "" if not record['PRODUCT_TEMPLATE_ID']: if message: message += ', ' message += 'Product Template Id not available in Row Number %s' % ( row_no) if not record['PRODUCT_ID']: if message: message += ', ' message += 'Product Id not available in Row Number %s' % ( row_no) vals = { 'message': message, 'model_id': model_id, 'log_line_id': woo_common_log_id.id, 'woo_instance_id': instance_id.id } common_log_line_obj.create(vals) row_no += 1 continue woo_template = woo_product_template.search([ ('woo_instance_id', '=', instance_id.id), ('product_tmpl_id', '=', int(record['PRODUCT_TEMPLATE_ID'])) ]) product_template = product_tmpl_obj.browse( int(record['PRODUCT_TEMPLATE_ID'])) if product_template.attribute_line_ids and len( product_template.attribute_line_ids.filtered( lambda x: x.attribute_id.create_variant == "always") ) > 0: product_type = 'variable' else: product_type = 'simple' categ_obj = category_obj.browse(int(record.get( 'CATEGORY_ID'))) if record.get('CATEGORY_ID') else '' woo_product_template_vals = { 'product_tmpl_id': int(record['PRODUCT_TEMPLATE_ID']), 'woo_instance_id': instance_id.id, 'name': record['template_name'], 'woo_product_type': product_type } if self.env["ir.config_parameter"].sudo().get_param( "woo_commerce_ept.set_sales_description"): woo_product_template_vals.update({ 'woo_description': record.get('sale_description'), 'woo_short_description': record.get('product_description') }) if not woo_template: if categ_obj: woo_category_dict = self.create_categ_in_woo( categ_obj, instance_id.id, woo_category_dict) # create category woo_categ_id = self.update_category_info( categ_obj, instance_id.id) woo_categ_ids = [(6, 0, woo_categ_id.ids)] woo_product_template_vals.update( {'woo_categ_ids': woo_categ_ids}) woo_template = woo_product_template.create( woo_product_template_vals) woo_template_id = woo_template.id else: if woo_template_id != woo_template.id: woo_category_dict = self.create_categ_in_woo( categ_obj, instance_id.id, woo_category_dict) # create category if categ_obj: woo_categ_id = self.update_category_info( categ_obj, instance_id.id) woo_product_template_vals.update( {'woo_categ_ids': woo_categ_ids}) woo_template.write(woo_product_template_vals) woo_template_id = woo_template.id # For adding all odoo images into Woo layer. woo_product_image_list = [] product_template = woo_template.product_tmpl_id for odoo_image in product_template.ept_image_ids.filtered( lambda x: not x.product_id): woo_product_image = woo_product_image_obj.search_read( [("woo_template_id", "=", woo_template_id), ("odoo_image_id", "=", odoo_image.id)], ["id"]) if woo_product_image: mimetype = guess_mimetype( base64.b64decode(woo_product_image.image)) woo_product_image.write({'image_mime_type': mimetype}) if not woo_product_image: mimetype = guess_mimetype( base64.b64decode(odoo_image.image)) woo_product_image_list.append({ "odoo_image_id": odoo_image.id, "woo_template_id": woo_template_id, "image_mime_type": mimetype }) if woo_product_image_list: woo_product_image_obj.create(woo_product_image_list) woo_variant = woo_product_obj.search([ ('woo_instance_id', '=', instance_id.id), ('product_id', '=', int(record['PRODUCT_ID'])), ('woo_template_id', '=', woo_template.id) ]) if not woo_variant: woo_variant_vals = ({ 'woo_instance_id': instance_id.id, 'product_id': int(record['PRODUCT_ID']), 'woo_template_id': woo_template.id, 'default_code': record['woo_product_default_code'], 'name': record['product_name'], }) woo_variant = woo_product_obj.create(woo_variant_vals) else: woo_variant_vals = ({ 'woo_instance_id': instance_id.id, 'product_id': int(record['PRODUCT_ID']), 'woo_template_id': woo_template.id, 'default_code': record['woo_product_default_code'], 'name': record['product_name'], }) woo_variant.write(woo_variant_vals) # For adding all odoo images into Woo layer. product_id = woo_variant.product_id odoo_image = product_id.ept_image_ids if odoo_image: woo_product_image = woo_product_image_obj.search_read( [("woo_template_id", "=", woo_template_id), ("woo_variant_id", "=", woo_variant.id), ("odoo_image_id", "=", odoo_image[0].id)], ["id"]) if woo_product_image: mimetype = guess_mimetype( base64.b64decode(woo_product_image.image)) woo_product_image.write({'image_mime_type': mimetype}) if not woo_product_image: mimetype = guess_mimetype( base64.b64decode(odoo_image[0].image)) woo_product_image_obj.create({ "odoo_image_id": odoo_image[0].id, "woo_variant_id": woo_variant.id, "woo_template_id": woo_template_id, "image_mime_type": mimetype }) # pricelist_item = self.env['product.pricelist.item'].search( # [('pricelist_id', '=', instance_id.woo_pricelist_id.id), # ('product_id', '=', int(record['PRODUCT_ID']))], limit=1) # # price = woo_variant.product_id.lst_price # if not pricelist_item: # instance_id.woo_pricelist_id.write({ # 'item_ids': [(0, 0, { # 'applied_on': '0_product_variant', # 'product_id': int(record['PRODUCT_ID']), # 'compute_price': 'fixed', # 'fixed_price': price # })] # }) # else: # if pricelist_item.currency_id.id != woo_template.product_tmpl_id.company_id.currency_id.id: # instance_currency = pricelist_item.currency_id # product_company_currency = woo_template.product_tmpl_id.company_id.currency_id # price = instance_currency.compute(float(woo_variant.product_id.lst_price), # product_company_currency) # pricelist_item.write({'fixed_price': price}) row_no += 1 if not woo_common_log_id.log_lines: woo_common_log_id.sudo().unlink() return True
def test_default_mimetype_empty(self): mimetype = guess_mimetype(b'') # odoo implementation returns application/octet-stream by default # if available, python-magic returns application/x-empty self.assertIn(mimetype, ('application/octet-stream', 'application/x-empty'))
def get_mimetype(record): mimetype = mimetypes.guess_type(record.name)[0] if (not mimetype or mimetype == 'application/octet-stream') and record.content: mimetype = guess_mimetype(base64.b64decode(record.content)) return mimetype or 'application/octet-stream'
def test_mimetype_octet_stream(self): mimetype = guess_mimetype(b'\0') self.assertEqual(mimetype, 'application/octet-stream')
from psycopg2 import IntegrityError from contextlib import contextmanager from io import BytesIO import pathlib import tempfile import sys from unittest.mock import patch, Mock, ANY, call from lxml import etree from odoo.modules.module import get_resource_from_path, get_resource_path from odoo.tools import config, mute_logger from odoo.tools.mimetypes import guess_mimetype from odoo.tests import common MOCK_LPR = 'MOCK_LPR' HTML_MIMETYPE = guess_mimetype(b'<html><body></body></html>') XML_MIMETYPE = guess_mimetype(b'<?xml version="1.0"/>') PDF_MIMETYPE = 'application/pdf' @common.at_install(False) @common.post_install(True) class PrinterCase(common.SavepointCase): """Base test case for printing""" @classmethod def setUpClass(cls): super().setUpClass() # Reset system default printer cls.printer_default = cls.env.ref('print.default_printer') cls.printer_default.queue = None
def test_default_mimetype(self): mimetype = guess_mimetype(b'', default='test') # if available, python-magic returns application/x-empty self.assertIn(mimetype, ('test', 'application/x-empty'))
def import_xls_file(self): self.ensure_one() if not self.import_file: raise Warning("Please select the file first.") p, ext = os.path.splitext(self.file_name) if ext[1:] not in ['xls','xlsx']: raise Warning(_("Unsupported file format \"{}\", import only supports XLS, XLSX").format(self.file_name)) ctx = self._context.copy() active_id = ctx.get('active_id') active_model = ctx.get('active_model') if not ctx.get('active_id') or not active_model: return # guess mimetype from file content options = {u'datetime_format': u'', u'date_format': u'', u'keep_matches': False, u'encoding': u'utf-8', u'fields': [], u'quoting': u'"', u'headers': True, u'separator': u',', u'float_thousand_separator': u',', u'float_decimal_separator': u'.', u'advanced': False} import_file = base64.b64decode(self.import_file) mimetype = guess_mimetype(import_file) (file_extension, handler, req) = FILE_TYPE_DICT.get(mimetype, (None, None, None)) result = [] if handler: result = getattr(self, '_read_' + file_extension)(options,import_file) if not result and self.file_name: p, ext = os.path.splitext(self.file_name) if ext in EXTENSIONS: result = getattr(self, '_read_' + ext[1:])(options,import_file) if not result and req: raise Warning(_("Unable to load \"{extension}\" file: requires Python module \"{modname}\"").format(extension=file_extension, modname=req)) employee_obj = self.env['hr.employee'] employee_not_found = [] #payslip_obj = self.env['hr.payslip'] #field_list = payslip_obj._fields.keys() #default_payslip_vals = payslip_obj.default_get(field_list) payslip_batch = self.env[active_model].browse(active_id) worked_days_lines_by_payslip = {} other_inputs = self._context.get('other_inputs') for row in result: emp_code = row[0] if not emp_code: continue employee = employee_obj.search([('no_empleado','=',emp_code)],limit=1) if not employee: employee_not_found.append(emp_code) continue payslips = payslip_batch.slip_ids.filtered(lambda x:x.employee_id.id==employee.id) if not payslips: continue description = row[1] code = row[2] vals = {} if other_inputs: vals['amount'] = row[3] else: vals.update({'number_of_days':row[3] or '0', 'number_of_hours' : row[4] or '0'}) for payslip in payslips: contract_id = payslip.contract_id and payslip.contract_id.id if not contract_id: contract_ids = payslip.get_contract(payslip.employee_id, payslip.date_from, payslip.date_to) contract_id = contract_ids and contract_ids[0] or False if not contract_id: contract_id = self.contract_id.id if payslip not in worked_days_lines_by_payslip: worked_days_lines_by_payslip[payslip] = [] if other_inputs: worked_lines = payslip.input_line_ids.filtered(lambda x:x.code==code) else: worked_lines = payslip.worked_days_line_ids.filtered(lambda x:x.code==code) if worked_lines: worked_days_lines_by_payslip[payslip] += [(1, l.id, vals) for l in worked_lines] #worked_lines.write({'number_of_days':no_of_days, 'number_of_hours' : no_of_hours}) else: if not contract_id: raise Warning("Please select Contract. No valid contract found for employee %s."%(payslip.employee_id.name)) vals.update({'name':description,'code':code,'contract_id':contract_id}) worked_days_lines_by_payslip[payslip].append((0,0, vals)) for payslip, worked_day_lines in worked_days_lines_by_payslip.items(): if not worked_day_lines: continue if other_inputs: vls = {'input_line_ids':worked_day_lines} else: vls = {'worked_days_line_ids':worked_day_lines} payslip.write(vls) return True
def test_mimetype_bmp(self): content = base64.b64decode(BMP) mimetype = guess_mimetype(content, default='test') # mimetype should match image/bmp, image/x-ms-bmp, ... self.assertRegexpMatches(mimetype, r'image/.*\bbmp')
def save_unsplash_url(self, unsplashurls=None, **kwargs): """ unsplashurls = { image_id1: { url: image_url, download_url: download_url, }, image_id2: { url: image_url, download_url: download_url, }, ..... } """ def slugify(s): ''' Keeps only alphanumeric characters, hyphens and spaces from a string. The string will also be truncated to 1024 characters max. :param s: the string to be filtered :return: the sanitized string ''' return "".join([c for c in s if c.isalnum() or c in list("- ")])[:1024] if not unsplashurls: return [] uploads = [] Attachments = request.env['ir.attachment'] query = kwargs.get('query', '') query = slugify(query) res_model = kwargs.get('res_model', 'ir.ui.view') if res_model != 'ir.ui.view' and kwargs.get('res_id'): res_id = int(kwargs['res_id']) else: res_id = None for key, value in unsplashurls.items(): url = value.get('url') try: if not url.startswith('https://images.unsplash.com/'): logger.exception("ERROR: Unknown Unsplash URL!: " + url) raise Exception(_("ERROR: Unknown Unsplash URL!")) req = requests.get(url) if req.status_code != requests.codes.ok: continue # get mime-type of image url because unsplash url dosn't contains mime-types in url image_base64 = base64.b64encode(req.content) except requests.exceptions.ConnectionError as e: logger.exception("Connection Error: " + str(e)) continue except requests.exceptions.Timeout as e: logger.exception("Timeout: " + str(e)) continue image_base64 = tools.image_process(image_base64) mimetype = guess_mimetype(base64.b64decode(image_base64)) # append image extension in name query += mimetypes.guess_extension(mimetype) or '' # /unsplash/5gR788gfd/lion url_frags = ['unsplash', key, query] attachment = Attachments.create({ 'name': query, 'url': '/' + '/'.join(url_frags), 'datas_fname': '_'.join(url_frags), 'mimetype': mimetype, 'datas': image_base64, 'public': res_model == 'ir.ui.view', 'res_id': res_id, 'res_model': res_model, }) attachment.generate_access_token() uploads.extend( attachment.read([ 'name', 'mimetype', 'checksum', 'res_id', 'res_model', 'access_token', 'url' ])) # Notifies Unsplash from an image download. (API requirement) self._notify_download(value.get('download_url')) return uploads
def test_doc(self): self.assertEqual( guess_mimetype(contents('doc')), 'application/msword' )
def _check_xlsx(self, data_file, filename): return filename and os.path.splitext(filename)[1] == '.xlsx' or \ guess_mimetype(data_file) == MIMETYPE_XLSX
def test_unknown(self): self.assertEqual( guess_mimetype(contents('csv')), 'application/octet-stream' )
def binary_content( cls, xmlid=None, model='ir.attachment', id=None, field='datas', # pylint: disable=redefined-builtin unique=False, filename=None, filename_field='datas_fname', download=False, mimetype=None, default_mimetype='application/octet-stream', access_token=None, related_id=None, access_mode=None, env=None): """ Get file, attachment or downloadable content If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the binary field (via ``default_get``), otherwise fetches the field for that precise record. :param str xmlid: xmlid of the record :param str model: name of the model to fetch the binary from :param int id: id of the record from which to fetch the binary :param str field: binary field :param bool unique: add a max-age for the cache control :param str filename: choose a filename :param str filename_field: if not create an filename with model-id-field :param bool download: apply headers to download the file :param str mimetype: mintype of the field (for headers) :param related_id: the id of another record used for custom_check :param access_mode: if truthy, will call custom_check to fetch the object that contains the binary. :param str default_mimetype: default mintype if no mintype found :param str access_token: optional token for unauthenticated access only available for ir.attachment :param Environment env: by default use request.env :returns: (status, headers, content) """ env = env or request.env # get object and content obj = None if xmlid: obj = cls._xmlid_to_obj(env, xmlid) elif id and model in env.registry: obj = env[model].browse(int(id)) # obj exists if not obj or not obj.exists() or field not in obj: return (404, [], None) # access token grant access if model == 'ir.attachment' and access_token: obj = obj.sudo() if access_mode: if not cls._check_access_mode(env, id, access_mode, model, access_token=access_token, related_id=related_id): return (403, [], None) elif not consteq(obj.access_token or u'', access_token): return (403, [], None) # check read access try: obj['__last_update'] except AccessError: return (403, [], None) status, headers, content = None, [], None # attachment by url check module_resource_path = None if model == 'ir.attachment' and obj.type == 'url' and obj.url: url_match = re.match(r"^/(\w+)/(.+)$", obj.url) if url_match: module = url_match.group(1) module_path = get_module_path(module) module_resource_path = get_resource_path( module, url_match.group(2)) if module_path and module_resource_path: module_path = os.path.join( os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath( module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, 'rb') as f: content = base64.b64encode(f.read()) # 'last_update' variable removed for lint error fix if not module_resource_path: module_resource_path = obj.url if not content: status = 301 content = module_resource_path else: # begin redefined part of original binary_content of odoo/base/addons/ir/ir_http att = env['ir.http'].find_field_attachment(env, model, field, obj) if att: content = att.url status = 301 # yelizariev: # Why do we redefine mimetype variable passed to the method? Can original mimetype has not a Non wrong value? # em230418: # in original binary_content method, mimetype is redefined without any condition: # https://github.com/odoo/odoo/blob/98a137e4b1f631a10d46b5e0cb21bb83ed7e861f/odoo/addons/base/ir/ir_http.py#L312 mimetype = att.mimetype if not content: content = obj[field] or '' # end redefined part of original binary_content # filename if not filename: if filename_field in obj: filename = obj[filename_field] elif module_resource_path: filename = os.path.basename(module_resource_path) else: filename = "%s-%s-%s" % (obj._name, obj.id, field) # mimetype # redefined: in the original function there is no condition if not mimetype: mimetype = 'mimetype' in obj and obj.mimetype or False if not mimetype: if filename: mimetype = mimetypes.guess_type(filename)[0] if not mimetype and getattr(env[model]._fields[field], 'attachment', False): # for binary fields, fetch the ir_attachement for mimetype check attach_mimetype = env['ir.attachment'].search_read( domain=[('res_model', '=', model), ('res_id', '=', id), ('res_field', '=', field)], fields=['mimetype'], limit=1) mimetype = attach_mimetype and attach_mimetype[0]['mimetype'] if not mimetype: mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')] # cache etag = bool(request) and request.httprequest.headers.get( 'If-None-Match') retag = '"%s"' % hashlib.md5( pycompat.to_text(content).encode('utf-8')).hexdigest() status = status or (304 if etag == retag else 200) headers.append(('ETag', retag)) headers.append( ('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0))) # content-disposition default name if download: headers.append( ('Content-Disposition', cls.content_disposition(filename))) return (status, headers, content)
def test_gif(self): self.assertEqual( guess_mimetype(contents('gif')), 'image/gif' )
def _check_ods(self, data_file, filename): return filename and os.path.splitext(filename)[1] == '.ods' or \ guess_mimetype(data_file) == MIMETYPE_ODS
def test_jpeg(self): self.assertEqual( guess_mimetype(contents('jpg')), 'image/jpeg' )