Esempio n. 1
0
def url_for(path_or_uri, lang=None):
    current_path = request.httprequest.path  # should already be text
    location = pycompat.to_text(path_or_uri).strip()
    force_lang = lang is not None
    url = werkzeug.urls.url_parse(location)

    if not url.netloc and not url.scheme and (url.path or force_lang):
        location = werkzeug.urls.url_join(current_path, location)

        lang = pycompat.to_text(lang or request.context.get('lang') or 'en_US')
        langs = [lg[0] for lg in request.env['ir.http']._get_language_codes()]

        if (len(langs) > 1 or force_lang) and is_multilang_url(
                location, langs):
            ps = location.split(u'/')
            if ps[1] in langs:
                # Replace the language only if we explicitly provide a language to url_for
                if force_lang:
                    ps[1] = lang
                # Remove the default language unless it's explicitly provided
                elif ps[1] == request.env['ir.http']._get_default_lang().code:
                    ps.pop(1)
            # Insert the context language or the provided language
            elif lang != request.env['ir.http']._get_default_lang(
            ).code or force_lang:
                ps.insert(1, lang)
            location = u'/'.join(ps)

    return location
Esempio n. 2
0
 def to_html(self):
     tagName, attributes, content = self.to_node()
     html = u"<%s " % tagName
     for name, value in attributes.items():
         if value or isinstance(value, string_types):
             html += u' %s="%s"' % (name, escape(to_text(value)))
     if content is None:
         html += u'/>'
     else:
         html += u'>%s</%s>' % (escape(to_text(content)), tagName)
     return html
Esempio n. 3
0
 def _compile_directive_snippet(self, el, options):
     el.set('t-call', el.attrib.pop('t-snippet'))
     View = self.env['ir.ui.view']
     view_id = View.get_view_id(el.attrib.get('t-call'))
     name = View.browse(view_id).display_name
     thumbnail = el.attrib.pop('t-thumbnail', "oe-thumbnail")
     div = u'<div name="%s" data-oe-type="snippet" data-oe-thumbnail="%s">' % (
         escape(pycompat.to_text(name)), escape(
             pycompat.to_text(thumbnail)))
     return [self._append(ast.Str(div))] + self._compile_node(
         el, options) + [self._append(ast.Str(u'</div>'))]
Esempio n. 4
0
 def _compile_directive_install(self, el, options):
     if self.user_has_groups('base.group_system'):
         module = self.env['ir.module.module'].search([
             ('name', '=', el.attrib.get('t-install'))
         ])
         if not module or module.state == 'installed':
             return []
         name = el.attrib.get('string') or 'Snippet'
         thumbnail = el.attrib.pop('t-thumbnail', 'oe-thumbnail')
         div = u'<div name="%s" data-oe-type="snippet" data-module-id="%s" data-oe-thumbnail="%s"><section/></div>' % (
             escape(pycompat.to_text(name)), module.id,
             escape(pycompat.to_text(thumbnail)))
         return [self._append(ast.Str(div))]
     else:
         return []
Esempio n. 5
0
 def to_node(self):
     if self.url:
         attr = OrderedDict([
             ["type", "text/css"],
             ["rel", "stylesheet"],
             ["href", self.html_url],
             ["media", escape(to_text(self.media)) if self.media else None]
         ])
         return ("link", attr, None)
     else:
         attr = OrderedDict([
             ["type", "text/css"],
             ["media", escape(to_text(self.media)) if self.media else None]
         ])
         return ("style", attr, self.with_header())
Esempio n. 6
0
    def value_to_html(self, value, options):
        if not value:
            return ''
        lang = self.user_lang()
        locale = babel_locale_parse(lang.code)

        if isinstance(value, pycompat.string_types):
            value = fields.Datetime.from_string(value)

        value = fields.Datetime.context_timestamp(self, value)

        if options and 'format' in options:
            pattern = options['format']
        else:
            if options and options.get('time_only'):
                strftime_pattern = (u"%s" % (lang.time_format))
            else:
                strftime_pattern = (u"%s %s" %
                                    (lang.date_format, lang.time_format))

            pattern = posix_to_ldml(strftime_pattern, locale=locale)

        if options and options.get('hide_seconds'):
            pattern = pattern.replace(":ss", "").replace(":s", "")

        return pycompat.to_text(
            babel.dates.format_datetime(value, format=pattern, locale=locale))
Esempio n. 7
0
    def value_to_html(self, value, options):
        if 'decimal_precision' in options:
            precision = self.env['decimal.precision'].search([
                ('name', '=', options['decimal_precision'])
            ]).digits
        else:
            precision = options['precision']

        if precision is None:
            fmt = '%f'
        else:
            value = float_utils.float_round(value, precision_digits=precision)
            fmt = '%.{precision}f'.format(precision=precision)

        formatted = self.user_lang().format(fmt, value, grouping=True).replace(
            r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}')

        # %f does not strip trailing zeroes. %g does but its precision causes
        # it to switch to scientific notation starting at a million *and* to
        # strip decimals. So use %f and if no precision was specified manually
        # strip trailing 0.
        if precision is None:
            formatted = re.sub(r'(?:(0|\d+?)0+)$', r'\1', formatted)

        return pycompat.to_text(formatted)
Esempio n. 8
0
    def value_to_html(self, value, options):
        """ value_to_html(value, field, options=None)

        Converts a single value to its HTML version/output
        :rtype: unicode
        """
        return html_escape(pycompat.to_text(value), options)
Esempio n. 9
0
    def attributes(self, record, field_name, options, values):
        attrs = super(DateTime, self).attributes(record, field_name, options,
                                                 values)

        if options.get('inherit_branding'):
            value = record[field_name]
            lg = self.env['res.lang']._lang_get(self.env.user.lang)
            locale = babel_locale_parse(lg.code)
            babel_format = value_format = posix_to_ldml(
                '%s %s' % (lg.date_format, lg.time_format), locale=locale)
            tz = record.env.context.get('tz') or self.env.user.tz

            if isinstance(value, pycompat.string_types):
                value = fields.Datetime.from_string(value)

            if value:
                # convert from UTC (server timezone) to user timezone
                value = fields.Datetime.context_timestamp(
                    self.with_context(tz=tz), timestamp=value)
                value_format = pycompat.to_text(
                    babel.dates.format_datetime(value,
                                                format=babel_format,
                                                locale=locale))
                value = fields.Datetime.to_string(value)

            attrs['data-oe-original'] = value
            attrs['data-oe-original-with-format'] = value_format
            attrs['data-oe-original-tz'] = tz
        return attrs
Esempio n. 10
0
    def attributes(self, record, field_name, options, values):
        attrs = super(Date, self).attributes(record, field_name, options,
                                             values)
        if options.get('inherit_branding'):
            attrs['data-oe-original'] = record[field_name]

            if record._fields[field_name].type == 'datetime':
                attrs = self.env['ir.qweb.field.datetime'].attributes(
                    record, field_name, options, values)
                attrs['data-oe-type'] = 'datetime'
                return attrs

            lg = self.env['res.lang']._lang_get(self.env.user.lang)
            locale = babel_locale_parse(lg.code)
            babel_format = value_format = posix_to_ldml(lg.date_format,
                                                        locale=locale)

            if record[field_name]:
                date = fields.Date.from_string(record[field_name])
                value_format = pycompat.to_text(
                    babel.dates.format_date(date,
                                            format=babel_format,
                                            locale=locale))

            attrs['data-oe-original-with-format'] = value_format
        return attrs
Esempio n. 11
0
def nl2br(string):
    """ Converts newlines to HTML linebreaks in ``string``. returns
    the unicode result

    :param str string:
    :rtype: unicode
    """
    return pycompat.to_text(string).replace(u'\n', u'<br>\n')
Esempio n. 12
0
    def to_html(self, sep=None, css=True, js=True, debug=False, async_load=False, url_for=(lambda url: url)):
        nodes = self.to_node(css=css, js=js, debug=debug, async_load=async_load)

        if sep is None:
            sep = u'\n            '
        response = []
        for tagName, attributes, content in nodes:
            html = u"<%s " % tagName
            for name, value in attributes.items():
                if value or isinstance(value, string_types):
                    html += u' %s="%s"' % (name, escape(to_text(value)))
            if content is None:
                html += u'/>'
            else:
                html += u'>%s</%s>' % (escape(to_text(content)), tagName)
            response.append(html)

        return sep + sep.join(response)
Esempio n. 13
0
    def record_to_html(self, record, field_name, options):
        if not getattr(record, field_name):
            return None

        view = getattr(record, field_name)

        if view._name != "ir.ui.view":
            _logger.warning("%s.%s must be a 'ir.ui.view' model." %
                            (record, field_name))
            return None

        return pycompat.to_text(
            view.render(options.get('values', {}), engine='ir.qweb'))
Esempio n. 14
0
    def value_to_html(self, value, options):
        locale = babel_locale_parse(self.user_lang().code)

        if isinstance(value, pycompat.string_types):
            value = fields.Datetime.from_string(value)

        # value should be a naive datetime in UTC. So is fields.Datetime.now()
        reference = fields.Datetime.from_string(options['now'])

        return pycompat.to_text(
            babel.dates.format_timedelta(value - reference,
                                         add_direction=True,
                                         locale=locale))
Esempio n. 15
0
def authorize(env, key, account_token, credit, dbuuid=False, description=None, credit_template=None):
    endpoint = get_endpoint(env)
    params = {
        'account_token': account_token,
        'credit': credit,
        'key': key,
        'description': description,
    }
    if dbuuid:
        params.update({'dbuuid': dbuuid})
    try:
        transaction_token = jsonrpc(endpoint + '/iap/1/authorize', params=params)
    except InsufficientCreditError as e:
        if credit_template:
            arguments = json.loads(e.args[0])
            arguments['body'] = pycompat.to_text(env['ir.qweb'].render(credit_template))
            e.args = (json.dumps(arguments),)
        raise e
    return transaction_token
Esempio n. 16
0
 def value_to_html(self, value, options):
     return pycompat.to_text(self.user_lang().format(
         '%d', value,
         grouping=True).replace(r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}'))
Esempio n. 17
0
 def _fetch_content(self):
     try:
         return super(JavascriptAsset, self)._fetch_content()
     except AssetError as e:
         return u"console.error(%s);" % json.dumps(to_text(e))
Esempio n. 18
0
    def record_to_html(self, record, field_name, options):
        assert options['tagName'] != 'img',\
            "Oddly enough, the root tag of an image field can not be img. " \
            "That is because the image goes into the tag, or it gets the " \
            "hose again."

        if options.get('qweb_img_raw_data', False):
            return super(Image, self).record_to_html(record, field_name,
                                                     options)

        aclasses = ['img', 'img-fluid'] if options.get('qweb_img_responsive',
                                                       True) else ['img']
        aclasses += options.get('class', '').split()
        classes = ' '.join(pycompat.imap(escape, aclasses))

        max_size = None
        if options.get('resize'):
            max_size = options.get('resize')
        else:
            max_width, max_height = options.get('max_width', 0), options.get(
                'max_height', 0)
            if max_width or max_height:
                max_size = '%sx%s' % (max_width, max_height)

        sha = hashlib.sha1(
            str(getattr(record,
                        '__last_update')).encode('utf-8')).hexdigest()[0:7]
        max_size = '' if max_size is None else '/%s' % max_size
        avoid_if_small = '&avoid_if_small=true' if options.get(
            'avoid_if_small') else ''
        src = '/web/image/%s/%s/%s%s?unique=%s%s' % (
            record._name, record.id, field_name, max_size, sha, avoid_if_small)

        alt = None
        if options.get('alt-field') and getattr(record, options['alt-field'],
                                                None):
            alt = escape(record[options['alt-field']])
        elif options.get('alt'):
            alt = options['alt']

        src_zoom = None
        if options.get('zoom') and getattr(record, options['zoom'], None):
            src_zoom = '/web/image/%s/%s/%s%s?unique=%s' % (
                record._name, record.id, options['zoom'], max_size, sha)
        elif options.get('zoom'):
            src_zoom = options['zoom']

        itemprop = None
        if options.get('itemprop'):
            itemprop = options['itemprop']

        atts = OrderedDict()
        atts["src"] = src
        atts["itemprop"] = itemprop
        atts["class"] = classes
        atts["style"] = options.get('style')
        atts["alt"] = alt
        atts["data-zoom"] = src_zoom and u'1' or None
        atts["data-zoom-image"] = src_zoom
        atts["data-no-post-process"] = options.get('data-no-post-process')

        atts = self.env['ir.qweb']._post_processing_att(
            'img', atts, options.get('template_options'))

        img = ['<img']
        for name, value in atts.items():
            if value:
                img.append(' ')
                img.append(escape(pycompat.to_text(name)))
                img.append('="')
                img.append(escape(pycompat.to_text(value)))
                img.append('"')
        img.append('/>')

        return u''.join(img)
Esempio n. 19
0
    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):
        """ 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:
            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
        default_filename = False
        if not filename:
            if filename_field in obj:
                filename = obj[filename_field]
            if not filename and module_resource_path:
                filename = os.path.basename(module_resource_path)
            if not filename:
                default_filename = True
                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:
                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)

        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)
Esempio n. 20
0
 def value_to_html(self, value, options):
     if not value:
         return ''
     return html_escape(
         pycompat.to_text(options['selection'][value]) or u'', options)