diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 7ba775c1797..afcb7668783 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -512,14 +512,21 @@ class actions_server(osv.osv): return obj - def merge_message(self, cr, uid, keystr, action, context): + def merge_message(self, cr, uid, keystr, action, context=None): + if context is None: + context = {} logger = netsvc.Logger() def merge(match): obj_pool = self.pool.get(action.model_id.model) id = context.get('active_id') obj = obj_pool.browse(cr, uid, id) exp = str(match.group()[2:-2]).strip() - result = eval(exp, {'object':obj, 'context': context,'time':time}) + result = eval(exp, + { + 'object': obj, + 'context': dict(context), # copy context to prevent side-effects of eval + 'time': time, + }) if result in (None, False): return str("--------") return tools.ustr(result) @@ -536,13 +543,16 @@ class actions_server(osv.osv): # False : Finnished correctly # ACTION_ID : Action to launch - def run(self, cr, uid, ids, context={}): + # FIXME: refactor all the eval() calls in run()! + def run(self, cr, uid, ids, context=None): logger = netsvc.Logger() + if context is None: + context = {} for action in self.browse(cr, uid, ids, context): obj_pool = self.pool.get(action.model_id.model) obj = obj_pool.browse(cr, uid, context['active_id'], context=context) cxt = { - 'context':context, + 'context': dict(context), # copy context to prevent side-effects of eval 'object': obj, 'time':time, 'cr': cr, @@ -560,26 +570,19 @@ class actions_server(osv.osv): .read(cr, uid, action.action_id.id, context=context) if action.state=='code': - if config['server_actions_allow_code']: - localdict = { - 'self': self.pool.get(action.model_id.model), - 'context': context, - 'time': time, - 'ids': ids, - 'cr': cr, - 'uid': uid, - 'object':obj, - 'obj': obj, - } - eval(action.code, localdict, mode="exec") - if 'action' in localdict: - return localdict['action'] - else: - netsvc.Logger().notifyChannel( - self._name, netsvc.LOG_ERROR, - "%s is a `code` server action, but " - "it isn't allowed in this configuration.\n\n" - "See server options to enable it"%action) + localdict = { + 'self': self.pool.get(action.model_id.model), + 'context': dict(context), # copy context to prevent side-effects of eval + 'time': time, + 'ids': ids, + 'cr': cr, + 'uid': uid, + 'object':obj, + 'obj': obj, + } + eval(action.code, localdict, mode="exec", nocopy=True) # nocopy allows to return 'action' + if 'action' in localdict: + return localdict['action'] if action.state == 'email': user = config['email_from'] @@ -631,9 +634,9 @@ class actions_server(osv.osv): obj_pool = self.pool.get(action.model_id.model) obj = obj_pool.browse(cr, uid, context['active_id'], context=context) cxt = { - 'context':context, + 'context': dict(context), # copy context to prevent side-effects of eval 'object': obj, - 'time':time, + 'time': time, 'cr': cr, 'pool' : self.pool, 'uid' : uid @@ -651,7 +654,11 @@ class actions_server(osv.osv): if exp.type == 'equation': obj_pool = self.pool.get(action.model_id.model) obj = obj_pool.browse(cr, uid, context['active_id'], context=context) - cxt = {'context':context, 'object': obj, 'time':time} + cxt = { + 'context': dict(context), # copy context to prevent side-effects of eval + 'object': obj, + 'time': time, + } expr = eval(euq, cxt) else: expr = exp.value @@ -687,7 +694,12 @@ class actions_server(osv.osv): if exp.type == 'equation': obj_pool = self.pool.get(action.model_id.model) obj = obj_pool.browse(cr, uid, context['active_id'], context=context) - expr = eval(euq, {'context':context, 'object': obj, 'time':time}) + expr = eval(euq, + { + 'context': dict(context), # copy context to prevent side-effects of eval + 'object': obj, + 'time': time, + }) else: expr = exp.value res[exp.col1.name] = expr @@ -706,7 +718,12 @@ class actions_server(osv.osv): if exp.type == 'equation': obj_pool = self.pool.get(action.model_id.model) obj = obj_pool.browse(cr, uid, context['active_id'], context=context) - expr = eval(euq, {'context':context, 'object': obj, 'time':time}) + expr = eval(euq, + { + 'context': dict(context), # copy context to prevent side-effects of eval + 'object': obj, + 'time': time, + }) else: expr = exp.value res[exp.col1.name] = expr diff --git a/bin/addons/base/module/module.py b/bin/addons/base/module/module.py index 89a059eb9c5..f4086f9edc3 100644 --- a/bin/addons/base/module/module.py +++ b/bin/addons/base/module/module.py @@ -130,8 +130,8 @@ class module(osv.osv): return res _columns = { - 'name': fields.char("Name", size=128, readonly=True, required=True), - 'category_id': fields.many2one('ir.module.category', 'Category', readonly=True), + 'name': fields.char("Name", size=128, readonly=True, required=True, select=True), + 'category_id': fields.many2one('ir.module.category', 'Category', readonly=True, select=True), 'shortdesc': fields.char('Short Description', size=256, readonly=True, translate=True), 'description': fields.text("Description", readonly=True, translate=True), 'author': fields.char("Author", size=128, readonly=True), @@ -160,7 +160,7 @@ class module(osv.osv): ('to upgrade','To be upgraded'), ('to remove','To be removed'), ('to install','To be installed') - ], string='State', readonly=True), + ], string='State', readonly=True, select=True), 'demo': fields.boolean('Demo data'), 'license': fields.selection([ ('GPL-2', 'GPL Version 2'), @@ -510,7 +510,7 @@ class web_module_dependency(osv.osv): _columns = { - 'name': fields.char('Name', size=128), + 'name': fields.char('Name', size=128, select=True), 'module_id': fields.many2one('ir.module.module', 'Module', select=True, ondelete='cascade'), 'web_module_id': fields.many2one('ir.module.web', 'Web Module', select=True, ondelete='cascade'), 'state': fields.function(_state, method=True, type='selection', selection=[ @@ -521,7 +521,7 @@ class web_module_dependency(osv.osv): ('to remove','To be removed'), ('to install','To be installed'), ('unknown', 'Unknown'), - ], string='State', readonly=True), + ], string='State', readonly=True, select=True), } web_module_dependency() @@ -542,7 +542,7 @@ class module_dependency(osv.osv): return result _columns = { - 'name': fields.char('Name', size=128), + 'name': fields.char('Name', size=128, select=True), 'module_id': fields.many2one('ir.module.module', 'Module', select=True, ondelete='cascade'), 'state': fields.function(_state, method=True, type='selection', selection=[ ('uninstallable','Uninstallable'), @@ -552,7 +552,7 @@ class module_dependency(osv.osv): ('to remove','To be removed'), ('to install','To be installed'), ('unknown', 'Unknown'), - ], string='State', readonly=True), + ], string='State', readonly=True, select=True), } module_dependency() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bin/addons/base/res/ir_property.py b/bin/addons/base/res/ir_property.py index 2141c26b435..17514898eeb 100644 --- a/bin/addons/base/res/ir_property.py +++ b/bin/addons/base/res/ir_property.py @@ -47,12 +47,12 @@ class ir_property(osv.osv): _columns = { - 'name': fields.char('Name', size=128), + 'name': fields.char('Name', size=128, select=1), 'res_id': fields.reference('Resource', selection=_models_get, size=128, - help="If not set, act as default property"), - 'company_id': fields.many2one('res.company', 'Company'), - 'fields_id': fields.many2one('ir.model.fields', 'Fields', ondelete='cascade', required=True), + help="If not set, act as default property", select=1), + 'company_id': fields.many2one('res.company', 'Company', select=1), + 'fields_id': fields.many2one('ir.model.fields', 'Field', ondelete='cascade', required=True, select=1), 'value_float' : fields.float('Value'), 'value_integer' : fields.integer_big('Value'), # will contain (int, bigint) diff --git a/bin/osv/fields.py b/bin/osv/fields.py index e2f8e8a1ece..3ab140e4088 100644 --- a/bin/osv/fields.py +++ b/bin/osv/fields.py @@ -901,12 +901,9 @@ class property(function): domain = [('fields_id.model', '=', obj._name), ('fields_id.name','in',prop_name)] #domain = prop._get_domain(cr, uid, prop_name, obj._name, context) - if domain is not None: + if vids: domain = [('res_id', 'in', vids)] + domain - return prop.search(cr, uid, domain, context=context) - else: - return [] - + return prop.search(cr, uid, domain, context=context) # TODO: to rewrite more clean def _fnct_write(self, obj, cr, uid, id, prop_name, id_val, obj_dest, context=None): diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 3f259dd66bc..25a987dac61 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -2275,10 +2275,9 @@ class orm(orm_template): del r['id'] if groupby and fget[groupby]['type'] == 'many2one': data_ids = self.search(cr, uid, [('id', 'in', alldata.keys())], order=groupby, context=context) - data_read = self.read(cr, uid, data_ids, groupby and [groupby] or ['id'], context=context) + data = self.read(cr, uid, data_ids, groupby and [groupby] or ['id'], context=context) # restore order of the search as read() uses the default _order (this is only for groups, so the size of data_read shoud be small): - data_read.sort(lambda x,y: cmp(data_ids.index(x['id']), data_ids.index(y['id']))) - data = data_read + data.sort(lambda x,y: cmp(data_ids.index(x['id']), data_ids.index(y['id']))) else: data = self.read(cr, uid, alldata.keys(), groupby and [groupby] or ['id'], context=context) if groupby: diff --git a/bin/tools/config.py b/bin/tools/config.py index a0554eb26ec..2964870d427 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -221,9 +221,6 @@ class configmanager(object): security = optparse.OptionGroup(parser, 'Security-related options') security.add_option('--no-database-list', action="store_false", dest='list_db', help="disable the ability to return the list of databases") - security.add_option('--enable-code-actions', action='store_true', - dest='server_actions_allow_code', default=False, - help='Enables server actions of state "code". Warning, this is a security risk.') parser.add_option_group(security) def parse_config(self): @@ -287,7 +284,7 @@ class configmanager(object): keys = [ 'language', 'translate_out', 'translate_in', 'debug_mode', 'smtp_ssl', 'stop_after_init', 'logrotate', 'without_demo', 'netrpc', 'xmlrpc', 'syslog', - 'list_db', 'server_actions_allow_code', 'xmlrpcs', + 'list_db', 'xmlrpcs', 'test_file', 'test_disable', 'test_commit', 'test_report_directory' ] diff --git a/bin/tools/misc.py b/bin/tools/misc.py index 2baf7c0c227..1256adb46f6 100644 --- a/bin/tools/misc.py +++ b/bin/tools/misc.py @@ -62,9 +62,7 @@ _logger = logging.getLogger('tools') def init_db(cr): import addons f = addons.get_module_resource('base', 'base.sql') - for line in file_open(f).read().split(';'): - if (len(line)>0) and (not line.isspace()): - cr.execute(line) + cr.execute(file_open(f).read()) cr.commit() for i in addons.get_modules():