[MERGE] Forward-port of latest 7.0 bugfixes, up to rev. 5229 revid:launchpad_translat...
authorDenis Ledoux <dle@openerp.com>
Tue, 11 Feb 2014 16:39:02 +0000 (17:39 +0100)
committerDenis Ledoux <dle@openerp.com>
Tue, 11 Feb 2014 16:39:02 +0000 (17:39 +0100)
bzr revid: dle@openerp.com-20140211163902-ya86jr7lwlj1mkk9

1  2 
openerp/osv/orm.py
openerp/tools/mail.py

@@@ -5028,37 -4951,30 +5028,35 @@@ class BaseModel(object)
                  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])]
@@@ -59,47 -54,29 +59,56 @@@ def html_sanitize(src, silent=True)
      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