Commit Graph
12 Commits
Author SHA1 Message Date
Fabien Pinckaers 8ae4d92a58 [IMP] base: remove postprocessing of rendered pages
First step to stream QWeb templates: removing the two post
processing operations applied on rendered templates. This
should slightly speed up the rendering of every page.

1/ Don't remove empty lines after rendering, but fix the root
cause of: view inheritancies and QWeb compilation that don't
add extra empty lines.

2/ handle page break in the two reports that uses it, rather
than processing every view produced.

closes odoo/odoo#82244

Related: odoo/enterprise#23328
Signed-off-by: Fabien Pinckaers <fp@odoo.com>
2022-01-10 19:28:29 +00:00
Jeremy KerstenandOkan SUMER be43710ab8 [IMP] tools: xpath - support mode inner for position replace
This commit adds a new attribute mode for position 'replace' to the xpath feature.

This mode can take 2 values:

- 'outer' (default mode if not provided) that will replace the sibling target
- 'inner' that will preserve the sibling target

If base arch is:
```html
<p>
   <field name='x'>yyy</field>
</p>
```

`<field name='x' position="replace" (mode="outer")>zzz</field>`
```html
<p>
   zzz
</p>
```

`<field name='x' position="replace" mode="inner">zzz</field>`
```html
<p>
   <field name='x'>
      zzz
   </field>
</p>
```

Mode inner is useful for theme or render flat content, but not recommanded to
be used in page editable since we ignore the inherit-branding part until now.

task-2172208

closes odoo/odoo#48679

Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Co-authored-by: Okan SUMER (osu) <osu@odoo.com>
Co-authored-by: Jérémy Kersten <jke@odoo.com>
2021-07-29 07:04:55 +00:00
Julien Castiaux 5815ce7753 [FIX] base: some fixes for ir.ui.view
Task: 2463632
2021-06-11 17:09:05 +00:00
Xavier Morel 01875541b1 [CHG] core, web: deprecate t-raw
Add a big fat warning when the qweb compiler finds a `t-raw`.

`t-esc` should now be used everywhere, the use-case for `t-raw` should
be handled by converting the corresponding values to `Markup`
objects. Even though it's convenient, this constructor *should never
be made available in the qweb rendering context* (maybe that should be
checked for explicitely?).

Replace `werkzeug.escape` by `markupsafe.escape` in
`odoo.tools.html_escape`, this means the output of `html_escape` is
markup-safe.

Updated qweb to work correctly with escaping and `Markup`, amongst
other things QWeb bodies should be markup-safe internally (so that a
`t-set` value can be fed into a `t-esc`). See at the bottom for the
attributes handling as it's a bit complicated.

`to_text` needed updating: `markupsafe.Markup` is a subclass of `str`,
but `str` is not a passthrough for strings. So `Markup` instances
going through would be converted to normal `str`, losing their safety
flag. Since qweb internally uses `to_text` on pretty much
everything (in order to handle None / False), this would then cause
almost every `Markup` to get mistakenly double-escaped.

Also mark a bunch of APIs as markup-safe by default

* html_sanitize output.
* HTML fields content, sanitization is applied on intake (so stripped
  by the trip through the database) and if the field is unsanitised
  the injection is very much intentional, probably. Note: this
  includes automatically decoding bytes as a number of default values
  & computes yield bytes, which Markup will happily accept... by
  repr-ing them which is useless. This is hard to notice without `-b`.
* Script-safe json, it's rather the point (though it uses a
  non-standard escaping scheme).
* Note that `nl2br`, kinda: it should work correctly whether or not
  the input is markup-safe, this means we should not need to escape
  values fed to `nl2br`, but it doesn't hurt either.

Update some qweb field serialisations to mark their output as
markup-safe when necessary (e.g. monetary, barcode,
contact). Otherwise either using proper escaping internally or doing
nothing should do the trick.

Also update qweb to return markup-safe bytes: we want qweb to return
markup-safe contents as a common use-case is to render something with
one template, and inject its content in an other one (with Python code
inbetween, as `t-call` works a bit differently and does not go through
the external rendering interface).

However qweb returns `bytes` while `Markup` extends `str`. After a
quick experiment with changing qweb rendering to return `str` (rather
unmitigated failure I fear), it looks like the safest tack is to add a
somewhat similar bytes-based type, which decodes to a `Markup` but
keeps to bytes semantics.

For debugging and convenience reasons, MarkupSafeBytes does *not*
stringify and raises an error instead (`__repr__` works fine). This is
to avoid implicit stringifications which do the wrong thing (namely
create a string `"b'foo'"`).

Also add some configuration around BytesWarning (which still has to be
enabled at the interpreter level via `-b`, there's no way to enable it
programmatically smh), and monkeypatch `showwarning` to show warning
tracebacks, as it's common for warnings to be triggered in the bowels
of the application, and hard to relate to business logic without the
complete traceback.

`t-out`
=======

`t-esc` is a bit confusing for the new behaviour of "maybe escape
maybe not", so add a `t-out` alias with the same behaviour.

Unlike `t-raw`, `t-esc` is only soft-deprecated for now: there are
thousands of instances, so editing all the templates is not
great. Eventually we'll add a `ci/style` to prevent addition of new
ones, and eventually we might do a bulk-replace and hard-deprecate.

Attributes handling
===================

There are a few issues with respect to attributes. The first issue is
that markup-safe content is not necessarily attributes-safe
e.g. markup-safe content can contain unescaped `<` or double-quotes
while attributes can not. So we must forcefully escape the input, even
if it's supposedly markup-safe already.

This causes a problem for script-safe JSON: it's markup-safe but
really does its own thing. So instead of escaping it up-front and
wrapping it in Markup, make script-safe JSON its own type which
applies JSON-escaping *during the `__html__` call.

This way if a script-safe JSON object goes through `markupsafe.escape`
we'll apply script-safe escaping, otherwise it'll be treated as a
regular strings and eventually escaped the normal way.

A second issue was the processing of format-valued
attributes (`t-attf`): literal segments should always be markup-safe,
while non-literal may or may not be. This turns out to be an issue if
the non-literal segment *is* markup-safe: in that case when the
literal and non-literal segments get concatenated the literal segments
will get escaped, then attributes serialization will escape
them *again* leading to doubly-escaped content in attributes.

The most visible instance of this was the `snippet_options` template,
specifically:

    <t t-set="so_content_addition_selector" t-translation="off">blockquote, ...</t>
    <div id="so_content_addition"
        t-att-data-selector="so_content_addition_selector"
        t-attf-data-drop-near="p, h1, h2, h3, .row > div > img, #{so_content_addition_selector}"
        data-drop-in=".content, nav"/>

Here `so_content_addition_selector` is a qweb body therefore
markup-safe, When concatenated with the literal part of
`t-atff-data-drop-near` it would cause the HTML-escaping of that
yielding a new Markup object. Normal attributes processing would then
strip the markup flag (using `str()`) and escape it again, leading to
doubly-escaped literals.

The original hack around was to unescape() `Markup` content before
stringifying it and escaping it again, in the attribute serialization
method (`_append_attributes`).

That's pretty disgusting, after some more consideration & testing it
looks like a much better and safer fix is to ensure the
expression (non-literal) segments of format strings always result in
`str`, never `Markup`, which is easy enough: just all `str()` on the
output of strexpr. We could also have concatenated all the bits using
`''.join` instead of repeated concatenation (`+`).

Also add a check on the type of the format string for safety, I think
it should always be a proper str and the bytes thing is only when
running in py2 (where lxml uses bytestrings as a space optimization
for ascii-only values) but it should not hurt too much to perform a
single typecheck assertion on the value... instead of performing one
per literal segment.

Note: we may need to implement unescape anyway, because it's still
possible to get double-escaping with the current scheme: given an
explicitly escape-ed `foo` and `t-att-foo="foo"`, `foo` will be
re-escaped.

fixup! [CHG] core, web: deprecate t-raw
2021-04-29 05:34:19 +00:00
Martin Trigaux ba244cef01 [IMP] *: replace to new _() syntax
Using a few regex like
\((_\(.*%s.*)(\) % )([\w\[\]][\w .\[\]\(\)'"]*)\)
($1, $3))

Old syntax is still compatible but starts the migration to the new
syntax that catches error.
2020-06-18 13:03:34 +02:00
Jeremy Kersten 5198b209f5 [IMP] base: improve log for wrong xpath
Before create_multi, in case of invalid syntax used in an XPath, only
the problematic record was displayed. It was not ideal for long
definition but still usable.
Since the views are created using create_multi, the whole file content
is displayed in the error traceback, making it almost impossible to
locate on files with multiple records.

closes odoo/odoo#43590

X-original-commit: 8622469e1fdd4789cc45ed52093d0f329abca14e
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
2020-01-20 16:31:09 +00:00
Lucas Perais (lpe) e237ba26f7 [IMP]: web, tools: static inheritance do not disclose t-inherit* directives
Before this commit, when a template was inheriting from another
the template mentionned its t-inherit

This has been deemed overkill as the information is irrelevant to the caller
i.e. the caller just wants the template and doesn't care how they've been computed

After this commit, only t-name and attributes not related with inheritance
are disclosed

[FIX]: base: static inheritance propagates other attributes

When doing a inherit in primary mode, the original attributes on the root node of
the inheriting template were not propagated

After this commit they are
2019-12-04 13:06:54 +00:00
Lucas Perais (lpe) 96ab29c987 [IMP] web: template inheritance respects XPATH specs
At the conception of this feature it has been intentionally thought that
the behavior for static templates should resemble
what is done for ir.ui.view
While keeping the general previous behavior (and this is important)

A little bit of context for ir.ui.view
They are defined as XML's, but end up as python objects
Their meta-data (id, name, inheritance specs...) are thus
present in their XML definition, but end up as part of python objects members
Hence, the final, business, usable arch is free of those meta-data
and is left only with business-relevant dom nodes

The static inheritance feature was backed with those ideas
but inherently encountered the issue that, for them,
the meta-data also end up in the business dom, since
they are at no point considered as plain objects.

Decision has been made, back then, to exclude the root node
that holds the metadata, to be at all targeted by any XPATH

This decision is now challenged as the specs of XPATH should be respected

This commit consequently introduces the root node as any other
It can be replaced, and will be targeted by
`expr="."` or `expr="//NODE_TAG"`

The few attributes that are necessary to define them are kept across
inheritance cycles though.
2019-12-04 13:06:52 +00:00
Lucas Perais (lpe) bbbfca2d97 [FIX] web, tools: static inheritance supports replace in debug mode
Have a parent template
Have a child, in extension inherit mode of the parent
The child has a xpath like
`<xpath expr="." position="replace" />`

Before this commit, there was a crash.
That was because the Comment
(which indicates which templates modified the parent)
was taken as the replacer node
instead of the actual content of the xpath

After this commit, there is no crash, and it works as expected

closes odoo/odoo#39453

X-original-commit: 02d790e1d21b78395e489f57bf30c82f728cbee6
Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
2019-10-28 14:15:53 +00:00
Alexandre Kühn dc31884dcf [FIX] base, tools: add pre_locate to apply_inheritance_specs
Revision on https://github.com/odoo/odoo/commit/fc5878ecc668ee83cd1a374474f0b21bf6a51940

Commit above introduced server-side inheritance of static XML.
To do so, it made some changes to the way inheritance of view
templates is applied, such as moving this logic outside of the record
`ir.ui.view`.

This change, however, removed the feature to overwrite these methods.
Studio did that in order to correctly apply `group_ids`[1][2].

This commit fixes the issue by introducing an optional callback
`pre_locate` as parameter of the methods `apply_inheritance_specs`.
When set, this function is called just before locating a node during
the application of inheritance of the view. Studio can make use of
this callback to handle group_ids properly, again.

[1] https://github.com/odoo/enterprise/commit/b56101200ac35dae3eadbc0bdf4ba17461f33907
[2] https://github.com/odoo/enterprise/commit/38f7eb8153df8406498fa58eb809271db778e6d8

Related to: https://github.com/odoo/enterprise/pull/5321

Task-Id 2047439

closes odoo/odoo#36200

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
2019-08-30 11:41:12 +00:00
Christophe Simonis 140ee6b8f0 [MERGE] forward port branch saas-12.4 up to 98a55917a6 2019-08-14 16:48:10 +02:00
Lucas Perais (lpe)andJulien Mougenot fc5878ecc6 [IMP] base, web: static xml templates support serverside inheritance
QWeb templates that show up in the 'qweb' key of a module's manifest
now support server side inheritance and xpath evaluation

QWeb templates that show up in the xmlDependencies of a JS widget are not
impacted at all by theses changes, as they are served through the
Werkzeug sharedMiddleware

A similar syntax than ir.ui.view has been implemented in the QWeb templates
- each template must have a root node, whatever tag works

- the root node of a template must have a t-name containing the name of the template
The name -- without the module's name -- may contain dots pretty much anywhere
Though what is recommended is only underscores in template names

- if a template is to inherit from a parent, the root node has a t-inherit directive
containing either the full name of the template it inherits from which is module_name.template_name
or the name of the template, no module name necessary, if the parent template is in the same module

- there are 2 modes of inheriting
primary: copy the behavior of the parent into the template
extension: modifies the parent in place

Task: 1999528

closes odoo/odoo#33892

Signed-off-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>


Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Lucas Perais <lpe@odoo.com>
2019-07-24 12:21:59 +00:00