if field_to_other in default:
# all the fields of 'other' are given by the record: default[field_to_other],
# except the ones redefined in self
- blacklist.update(set(self.pool.get(other)._all_columns) - set(self._columns))
+ blacklist.update(set(self.pool[other]._all_columns) - set(self._columns))
else:
- blacklist_given_fields(self.pool.get(other))
+ blacklist_given_fields(self.pool[other])
+ # blacklist deprecated fields
+ for name, field in obj._columns.items():
+ if field.deprecated:
+ blacklist.add(name)
+
blacklist_given_fields(self)
- fields_to_read = [f for f in self.check_field_access_rights(cr, uid, 'read', None)
- if f not in blacklist]
- data = self.read(cr, uid, [id], fields_to_read, context=context)
+
+ fields_to_copy = dict((f,fi) for f, fi in self._all_columns.iteritems()
+ if f not in default
+ if f not in blacklist
+ if not isinstance(fi.column, fields.function))
+
+ data = self.read(cr, uid, [id], fields_to_copy.keys(), context=context)
if data:
data = data[0]
else:
- raise IndexError(_("Record #%d of %s not found, cannot copy!") % (id, self._name))
+ raise IndexError( _("Record #%d of %s not found, cannot copy!") %( id, self._name))
res = dict(default)
- for f, colinfo in self._all_columns.items():
+ for f, colinfo in fields_to_copy.iteritems():
field = colinfo.column
- if f in default:
- pass
- elif f in blacklist:
- pass
- elif isinstance(field, fields.function):
- pass
- elif field._type == 'many2one':
+ if field._type == 'many2one':
res[f] = data[f] and data[f][0]
elif field._type == 'one2many':
- other = self.pool.get(field._obj)
+ other = self.pool[field._obj]
# duplicate following the order of the ids because we'll rely on
# it later for copying translations in copy_translation()!
lines = [other.copy_data(cr, uid, line_id, context=context) for line_id in sorted(data[f])]
part = re.compile(r"(<(([^a<>]|a[^<>\s])[^<>]*)@[^<>]+>)", re.IGNORECASE | re.DOTALL)
src = part.sub(lambda m: cgi.escape(m.group(1)), src)
- # some corner cases make the parser crash (such as <SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT> in test_mail)
+ kwargs = {
+ 'page_structure': True,
+ 'style': False, # do not remove style attributes
+ 'forms': True, # remove form tags
+ 'remove_unknown_tags': False,
+ 'allow_tags': allowed_tags,
+ }
+ if etree.LXML_VERSION >= (2, 3, 1):
+ # kill_tags attribute has been added in version 2.3.1
+ kwargs.update({
+ 'kill_tags': tags_to_kill,
+ 'remove_tags': tags_to_remove,
+ })
+ else:
+ kwargs['remove_tags'] = tags_to_kill + tags_to_remove
+
+ if etree.LXML_VERSION >= (3, 1, 0):
+ kwargs.update({
+ 'safe_attrs_only': True,
+ 'safe_attrs': safe_attrs,
+ })
+ else:
+ # lxml < 3.1.0 does not allow to specify safe_attrs. We keep all attributes in order to keep "style"
+ kwargs['safe_attrs_only'] = False
+
try:
- cleaner = clean.Cleaner(page_structure=True, style=False, safe_attrs_only=False, forms=False, kill_tags=tags_to_kill, remove_tags=tags_to_remove)
+ # some corner cases make the parser crash (such as <SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT> in test_mail)
+ cleaner = clean.Cleaner(**kwargs)
cleaned = cleaner.clean_html(src)
- except TypeError:
- # lxml.clean version < 2.3.1 does not have a kill_tags attribute
- # to remove in 2014
- cleaner = clean.Cleaner(page_structure=True, style=False, safe_attrs_only=False, forms=False, remove_tags=tags_to_kill + tags_to_remove)
- cleaned = cleaner.clean_html(src)
- except Exception, e:
- if isinstance(e, etree.ParserError) and 'empty' in str(e):
- return ""
- _logger.warning('html_sanitize failed to parse %s' % (src))
- cleaned = '<p>Impossible to parse</p>'
+ except etree.ParserError, e:
+ if 'empty' in str(e):
+ return ""
+ if not silent:
+ raise
+ logger.warning('ParserError obtained when sanitizing %r', src, exc_info=True)
+ cleaned = '<p>ParserError when sanitizing</p>'
+ except Exception:
+ if not silent:
+ raise
+ logger.warning('unknown error obtained when sanitizing %r', src, exc_info=True)
+ cleaned = '<p>Unknown error when sanitizing</p>'
+
+ # MAKO compatibility: $, { and } inside quotes are escaped, preventing correct mako execution
+ cleaned = cleaned.replace('%24', '$')
+ cleaned = cleaned.replace('%7B', '{')
+ cleaned = cleaned.replace('%7D', '}')
+ cleaned = cleaned.replace('%20', ' ')
+ cleaned = cleaned.replace('%5B', '[')
+ cleaned = cleaned.replace('%5D', ']')
+
return cleaned