Merge branch 'master' of openobject-server into mdv-gpl3-fwd
Conflicts: bin/netsvc.py bin/sql_db.py bin/ssl/SecureXMLRPCServer.py (note: fixes are lost now) bzr revid: p_christ@hol.gr-20081223154608-fs0830k7vyo81m5u
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
include README
|
||||
include bin/import_xml.rng
|
||||
include bin/server.cert
|
||||
include bin/server.pkey
|
||||
recursive-include doc *
|
||||
recursive-include man *
|
||||
recursive-include bin *xml *xsl *sql *rml *sxw *csv *rng
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: OpenERP
|
||||
Version: 5.0.0-rc1
|
||||
Version: 5.0.0-rc2
|
||||
Author: Tiny.be
|
||||
Author-email: fp at tiny be
|
||||
Maintainer: Tiny.be
|
||||
|
||||
@@ -512,11 +512,12 @@ def load_module_graph(cr, graph, status=None, check_access_rules=True, **kwargs)
|
||||
package_todo.append(package.name)
|
||||
ver = release.major_version + '.' + package.data.get('version', '1.0')
|
||||
# update the installed version in database...
|
||||
cr.execute("update ir_module_module set state='installed', latest_version=%s where id=%s", (ver, mid,))
|
||||
cr.commit()
|
||||
#cr.execute("update ir_module_module set state='installed', latest_version=%s where id=%s", (ver, mid,))
|
||||
|
||||
# Set new modules and dependencies
|
||||
modobj = pool.get('ir.module.module')
|
||||
modobj.write(cr, 1, [mid], {'state':'installed', 'latest_version':ver})
|
||||
cr.commit()
|
||||
|
||||
# Update translations for all installed languages
|
||||
if modobj:
|
||||
|
||||
@@ -2877,5 +2877,6 @@
|
||||
<test expr="currency_id.code == 'eur'.upper()"/>
|
||||
<test expr="name">Tiny sprl</test>
|
||||
</assert>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -257,13 +257,14 @@
|
||||
|
||||
<!-- register on configuratuion -->
|
||||
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
<record id="config_wizard_step_user" model="ir.actions.todo">
|
||||
<field name="name">Create User</field>
|
||||
<field name="note">Create your users.
|
||||
You will be able to assign groups to users. Groups define the access rights of each users on the different objects of the system.
|
||||
</field>
|
||||
<field name="action_id" ref="action_config_user_form"/>
|
||||
<field name="state">open</field>
|
||||
<field name="sequence">10</field>
|
||||
</record>
|
||||
|
||||
@@ -275,7 +276,6 @@ the simplified interface, which has less options and fields but is easier to
|
||||
understand. You will be able to switch to the extended view later.
|
||||
</field>
|
||||
<field name="action_id" ref="action_config_simple_view_form"/>
|
||||
<field name="state">open</field>
|
||||
<field name="sequence">5</field>
|
||||
</record>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1122
-413
File diff suppressed because it is too large
Load Diff
+1211
-502
File diff suppressed because it is too large
Load Diff
+1322
-613
File diff suppressed because it is too large
Load Diff
+1158
-449
File diff suppressed because it is too large
Load Diff
+1132
-423
File diff suppressed because it is too large
Load Diff
+1151
-442
File diff suppressed because it is too large
Load Diff
+1310
-601
File diff suppressed because it is too large
Load Diff
+1182
-473
File diff suppressed because it is too large
Load Diff
+1350
-787
File diff suppressed because it is too large
Load Diff
+1122
-413
File diff suppressed because it is too large
Load Diff
+1126
-417
File diff suppressed because it is too large
Load Diff
+1219
-510
File diff suppressed because it is too large
Load Diff
+1122
-413
File diff suppressed because it is too large
Load Diff
+1374
-664
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+2051
-1340
File diff suppressed because it is too large
Load Diff
+1201
-492
File diff suppressed because it is too large
Load Diff
+1132
-423
File diff suppressed because it is too large
Load Diff
+1213
-504
File diff suppressed because it is too large
Load Diff
+1239
-530
File diff suppressed because it is too large
Load Diff
+1138
-429
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1216
-507
File diff suppressed because it is too large
Load Diff
+1166
-457
File diff suppressed because it is too large
Load Diff
+1135
-426
File diff suppressed because it is too large
Load Diff
+73
-39
@@ -1,6 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Values -->
|
||||
|
||||
<record id="values_view_form_action" model="ir.ui.view">
|
||||
<field name="name">ir.values.form.action</field>
|
||||
<field name="model">ir.values</field>
|
||||
<field name="type">form</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Connect Events to Actions">
|
||||
<field name="name" select="1" required="1"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Action Source" colspan="2"/>
|
||||
<field name="model_id" on_change="onchange_object_id(model_id)"/>
|
||||
<field name="model" select="1" required="1"/>
|
||||
<field name="res_id"/>
|
||||
<field name="key2" select="2" required="1"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Action To Launch" colspan="2"/>
|
||||
<field name="action_id" on_change="onchange_action_id(action_id)"/>
|
||||
<field name="value_unpickle" required="1"/>
|
||||
<field name="object" readonly="1"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="act_values_form_action" model="ir.actions.act_window">
|
||||
<field name="name">Connect Actions To Client Events</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">ir.values</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
<field name="view_id" ref="values_view_form_action"/>
|
||||
<field name="domain">[('key','=','action')]</field>
|
||||
<field name="context">{'read':'default','default_object':1}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="act_values_form_action" id="menu_values_form_action" parent="base.menu_custom_action"/>
|
||||
|
||||
|
||||
<!-- Values -->
|
||||
|
||||
@@ -705,8 +745,8 @@
|
||||
'readonly': [('ttype','!=','one2many'), ('ttype','!=','many2one'), ('ttype','!=','many2many')]}"/>
|
||||
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')],
|
||||
'readonly': [('ttype','!=','one2many')]}"/>
|
||||
<field name="selection" attrs="{'required': [('ttype','=','selection')], 'readonly': [('ttype','!=','selection')]}"/>
|
||||
<field name="size" attrs="{'required': [('ttype','=','char')], 'readonly': [('ttype','!=','char')]}"/>
|
||||
<field name="selection" attrs="{'required': [('ttype','in',['selection','reference'])], 'readonly': [('ttype','not in',['selection','reference'])]}"/>
|
||||
<field name="size" attrs="{'required': [('ttype','in',['char','reference'])], 'readonly': [('ttype','not in',['char','reference'])]}"/>
|
||||
<field name="state"/>
|
||||
<field name="domain" attrs="{'readonly': [('relation','=','')]}"/>
|
||||
</group>
|
||||
@@ -783,8 +823,8 @@
|
||||
<field name="relation" select="2" attrs="{'required': [('ttype','in', ['many2one','one2many','many2many'])],
|
||||
'readonly': [('ttype','not in', ['many2one','one2many','many2many'])]}"/>
|
||||
<field name="relation_field" attrs="{'required': [('ttype','=','one2many')], 'readonly': [('ttype','!=','one2many')]}"/>
|
||||
<field name="selection" attrs="{'required': [('ttype','=','selection')], 'readonly': [('ttype','!=','selection')]}"/>
|
||||
<field name="size" attrs="{'required': [('ttype','=','char')], 'readonly': [('ttype','!=','char')]}"/>
|
||||
<field name="selection" attrs="{'required': [('ttype','in',['selection','reference'])], 'readonly': [('ttype','not in',['selection','reference'])]}"/>
|
||||
<field name="size" attrs="{'required': [('ttype','in',['char','reference'])], 'readonly': [('ttype','not in',['char','reference'])]}"/>
|
||||
<field name="state"/>
|
||||
<field name="domain" attrs="{'readonly': [('relation','=','')]}"/>
|
||||
</group>
|
||||
@@ -1148,46 +1188,43 @@
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Server Action">
|
||||
<field name="name" select="1"/>
|
||||
<field name="state" select="1"/>
|
||||
<field name="model_id" select="1"/>
|
||||
<field name="sequence" select="2"/>
|
||||
<field name="condition" colspan="4"/>
|
||||
<group col="6" colspan="4">
|
||||
<field name="name" select="1"/>
|
||||
<field name="model_id" select="1"/>
|
||||
<field name="state" select="1"/>
|
||||
<field name="sequence" select="2"/>
|
||||
<field name="condition"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
|
||||
<page string="Python Code" attrs="{'invisible':[('state','!=','code')]}">
|
||||
<page string="Python Code" attrs="{'invisible':[('state','!=','code')]}">
|
||||
<separator colspan="4" string="Python Code"/>
|
||||
<field name="code" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
|
||||
<page string="Trigger" attrs="{'invisible':[('state','!=','trigger')]}">
|
||||
<separator colspan="4" string="Trigger Configuration"/>
|
||||
<field name="wkf_model_id"/>
|
||||
<field name="trigger_obj_id" select="2" domain="[('model_id','=',model_id)]" on_change="on_trigger_obj_id(trigger_obj_id)"/>
|
||||
<field name="trigger_name" select="2"/>
|
||||
<field name="wkf_model_id" attrs="{'required':[('state','=','trigger')]}"/>
|
||||
<field name="trigger_obj_id" select="2" context="{'key':''}" domain="[('model_id','=',model_id)]" attrs="{'required':[('state','=','trigger')]}"/>
|
||||
<field name="trigger_name" select="2" attrs="{'required':[('state','=','trigger')]}"/>
|
||||
</page>
|
||||
|
||||
<page string="Action to Launch" attrs="{'invisible':[('state','!=','client_action')]}">
|
||||
<field name="action_id" select="2" colspan="4"/>
|
||||
<page string="Action to Launch" attrs="{'invisible':[('state','!=','client_action')]}">
|
||||
<separator colspan="4" string="Client Action Configuration"/>
|
||||
<field name="action_id" select="2" attrs="{'required':[('state','=','client_action')]}"/>
|
||||
</page>
|
||||
|
||||
<page string="Email Configuration" attrs="{'invisible':[('state','!=','email')]}">
|
||||
<separator colspan="4" string="Email Configuration"/>
|
||||
<field name="email" domain="[('model_id','=',model_id)]"/>
|
||||
<field name="subject" colspan="4"/>
|
||||
<field name="message" select="2" colspan="4"/>
|
||||
<field name="email" domain="[('model_id','=',model_id)]" attrs="{'required':[('state','=','email')]}"/>
|
||||
<field name="subject" colspan="4" attrs="{'required':[('state','=','email')]}"/>
|
||||
<field name="message" select="2" colspan="4" attrs="{'required':[('state','=','email')]}"/>
|
||||
<newline/>
|
||||
<label colspan="4" string="Access all the fields related to the current object using expression in double brackets, i.e. [[ object.partner_id.name ]]" align="0.0"/>
|
||||
<label colspan="4" string="Access all the fields related to the current object using expression in double brackets, i.e.[[ object.partner_id.name ]]" align="0.0"/>
|
||||
</page>
|
||||
|
||||
<page string="SMS Configuration" attrs="{'invisible':[('state','!=','sms')]}">
|
||||
<separator colspan="4" string="SMS Configuration"/>
|
||||
<field name="mobile" domain="[('model_id','=',model_id)]"/>
|
||||
<field name="sms" colspan="4"/>
|
||||
<field name="mobile" domain="[('model_id','=',model_id)]" attrs="{'required':[('state','=','email')]}"/>
|
||||
<field name="sms" colspan="4" attrs="{'required':[('state','=','email')]}"/>
|
||||
<newline/>
|
||||
<label colspan="4" string="Access all the fields related to the current object using expression in double brackets, i.e. [[ object.partner_id.name ]]" align="0.0"/>
|
||||
</page>
|
||||
|
||||
<page string="Create / Write" attrs="{'invisible':[('state','!=','object_create'),('state','!=','object_write')]}">
|
||||
<separator colspan="4" string="Fields Mapping"/>
|
||||
<field name="srcmodel_id" select="2" attrs="{'required':[('state','!=','dummy'), ('state','!=','sms'), ('state','!=','code'), ('state','!=','loop'),('state','!=','trigger'), ('state','!=','client_action'), ('state','!=','email'), ('state','!=','sms'), ('state','!=','other')]}"/>
|
||||
@@ -1207,21 +1244,17 @@
|
||||
<field name="write_id" attrs="{'readonly':[('state','!=','object_write')]}"/>
|
||||
<label colspan="4" string="If you use a formula type, use a python expression using the variable 'object'." align="0.0"/>
|
||||
</page>
|
||||
|
||||
<page string="Iteration Actions" attrs="{'invisible':[('state','!=','loop')]}">
|
||||
<separator colspan="4" string="Iteration Action Configuration"/>
|
||||
<field name="loop_action" domain="[('state','!=','loop')]"/>
|
||||
<field name="expression" attrs="{'required':[('state','=','loop')]}"/>
|
||||
<label colspan="4" string="Define the expression that generate a list" align="0.0"/>
|
||||
<field name="loop_action" domain="[('state','!=','loop')]" attrs="{'required':[('state','=','loop')]}"/>
|
||||
</page>
|
||||
|
||||
<page string="Multi Actions" attrs="{'invisible':[('state','!=','other')]}">
|
||||
<separator colspan="4" string="Other Actions Configuration"/>
|
||||
<field name="child_ids" nolabel="1" colspan="4"/>
|
||||
<label colspan="4" string="Only one client action will be execute, last
|
||||
clinent action will be consider in case of multiples clients actions" align="0.0"/>
|
||||
</page>
|
||||
|
||||
</notebook>
|
||||
<field name="type" readonly="1"/>
|
||||
</form>
|
||||
@@ -1236,6 +1269,7 @@
|
||||
<tree string="Server Actions">
|
||||
<field name="name"/>
|
||||
<field name="state"/>
|
||||
<field name="model_id"/>
|
||||
<field name="sequence"/>
|
||||
</tree>
|
||||
</field>
|
||||
@@ -1274,28 +1308,28 @@
|
||||
</record>
|
||||
<menuitem action="action_model_grid_security" id="menu_ir_access_grid" parent="menu_security_access"/>
|
||||
|
||||
<record id="ir_actions_todo_tree" model="ir.ui.view">
|
||||
<record id="ir_actions_todo_tree" model="ir.ui.view">
|
||||
<field name="model">ir.actions.todo</field>
|
||||
<field name="name">Config Wizard Steps</field>
|
||||
<field name="name">Config Wizard Steps</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom" string="Config Wizard Steps">
|
||||
<field name="name" select="1"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="action_id" select="1"/>
|
||||
<field name="sequence"/>
|
||||
<field name="state"/>
|
||||
<field name="active" select="1"/>
|
||||
<field name="active" select="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="config_wizard_step_view_form" model="ir.ui.view">
|
||||
<field name="model">ir.actions.todo</field>
|
||||
<field name="name">Config Wizard Steps</field>
|
||||
<field name="name">Config Wizard Steps</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form editable="bottom" string="Config Wizard Steps">
|
||||
<field name="name" select="1"/>
|
||||
<field name="active" select="1"/>
|
||||
<field name="active" select="1"/>
|
||||
<field name="action_id" select="1"/>
|
||||
<field name="sequence"/>
|
||||
<field name="state"/>
|
||||
@@ -1308,7 +1342,7 @@
|
||||
<field name="res_model">ir.actions.todo</field>
|
||||
<field name="view_id" ref="ir_actions_todo_tree"/>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain">[('type','=','configure')]</field>
|
||||
<field name="domain">[('type','=','configure')]</field>
|
||||
</record>
|
||||
<menuitem id="next_id_11" name="Configuration Wizards" parent="base.menu_config" sequence="1"/>
|
||||
<menuitem action="act_ir_actions_todo_form" id="menu_ir_actions_todo_form" parent="next_id_11"/>
|
||||
|
||||
@@ -365,7 +365,7 @@ server_object_lines()
|
||||
# Actions that are run on the server side
|
||||
#
|
||||
class actions_server(osv.osv):
|
||||
|
||||
|
||||
def _select_signals(self, cr, uid, context={}):
|
||||
cr.execute("select distinct t.signal as key, t.signal || ' - [ ' || w.osv || ' ] ' as val from wkf w, wkf_activity a, wkf_transition t "\
|
||||
" where w.id = a.wkf_id " \
|
||||
@@ -377,15 +377,14 @@ class actions_server(osv.osv):
|
||||
if not rs[0] == None and not rs[1] == None:
|
||||
res.append(rs)
|
||||
return res
|
||||
|
||||
|
||||
_name = 'ir.actions.server'
|
||||
_table = 'ir_act_server'
|
||||
_sequence = 'ir_actions_id_seq'
|
||||
_order = 'sequence'
|
||||
_columns = {
|
||||
'name': fields.char('Action Name', required=True, size=64),
|
||||
'condition' : fields.char('Condition', size=256),
|
||||
'sub_condition' : fields.char('Condition', size=256),
|
||||
'name': fields.char('Action Name', required=True, size=64, help="Easy to Refer action by name i.e. One Sales Order -> Many Invoice"),
|
||||
'condition' : fields.char('Condition', size=256, required=True, help="Condition that is to be test before execute action, i.e : object.list_price > object.cost_price"),
|
||||
'state': fields.selection([
|
||||
('client_action','Client Action'),
|
||||
('dummy','Dummy'),
|
||||
@@ -397,18 +396,18 @@ class actions_server(osv.osv):
|
||||
('object_create','Create Object'),
|
||||
('object_write','Write Object'),
|
||||
('other','Multi Actions'),
|
||||
], 'Action Type', required=True, size=32),
|
||||
'code':fields.text('Python Code'),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'model_id': fields.many2one('ir.model', 'Object', required=True),
|
||||
'action_id': fields.many2one('ir.actions.actions', 'Client Action'),
|
||||
'trigger_name': fields.selection(_select_signals, string='Trigger Name', size=128),
|
||||
'wkf_model_id': fields.many2one('ir.model', 'Workflow on'),
|
||||
'trigger_obj_id': fields.many2one('ir.model.fields','Trigger On'),
|
||||
'email': fields.char('Email Address', size=512),
|
||||
'subject': fields.char('Subject', size=1024, translate=True),
|
||||
'message': fields.text('Message', translate=True),
|
||||
'mobile': fields.char('Mobile No', size=512),
|
||||
], 'Action Type', required=True, size=32, help="Type of the Action that is to be execute"),
|
||||
'code':fields.text('Python Code', help="python code to be execute"),
|
||||
'sequence': fields.integer('Sequence', help="Important when you deal with the multi action, the execution order will be decided based on this, low number higher priority"),
|
||||
'model_id': fields.many2one('ir.model', 'Object', required=True, help="select the obect on which the action will work (read, write, create)"),
|
||||
'action_id': fields.many2one('ir.actions.actions', 'Client Action', help="Select the Ation Window, Report, Wizard to be execute"),
|
||||
'trigger_name': fields.selection(_select_signals, string='Trigger Name', size=128, help="Select the Signal name that is to be "),
|
||||
'wkf_model_id': fields.many2one('ir.model', 'Workflow on', help="Workflow to be execute on which model"),
|
||||
'trigger_obj_id': fields.many2one('ir.model.fields','Trigger On', help="select the object from the model on which the workflow will execute"),
|
||||
'email': fields.char('Email Address', size=512, help="provides the fiels that will refer to the tiny to fetch the email address, i.e. you select the invoice, then `object.invoice_address_id.email` is the field which give the correct address"),
|
||||
'subject': fields.char('Subject', size=1024, translate=True, help="Specify the subject, you can use the fields from the object. like `Hello [[ object.partner_id.name ]]`"),
|
||||
'message': fields.text('Message', translate=True, help="Specify the Message, you can use the fields from the object. like `Dear [[ object.partner_id.name ]]`"),
|
||||
'mobile': fields.char('Mobile No', size=512, help="provides the fiels that will refer to the tiny to fetch the mobile number, i.e. you select the invoice, then `object.invoice_address_id.mobile` is the field which give the correct mobile number"),
|
||||
'sms': fields.char('SMS', size=160, translate=True),
|
||||
'child_ids': fields.many2many('ir.actions.server', 'rel_server_actions', 'server_id', 'action_id', 'Others Actions'),
|
||||
'usage': fields.char('Action Usage', size=32),
|
||||
@@ -417,13 +416,12 @@ class actions_server(osv.osv):
|
||||
'fields_lines': fields.one2many('ir.server.object.lines', 'server_id', 'Fields Mapping'),
|
||||
'record_id':fields.many2one('ir.model.fields', 'Create Id', help="Provide the field name from where the record id stores after the create operations, if its empty, you can not track the new record"),
|
||||
'write_id':fields.char('Write Id', size=256, help="Provide the field name from where the record id refer for the write operation, if its empty it will refer to the active id of the object"),
|
||||
'loop_action':fields.many2one('ir.actions.server', 'Loop Action'),
|
||||
'expression':fields.char('Loop Expression', size=512),
|
||||
'loop_action':fields.many2one('ir.actions.server', 'Loop Action', help="select the action, which will be executes. Loop action will not be avaliable inside loop"),
|
||||
'expression':fields.char('Loop Expression', size=512, help="enter the field/expression that will return the list, i.e. select the sale order in Object, and we can have loop on sales order line. Expression = `object.order_line`"),
|
||||
}
|
||||
_defaults = {
|
||||
'state': lambda *a: 'dummy',
|
||||
'condition': lambda *a: 'True',
|
||||
'sub_condition': lambda *a: 'True',
|
||||
'type': lambda *a: 'ir.actions.server',
|
||||
'sequence': lambda *a: 5,
|
||||
'code': lambda *a: """# You can use the following variables
|
||||
|
||||
@@ -79,6 +79,7 @@ class ir_translation(osv.osv):
|
||||
cr.execute('CREATE INDEX ir_translation_lts ON ir_translation (lang, type, src)')
|
||||
cr.commit()
|
||||
|
||||
@tools.cache(skiparg=3)
|
||||
def _get_ids(self, cr, uid, name, tt, lang, ids):
|
||||
translations = {}
|
||||
if ids:
|
||||
|
||||
@@ -49,19 +49,45 @@ class ir_values(osv.osv):
|
||||
value = pickle.dumps(eval(value))
|
||||
self.write(cursor, user, id, {name[:-9]: value}, context=ctx)
|
||||
|
||||
def onchange_object_id(self, cr, uid, ids, object_id, context={}):
|
||||
if not object_id: return {}
|
||||
act = self.pool.get('ir.model').browse(cr, uid, object_id, context=context)
|
||||
return {
|
||||
'value': {'model': act.model}
|
||||
}
|
||||
|
||||
def onchange_action_id(self, cr, uid, ids, action_id, context={}):
|
||||
if not action_id: return {}
|
||||
act = self.pool.get('ir.actions.actions').browse(cr, uid, action_id, context=context)
|
||||
return {
|
||||
'value': {'value_unpickle': act.type+','+str(act.id)}
|
||||
}
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=128),
|
||||
'model': fields.char('Object', size=128),
|
||||
'model_id': fields.many2one('ir.model', 'Object', size=128,
|
||||
help="This field is not used, it only helps you to select a good model."),
|
||||
'model': fields.char('Object Name', size=128),
|
||||
'action_id': fields.many2one('ir.actions.actions', 'Action',
|
||||
help="This field is not used, it only helps you to select the right action."),
|
||||
'value': fields.text('Value'),
|
||||
'value_unpickle': fields.function(_value_unpickle, fnct_inv=_value_pickle,
|
||||
method=True, type='text', string='Value'),
|
||||
'object': fields.boolean('Is Object'),
|
||||
'key': fields.char('Type', size=128),
|
||||
'key2': fields.char('Value', size=256),
|
||||
'key': fields.selection([('action','Action'),('default','Default')], 'Type', size=128),
|
||||
'key2': fields.selection([
|
||||
('client_action_multi', 'Wizard in Forms'),
|
||||
('client_action_relate', 'Relate on Object'),
|
||||
('client_print_multi', 'Print'),
|
||||
('tree_but_action', 'Wizard in Tree'),
|
||||
('tree_but_open', 'Open on Tree'),
|
||||
('','/')
|
||||
], string='Event Type', size=256,
|
||||
help="The kind of action or button in the client side that will trigger the action."),
|
||||
'meta': fields.text('Meta Datas'),
|
||||
'meta_unpickle': fields.function(_value_unpickle, fnct_inv=_value_pickle,
|
||||
method=True, type='text', string='Meta Datas'),
|
||||
'res_id': fields.integer('Resource ID'),
|
||||
'res_id': fields.integer('Object ID', help="Keep 0 if the action must appear on all resources."),
|
||||
'user_id': fields.many2one('res.users', 'User', ondelete='cascade'),
|
||||
'company_id': fields.many2one('res.company', 'Company')
|
||||
}
|
||||
|
||||
@@ -459,11 +459,34 @@ class module(osv.osv):
|
||||
continue
|
||||
|
||||
for lang in filter_lang:
|
||||
f = os.path.join(tools.config['addons_path'], mod.name, 'i18n', lang + '.po')
|
||||
f = os.path.join(addons.get_module_path(mod.name), 'i18n', lang + '.po')
|
||||
if os.path.exists(f):
|
||||
logger.notifyChannel("init", netsvc.LOG_INFO, 'module %s: loading translation file for language %s' % (mod.name, lang))
|
||||
tools.trans_load(cr.dbname, f, lang, verbose=False)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
# Override the write method because we want to show a warning when the description field is empty !
|
||||
if isinstance( ids, (long, int) ):
|
||||
ids = [ids]
|
||||
if 'description' in vals and not vals['description']:
|
||||
logger = netsvc.Logger()
|
||||
for mod in self.browse(cr, uid, ids):
|
||||
logger.notifyChannel("init", netsvc.LOG_WARNING, 'module %s: description is empty !' % (mod.name))
|
||||
|
||||
return super(module, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
# Override the create method because we want to show a warning when the description field is empty !
|
||||
module_id = super(module, self).create(cr, uid, vals, context=context)
|
||||
|
||||
if 'description' in vals and not vals['description']:
|
||||
logger = netsvc.Logger()
|
||||
for mod in self.browse(cr, uid, [module_id]):
|
||||
logger.notifyChannel("init", netsvc.LOG_WARNING, 'module %s: description is empty !' % (mod.name))
|
||||
|
||||
return module_id
|
||||
|
||||
|
||||
module()
|
||||
|
||||
class module_dependency(osv.osv):
|
||||
|
||||
@@ -65,8 +65,7 @@ class wizard_info_get(wizard.interface):
|
||||
'module_download': '\n'.join(url)}
|
||||
|
||||
def _check_upgrade_module(self,cr,uid,data,context):
|
||||
db, pool = pooler.get_db_and_pool(cr.dbname)
|
||||
cr = db.cursor()
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
mod_obj = pool.get('ir.module.module')
|
||||
ids = mod_obj.search(cr, uid, [
|
||||
('state', 'in', ['to upgrade', 'to remove', 'to install'])])
|
||||
@@ -76,17 +75,16 @@ class wizard_info_get(wizard.interface):
|
||||
return 'end'
|
||||
|
||||
def _upgrade_module(self, cr, uid, data, context):
|
||||
db, pool = pooler.get_db_and_pool(cr.dbname)
|
||||
cr = db.cursor()
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
mod_obj = pool.get('ir.module.module')
|
||||
ids = mod_obj.search(cr, uid, [('state', 'in', ['to upgrade', 'to remove', 'to install'])])
|
||||
unmet_packages = []
|
||||
mod_dep_obj = pool.get('ir.module.module.dependency')
|
||||
for mod in mod_obj.browse(cr, uid, ids):
|
||||
depends_mod_ids = mod_dep_obj.search(cr, uid, [('module_id', '=', mod.id)])
|
||||
for dep_mod in mod_dep_obj.browse(cr, uid, depends_mod_ids):
|
||||
depends_mod_ids = mod_dep_obj.search(cr, uid, [('module_id', '=', mod.id)])
|
||||
for dep_mod in mod_dep_obj.browse(cr, uid, depends_mod_ids):
|
||||
if dep_mod.state in ('unknown','uninstalled'):
|
||||
unmet_packages.append(dep_mod.name)
|
||||
unmet_packages.append(dep_mod.name)
|
||||
if len(unmet_packages):
|
||||
raise wizard.except_wizard('Unmet dependency !', 'Following modules are uninstalled or unknown. \n\n'+'\n'.join(unmet_packages))
|
||||
mod_obj.download(cr, uid, ids, context=context)
|
||||
@@ -158,8 +156,7 @@ class wizard_info_get_simple(wizard.interface):
|
||||
'module_download': '\n'.join(url)}
|
||||
|
||||
def _check_upgrade_module(self,cr,uid,data,context):
|
||||
db, pool = pooler.get_db_and_pool(cr.dbname)
|
||||
cr = db.cursor()
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
mod_obj = pool.get('ir.module.module')
|
||||
ids = mod_obj.search(cr, uid, [
|
||||
('state', 'in', ['to upgrade', 'to remove', 'to install'])])
|
||||
@@ -169,8 +166,7 @@ class wizard_info_get_simple(wizard.interface):
|
||||
return 'end'
|
||||
|
||||
def _upgrade_module(self, cr, uid, data, context):
|
||||
db, pool = pooler.get_db_and_pool(cr.dbname)
|
||||
cr = db.cursor()
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
mod_obj = pool.get('ir.module.module')
|
||||
ids = mod_obj.search(cr, uid, [('state', 'in', ['to upgrade', 'to remove', 'to install'])])
|
||||
unmet_packages = []
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rng:grammar xmlns:rng="http://relaxng.org/ns/structure/1.0">
|
||||
<rng:define name="any">
|
||||
<rng:element>
|
||||
<rng:anyName/>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:attribute>
|
||||
<rng:element>
|
||||
<rng:anyName/>
|
||||
</rng:attribute>
|
||||
<rng:text/>
|
||||
<rng:ref name="any"/>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:attribute>
|
||||
<rng:anyName/>
|
||||
</rng:attribute>
|
||||
<rng:text/>
|
||||
<rng:ref name="any"/>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
<rng:start>
|
||||
<rng:ref name="any" />
|
||||
<rng:ref name="any" />
|
||||
</rng:start>
|
||||
</rng:grammar>
|
||||
|
||||
@@ -156,6 +156,7 @@
|
||||
<rng:element name="notebook">
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="colspan"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="tabpos"/></rng:optional>
|
||||
<rng:oneOrMore>
|
||||
<rng:ref name="page"/>
|
||||
</rng:oneOrMore>
|
||||
@@ -222,6 +223,7 @@
|
||||
<rng:optional><rng:attribute name="domain"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="invisible"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="password"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="comparator"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="sum"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="select"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="group"/></rng:optional>
|
||||
@@ -302,6 +304,7 @@
|
||||
<rng:optional><rng:attribute name="day_length" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="date_delay" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="type" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="mode" /></rng:optional>
|
||||
<rng:oneOrMore>
|
||||
<rng:ref name="field"/>
|
||||
</rng:oneOrMore>
|
||||
@@ -336,6 +339,7 @@
|
||||
<rng:optional><rng:attribute name="readonly"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="context"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="confirm"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="form" />
|
||||
|
||||
@@ -130,3 +130,5 @@
|
||||
"access_res_bank_group_partner_manager","res_bank_group_partner_manager","model_res_bank","group_partner_manager",1,1,1,1
|
||||
"access_res_bank_user","res_bank user","model_res_bank","group_user",1,0,0,0
|
||||
"access_maintenance_group_user","maintenance_contract group_user","model_maintenance_contract","group_maintenance_manager",1,1,1,1
|
||||
"access_maintenance_contract_module","maintenance.contract.module","model_maintenance_contract_module","group_maintenance_manager",1,1,1,1
|
||||
"access_maintenance_contract_wizard","maintenance.contract.wizard","model_maintenance_contract_wizard","group_maintenance_manager",1,1,1,1
|
||||
|
||||
|
+118
-91
@@ -4,7 +4,10 @@
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
# The refactoring about the OpenSSL support come from Tryton
|
||||
# Copyright (C) 2007-2008 Cédric Krier.
|
||||
# Copyright (C) 2007-2008 Bertrand Chenal.
|
||||
# Copyright (C) 2008 B2CK SPRL.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -21,22 +24,25 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import threading
|
||||
|
||||
import SimpleXMLRPCServer, signal, sys, xmlrpclib
|
||||
import SimpleXMLRPCServer
|
||||
import SocketServer
|
||||
import socket
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import signal
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import xmlrpclib
|
||||
import release
|
||||
|
||||
_service = {}
|
||||
_group = {}
|
||||
_res_id = 1
|
||||
_res = {}
|
||||
|
||||
|
||||
class ServiceEndPointCall(object):
|
||||
def __init__(self, id, method):
|
||||
self._id = id
|
||||
@@ -131,20 +137,10 @@ class LocalService(Service):
|
||||
Logger().notifyChannel('module', LOG_ERROR, 'This service does not exists: %s' % (str(keyError),) )
|
||||
raise
|
||||
|
||||
|
||||
|
||||
class ServiceUnavailable(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def service_exist(name):
|
||||
return (name in _service) and bool(_service[name])
|
||||
|
||||
|
||||
def get_rpc_paths():
|
||||
return map(lambda s: '/xmlrpc/%s' % s, _service)
|
||||
|
||||
|
||||
LOG_NOTSET = 'notset'
|
||||
LOG_DEBUG_RPC = 'debug_rpc'
|
||||
LOG_DEBUG = 'debug'
|
||||
LOG_INFO = 'info'
|
||||
@@ -159,7 +155,24 @@ def init_logger():
|
||||
from tools import config
|
||||
import os
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
if config['syslog']:
|
||||
# SysLog Handler
|
||||
if os.name == 'nt':
|
||||
sysloghandler = logging.handlers.NTEventLogHandler("%s %s" %
|
||||
(release.description,
|
||||
release.version))
|
||||
else:
|
||||
sysloghandler = logging.handlers.SysLogHandler('/dev/log')
|
||||
formatter = logging.Formatter('%(application)s:%(uncoloredlevelname)s:%(name)s:%(message)s')
|
||||
sysloghandler.setFormatter(formatter)
|
||||
logger.addHandler(sysloghandler)
|
||||
|
||||
# create a format for log messages and dates
|
||||
formatter = logging.Formatter('[%(asctime)s] %(levelname)s:%(name)s:%(message)s', '%a %b %d %Y %H:%M:%S')
|
||||
if config['logfile']:
|
||||
# LogFile Handler
|
||||
logf = config['logfile']
|
||||
try:
|
||||
dirname = os.path.dirname(logf)
|
||||
@@ -170,17 +183,16 @@ def init_logger():
|
||||
sys.stderr.write("ERROR: couldn't create the logfile directory\n")
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
else:
|
||||
# Normal Handler on standard output
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
|
||||
# create a format for log messages and dates
|
||||
formatter = logging.Formatter('[%(asctime)s] %(levelname)s:%(name)s:%(message)s', '%a %b %d %H:%M:%S %Y')
|
||||
|
||||
# tell the handler to use this format
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
# add the handler to the root logger
|
||||
logging.getLogger().addHandler(handler)
|
||||
logging.getLogger().setLevel(config['log_level'])
|
||||
logger.addHandler(handler)
|
||||
logger.setLevel(config['log_level'] or '0')
|
||||
|
||||
if (not isinstance(handler, logging.FileHandler)) and os.name != 'nt':
|
||||
# change color of level names
|
||||
@@ -206,6 +218,14 @@ def init_logger():
|
||||
|
||||
|
||||
class Logger(object):
|
||||
def uncoloredlevelname(self, level):
|
||||
# The level'names are globals to all loggers, so we must strip-off the
|
||||
# color formatting for some specific logger (i.e: syslog)
|
||||
levelname = logging.getLevelName(getattr(logging, level.upper(), 0))
|
||||
if levelname.startswith("\x1b["):
|
||||
return levelname[10:-4]
|
||||
return levelname
|
||||
|
||||
def notifyChannel(self, name, level, msg):
|
||||
log = logging.getLogger(name)
|
||||
|
||||
@@ -213,14 +233,19 @@ class Logger(object):
|
||||
fct = lambda msg, *args, **kwargs: log.log(logging.DEBUG_RPC, msg, *args, **kwargs)
|
||||
setattr(log, LOG_DEBUG_RPC, fct)
|
||||
|
||||
extra = {
|
||||
'uncoloredlevelname': self.uncoloredlevelname(level),
|
||||
'application' : "%s %s" % (release.description, release.version),
|
||||
}
|
||||
|
||||
level_method = getattr(log, level)
|
||||
|
||||
result = str(msg).strip().split('\n')
|
||||
if len(result)>1:
|
||||
for idx, s in enumerate(result):
|
||||
level_method('[%02d]: %s' % (idx+1, s,))
|
||||
level_method('[%02d]: %s' % (idx+1, s,), extra=extra)
|
||||
elif result:
|
||||
level_method(result[0])
|
||||
level_method(result[0], extra=extra)
|
||||
|
||||
init_logger()
|
||||
|
||||
@@ -248,46 +273,35 @@ class Agent(object):
|
||||
timer.cancel()
|
||||
quit = classmethod(quit)
|
||||
|
||||
|
||||
class RpcGateway(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
class Dispatcher(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def monitor(self, signal):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
pass
|
||||
|
||||
|
||||
class xmlrpc(object):
|
||||
class RpcGateway(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
class GenericXMLRPCRequestHandler:
|
||||
def log(self, title, msg):
|
||||
from pprint import pformat
|
||||
Logger().notifyChannel('XMLRPC-%s' % title, LOG_DEBUG_RPC, pformat(msg))
|
||||
|
||||
def _dispatch(self, method, params):
|
||||
# print 'TERP-CALL : ',method, params
|
||||
import traceback
|
||||
try:
|
||||
self.log('method', method)
|
||||
self.log('params', params)
|
||||
n = self.path.split("/")[-1]
|
||||
s = LocalService(n)
|
||||
m = getattr(s, method)
|
||||
s._service._response = None
|
||||
r = m(*params)
|
||||
self.log('result', r)
|
||||
res = s._service._response
|
||||
if res != None:
|
||||
if res is not None:
|
||||
r = res
|
||||
self.log('res',r)
|
||||
return r
|
||||
except Exception, e:
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(
|
||||
sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
self.log('exception', e)
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
s = str(e)
|
||||
import tools
|
||||
if tools.config['debug_mode']:
|
||||
@@ -296,47 +310,68 @@ class GenericXMLRPCRequestHandler:
|
||||
pdb.post_mortem(tb)
|
||||
raise xmlrpclib.Fault(s, tb_s)
|
||||
|
||||
class SSLSocket(object):
|
||||
def __init__(self, socket):
|
||||
if not hasattr(socket, 'sock_shutdown'):
|
||||
from OpenSSL import SSL
|
||||
import tools
|
||||
ctx = SSL.Context(SSL.SSLv23_METHOD)
|
||||
ctx.use_privatekey_file(tools.config['secure_pkey_file'])
|
||||
ctx.use_certificate_file(tools.config['secure_cert_file'])
|
||||
self.socket = SSL.Connection(ctx, socket)
|
||||
else:
|
||||
self.socket = socket
|
||||
|
||||
def shutdown(self, how):
|
||||
return self.socket.sock_shutdown(how)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.socket, name)
|
||||
|
||||
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
||||
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
||||
rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service)
|
||||
|
||||
class SecureXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||
def setup(self):
|
||||
self.connection = SSLSocket(self.request)
|
||||
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
|
||||
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
|
||||
|
||||
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
|
||||
|
||||
def server_bind(self):
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
|
||||
except:
|
||||
Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use')
|
||||
sys.exit(1)
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
|
||||
|
||||
class SecureThreadedXMLRPCServer(SimpleThreadedXMLRPCServer):
|
||||
def __init__(self, server_address, HandlerClass, logRequests=1):
|
||||
SimpleThreadedXMLRPCServer.__init__(self, server_address, HandlerClass, logRequests)
|
||||
self.socket = SSLSocket(socket.socket(self.address_family, self.socket_type))
|
||||
self.server_bind()
|
||||
self.server_activate()
|
||||
|
||||
class HttpDaemon(threading.Thread):
|
||||
|
||||
def __init__(self, interface, port, secure=False):
|
||||
threading.Thread.__init__(self)
|
||||
self.__port = port
|
||||
self.__interface = interface
|
||||
self.secure = secure
|
||||
if secure:
|
||||
from ssl import SecureXMLRPCServer
|
||||
self.secure = bool(secure)
|
||||
handler_class = (SimpleXMLRPCRequestHandler, SecureXMLRPCRequestHandler)[self.secure]
|
||||
server_class = (SimpleThreadedXMLRPCServer, SecureThreadedXMLRPCServer)[self.secure]
|
||||
|
||||
class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler):
|
||||
SecureXMLRPCServer.SecureXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
||||
|
||||
class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer):
|
||||
def server_bind(self):
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self)
|
||||
except:
|
||||
sys.stderr.write("ERROR: address already in use\n")
|
||||
sys.exit(1)
|
||||
|
||||
self.server = SecureThreadedXMLRPCServer((interface, port),
|
||||
SecureXMLRPCRequestHandler, 0)
|
||||
if self.secure:
|
||||
from OpenSSL.SSL import Error as SSLError
|
||||
else:
|
||||
self.server = SimpleThreadedXMLRPCServer((interface, port),
|
||||
SimpleXMLRPCRequestHandler, 0)
|
||||
class SSLError(Exception): pass
|
||||
|
||||
try:
|
||||
self.server = server_class((interface, port), handler_class, 0)
|
||||
except SSLError, e:
|
||||
Logger().notifyChannel('xml-rpc-ssl', LOG_CRITICAL, "Can't load the certificate and/or the private key files")
|
||||
sys.exit(1)
|
||||
except Exception, e:
|
||||
Logger().notifyChannel('xml-rpc', LOG_CRITICAL, "Error occur when strarting the server daemon: %s" % (e,))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def attach(self, path, gw):
|
||||
pass
|
||||
@@ -344,16 +379,7 @@ class HttpDaemon(threading.Thread):
|
||||
def stop(self):
|
||||
self.running = False
|
||||
if os.name != 'nt':
|
||||
if hasattr(socket, 'SHUT_RDWR'):
|
||||
if self.secure:
|
||||
self.server.socket.sock_shutdown(socket.SHUT_RDWR)
|
||||
else:
|
||||
self.server.socket.shutdown(socket.SHUT_RDWR)
|
||||
else:
|
||||
if self.secure:
|
||||
self.server.socket.sock_shutdown(2)
|
||||
else:
|
||||
self.server.socket.shutdown(2)
|
||||
self.server.socket.shutdown( hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2 )
|
||||
self.server.socket.close()
|
||||
|
||||
def run(self):
|
||||
@@ -403,16 +429,17 @@ class TinySocketClientThread(threading.Thread):
|
||||
return False
|
||||
try:
|
||||
self.log(msg)
|
||||
s = LocalService(msg[0])
|
||||
m = getattr(s, msg[1])
|
||||
s._service._response = None
|
||||
r = m(*msg[2:])
|
||||
res = s._service._response
|
||||
service = LocalService(msg[0])
|
||||
method = getattr(service, msg[1])
|
||||
service._service._response = None
|
||||
result_from_method = method(*msg[2:])
|
||||
res = service._service._response
|
||||
if res != None:
|
||||
r = res
|
||||
self.log(r)
|
||||
ts.mysend(r)
|
||||
result_from_method = res
|
||||
self.log(result_from_method)
|
||||
ts.mysend(result_from_method)
|
||||
except Exception, e:
|
||||
print repr(e)
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
import tools
|
||||
if tools.config['debug_mode']:
|
||||
|
||||
+12
-9
@@ -61,6 +61,14 @@ if pwd.getpwuid(os.getuid())[0] == 'root' :
|
||||
import netsvc
|
||||
logger = netsvc.Logger()
|
||||
|
||||
def atexit_callback():
|
||||
logger.notifyChannel('shutdown', netsvc.LOG_INFO, "Shutdown Server!")
|
||||
#logger.notifyChannel('pan! pan!', netsvc.LOG_INFO, "Killed Server ;-)")
|
||||
|
||||
import atexit
|
||||
|
||||
atexit.register(atexit_callback)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# import the tools module so that the commandline parameters are parsed
|
||||
#-----------------------------------------------------------------------
|
||||
@@ -82,9 +90,6 @@ if sys.platform == 'win32':
|
||||
#----------------------------------------------------------
|
||||
logger.notifyChannel("objects", netsvc.LOG_INFO, 'initialising distributed objects services')
|
||||
|
||||
dispatcher = netsvc.Dispatcher()
|
||||
dispatcher.monitor(signal.SIGINT)
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# connect to the database and initialize it with base if needed
|
||||
#---------------------------------------------------------------
|
||||
@@ -163,17 +168,16 @@ if tools.config['xmlrpc']:
|
||||
try:
|
||||
port = int(tools.config["port"])
|
||||
except Exception:
|
||||
logger.notifyChannel("init", netsvc.LOG_ERROR, "invalid port '%s'!" % (tools.config["port"],))
|
||||
logger.notifyChannel("init", netsvc.LOG_CRITICAL, "invalid port: %r" % (tools.config["port"],))
|
||||
sys.exit(1)
|
||||
interface = tools.config["interface"]
|
||||
secure = tools.config["secure"]
|
||||
|
||||
httpd = netsvc.HttpDaemon(interface, port, secure)
|
||||
|
||||
if tools.config["xmlrpc"]:
|
||||
xml_gw = netsvc.xmlrpc.RpcGateway('web-services')
|
||||
httpd.attach("/xmlrpc", xml_gw)
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO, "starting XML-RPC%s services, port %s" % ((tools.config['secure'] and ' Secure' or ''), port))
|
||||
xml_gw = netsvc.xmlrpc.RpcGateway('web-services')
|
||||
httpd.attach("/xmlrpc", xml_gw)
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO, "starting XML-RPC%s services, port %s" % ((tools.config['secure'] and ' Secure' or ''), port))
|
||||
|
||||
#
|
||||
#if tools.config["soap"]:
|
||||
@@ -220,7 +224,6 @@ if tools.config['netrpc']:
|
||||
tinySocket.start()
|
||||
if tools.config['xmlrpc']:
|
||||
httpd.start()
|
||||
#dispatcher.run()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
|
||||
@@ -426,7 +426,6 @@ class one2many(_column):
|
||||
context = {}
|
||||
if not values:
|
||||
return
|
||||
|
||||
_table = obj.pool.get(self._obj)._table
|
||||
obj = obj.pool.get(self._obj)
|
||||
for act in values:
|
||||
|
||||
+8
-6
@@ -129,7 +129,7 @@ class browse_record(object):
|
||||
cache.setdefault(table._name, {})
|
||||
self._data = cache[table._name]
|
||||
|
||||
if not id in self._data:
|
||||
if id not in self._data:
|
||||
self._data[id] = {'id': id}
|
||||
|
||||
self._cache = cache
|
||||
@@ -137,7 +137,7 @@ class browse_record(object):
|
||||
def __getitem__(self, name):
|
||||
if name == 'id':
|
||||
return self._id
|
||||
if not name in self._data[self._id]:
|
||||
if name not in self._data[self._id]:
|
||||
# build the list of fields we will fetch
|
||||
|
||||
# fetch the definition of the field which was asked for
|
||||
@@ -166,7 +166,7 @@ class browse_record(object):
|
||||
# otherwise we fetch only that field
|
||||
else:
|
||||
ffields = [(name, col)]
|
||||
ids = filter(lambda id: not name in self._data[id], self._data.keys())
|
||||
ids = filter(lambda id: name not in self._data[id], self._data.keys())
|
||||
# read the data
|
||||
fffields = map(lambda x: x[0], ffields)
|
||||
datas = self._table.read(self._cr, self._uid, ids, fffields, context=self._context, load="_classic_write")
|
||||
@@ -311,11 +311,11 @@ class orm_template(object):
|
||||
_invalids = set()
|
||||
|
||||
def _field_create(self, cr, context={}):
|
||||
cr.execute("SELECT id FROM ir_model WHERE model='%s'" % self._name)
|
||||
cr.execute("SELECT id FROM ir_model WHERE model=%s", (self._name,))
|
||||
if not cr.rowcount:
|
||||
cr.execute('SELECT nextval(%s)', ('ir_model_id_seq',))
|
||||
model_id = cr.fetchone()[0]
|
||||
cr.execute("INSERT INTO ir_model (id,model, name, info,state) VALUES (%s, %s, %s, %s,%s)", (model_id, self._name, self._description, self.__doc__, 'base'))
|
||||
cr.execute("INSERT INTO ir_model (id,model, name, info,state) VALUES (%s, %s, %s, %s, %s)", (model_id, self._name, self._description, self.__doc__, 'base'))
|
||||
else:
|
||||
model_id = cr.fetchone()[0]
|
||||
if 'module' in context:
|
||||
@@ -959,7 +959,6 @@ class orm_template(object):
|
||||
return None
|
||||
|
||||
|
||||
netsvc.Logger().notifyChannel('orm', netsvc.LOG_DEBUG, type(src))
|
||||
doc_src = dom.minidom.parseString(encode(src))
|
||||
doc_dest = dom.minidom.parseString(encode(inherit))
|
||||
toparse = doc_dest.childNodes
|
||||
@@ -1726,8 +1725,11 @@ class orm(orm_template):
|
||||
'translate': (field['translate']),
|
||||
#'select': int(field['select_level'])
|
||||
}
|
||||
|
||||
if field['ttype'] == 'selection':
|
||||
self._columns[field['name']] = getattr(fields, field['ttype'])(eval(field['selection']), **attrs)
|
||||
elif field['ttype'] == 'reference':
|
||||
self._columns[field['name']] = getattr(fields, field['ttype'])(selection=eval(field['selection']), **attrs)
|
||||
elif field['ttype'] == 'many2one':
|
||||
self._columns[field['name']] = getattr(fields, field['ttype'])(field['relation'], **attrs)
|
||||
elif field['ttype'] == 'one2many':
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
##############################################################################
|
||||
|
||||
name = 'openerp-server'
|
||||
version = '5.0.0_rc1'
|
||||
version = '5.0.0_rc2'
|
||||
major_version = '5.0'
|
||||
description = 'OpenERP Server'
|
||||
long_desc = '''\
|
||||
|
||||
@@ -166,7 +166,7 @@ class report_rml(report_int):
|
||||
res = service.execute(cr.dbname, uid, 'ir.translation',
|
||||
'_get_source', self.name2, 'xsl', lang, child.content)
|
||||
if res:
|
||||
child.setContent(res)
|
||||
child.setContent(res.encode('utf-8'))
|
||||
look_down(child.children, lang)
|
||||
child = child.next
|
||||
|
||||
@@ -218,7 +218,7 @@ from report_sxw import report_sxw
|
||||
def register_all(db):
|
||||
opj = os.path.join
|
||||
cr = db.cursor()
|
||||
cr.execute("SELECT * FROM ir_act_report_xml WHERE auto ORDER BY id")
|
||||
cr.execute("SELECT * FROM ir_act_report_xml WHERE auto=%s ORDER BY id", (True,))
|
||||
result = cr.dictfetchall()
|
||||
cr.close()
|
||||
for r in result:
|
||||
|
||||
@@ -166,7 +166,7 @@ class report_printscreen_list(report_int):
|
||||
col.setAttribute('para','yes')
|
||||
col.setAttribute('tree','no')
|
||||
if line[f] != None:
|
||||
txt = new_doc.createTextNode(line[f] or '')
|
||||
txt = new_doc.createTextNode(str(line[f] or ''))
|
||||
if temp[count] == 1:
|
||||
tsum[count] = float(tsum[count]) + float(line[f]);
|
||||
|
||||
|
||||
+16
-13
@@ -20,20 +20,23 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import base64, os, string
|
||||
|
||||
import netsvc
|
||||
import pooler, security, ir, tools
|
||||
import base64
|
||||
import logging
|
||||
|
||||
import threading, thread
|
||||
|
||||
import os
|
||||
import security
|
||||
import string
|
||||
import thread
|
||||
import threading
|
||||
import time
|
||||
import addons
|
||||
|
||||
import sql_db
|
||||
from tools.translate import _
|
||||
import addons
|
||||
import ir
|
||||
import netsvc
|
||||
import pooler
|
||||
import release
|
||||
import sql_db
|
||||
import tools
|
||||
|
||||
logging.basicConfig()
|
||||
|
||||
@@ -89,8 +92,8 @@ class db(netsvc.Service):
|
||||
mids = modobj.search(cr, 1, [('state', '=', 'installed')])
|
||||
modobj.update_translations(cr, 1, mids, lang)
|
||||
|
||||
cr.execute('UPDATE res_users SET password=%s, active=True WHERE login=%s', (
|
||||
user_password, 'admin'))
|
||||
cr.execute('UPDATE res_users SET password=%s, context_lang=%s, active=True WHERE login=%s', (
|
||||
user_password, lang, 'admin'))
|
||||
cr.execute('SELECT login, password, name ' \
|
||||
' FROM res_users ' \
|
||||
' ORDER BY login')
|
||||
@@ -459,11 +462,10 @@ class report_spool(netsvc.Service):
|
||||
self._reports[id] = {'uid': uid, 'result': False, 'state': False, 'exception': None}
|
||||
|
||||
def go(id, uid, ids, datas, context):
|
||||
cr = pooler.get_db(db).cursor()
|
||||
try:
|
||||
cr = pooler.get_db(db).cursor()
|
||||
obj = netsvc.LocalService('report.'+object)
|
||||
(result, format) = obj.create(cr, uid, ids, datas, context)
|
||||
cr.close()
|
||||
self._reports[id]['result'] = result
|
||||
self._reports[id]['format'] = format
|
||||
self._reports[id]['state'] = True
|
||||
@@ -477,6 +479,7 @@ class report_spool(netsvc.Service):
|
||||
'Exception: %s\n%s' % (str(exception), tb_s))
|
||||
self._reports[id]['exception'] = exception
|
||||
self._reports[id]['state'] = True
|
||||
cr.close()
|
||||
return True
|
||||
|
||||
thread.start_new_thread(go, (id, uid, ids, datas, context))
|
||||
|
||||
+12
-24
@@ -82,7 +82,10 @@ class Cursor(object):
|
||||
self._obj = self._cnx.cursor(cursor_factory=psycopg1cursor)
|
||||
self.autocommit(False)
|
||||
self.dbname = pool.dbname
|
||||
|
||||
|
||||
from inspect import stack
|
||||
self.__caller = tuple(stack()[2][1:3])
|
||||
|
||||
def __del__(self):
|
||||
if hasattr(self, '_obj'):
|
||||
# Oops. 'self' has not been closed explicitly.
|
||||
@@ -90,36 +93,26 @@ class Cursor(object):
|
||||
# but the database connection is not put back into the connection
|
||||
# pool, preventing some operation on the database like dropping it.
|
||||
# This can also lead to a server overload.
|
||||
log('Cursor not closed explicitly', netsvc.LOG_WARNING)
|
||||
msg = "Cursor not closed explicitly\n" \
|
||||
"Cursor was created at %s:%s" % self.__caller
|
||||
|
||||
log(msg, netsvc.LOG_WARNING)
|
||||
self.close()
|
||||
|
||||
@check
|
||||
def execute(self, query, params=None):
|
||||
if params is None:
|
||||
params=()
|
||||
if not isinstance(params, (tuple, list)):
|
||||
params = (params,)
|
||||
|
||||
def base_string(s):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode('utf-8')
|
||||
return s
|
||||
p=map(base_string, params)
|
||||
query = base_string(query)
|
||||
|
||||
self.count+=1
|
||||
if '%d' in query or '%f' in query:
|
||||
#import traceback
|
||||
#traceback.print_stack()
|
||||
log(query, netsvc.LOG_WARNING)
|
||||
log("SQL queries mustn't containt %d or %f anymore. Use only %s", netsvc.LOG_WARNING)
|
||||
if p:
|
||||
if params:
|
||||
query = query.replace('%d', '%s').replace('%f', '%s')
|
||||
|
||||
if self.sql_log:
|
||||
now = mdt.now()
|
||||
|
||||
try:
|
||||
res = self._obj.execute(query, p or None)
|
||||
res = self._obj.execute(query, params)
|
||||
except psycopg2.ProgrammingError, pe:
|
||||
logger= netsvc.Logger()
|
||||
logger.notifyChannel('sql_db', netsvc.LOG_ERROR, "Programming error: %s, in query %s" % (pe, query))
|
||||
@@ -140,12 +133,6 @@ class Cursor(object):
|
||||
self.sql_into_log[res_into.group(1)][1] += mdt.now() - now
|
||||
return res
|
||||
|
||||
def drop_view_if_exists(self, viewname):
|
||||
self._obj.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,))
|
||||
if self._obj.fetchone()[0]:
|
||||
self._obj.execute("DROP view %s" % (viewname,))
|
||||
self._obj.commit()
|
||||
|
||||
def print_log(self):
|
||||
def process(type):
|
||||
sqllogs = {'from':self.sql_from_log, 'into':self.sql_into_log}
|
||||
@@ -163,6 +150,7 @@ class Cursor(object):
|
||||
process('from')
|
||||
process('into')
|
||||
self.count = 0
|
||||
self.sql_log = False
|
||||
|
||||
@check
|
||||
def close(self):
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
"""
|
||||
SecureXMLRPCServer module using pyOpenSSL 0.5
|
||||
Extremely kludgey code written 0907.2002
|
||||
by Michal Wallace ( http://www.sabren.net/ )
|
||||
|
||||
This acts as a drop-in replacement for
|
||||
SimpleXMLRPCServer from the standard python
|
||||
library.
|
||||
|
||||
This code is in the public domain and is
|
||||
provided AS-IS WITH NO WARRANTY WHATSOEVER.
|
||||
"""
|
||||
import SocketServer
|
||||
import os, socket, sys
|
||||
import SimpleXMLRPCServer
|
||||
from OpenSSL import SSL
|
||||
import tools
|
||||
import netsvc
|
||||
|
||||
logger = netsvc.Logger()
|
||||
|
||||
|
||||
class SSLBugFix:
|
||||
"""
|
||||
SSL Connection tends to die on sendall,
|
||||
so I use send() as a workaround. This is
|
||||
called by socket._fileobject, which is needed
|
||||
so SocketServer (and kids) can treat the connection
|
||||
as a regular file.
|
||||
"""
|
||||
def __init__(self, conn):
|
||||
"""
|
||||
For some reason, I can't subclass Connection,
|
||||
so I'm making a proxy, instead.
|
||||
"""
|
||||
self.__dict__["conn"] = conn
|
||||
def __getattr__(self,name):
|
||||
return getattr(self.__dict__["conn"], name)
|
||||
def __setattr__(self,name, value):
|
||||
setattr(self.__dict__["conn"], name, value)
|
||||
|
||||
|
||||
# def sendall(self, data):
|
||||
# """
|
||||
# This is the bugfix. Connection.sendall() segfaults
|
||||
# on socket._fileobject.flush(), so just rewire it
|
||||
# to use send() instead.
|
||||
# """
|
||||
# self.__dict__["conn"].send(data)
|
||||
|
||||
def recv(self, bufsize):
|
||||
""" Another bugfix: SSL's recv() may raise
|
||||
recoverable exceptions, which simply need us to retry
|
||||
the call
|
||||
"""
|
||||
while True:
|
||||
try:
|
||||
return self.__dict__["conn"].recv(bufsize)
|
||||
except SSL.WantReadError:
|
||||
pass
|
||||
except SSL.WantWriteError:
|
||||
pass
|
||||
|
||||
def shutdown(self, how=1):
|
||||
"""
|
||||
This isn't part of the bugfix. SimpleXMLRpcServer.doPOST
|
||||
calls shutdown(1), and Connection.shutdown() doesn't take
|
||||
an argument. So we just discard it:
|
||||
"""
|
||||
self.__dict__["conn"].shutdown()
|
||||
|
||||
def accept(self):
|
||||
"""
|
||||
This is the other part of the shutdown() workaround.
|
||||
Since servers create new sockets, we have to infect
|
||||
them with our magic. :)
|
||||
"""
|
||||
c, a = self.__dict__["conn"].accept()
|
||||
return (SSLBugFix(c), a)
|
||||
|
||||
|
||||
|
||||
class SecureTCPServer(SocketServer.TCPServer):
|
||||
"""
|
||||
Just like TCPServer, but use a socket.
|
||||
This really ought to let you specify the key and certificate files.
|
||||
"""
|
||||
def __init__(self, server_address, RequestHandlerClass):
|
||||
SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass)
|
||||
|
||||
## Same as normal, but make it secure:
|
||||
ctx = SSL.Context(SSL.SSLv23_METHOD)
|
||||
ctx.set_options(SSL.OP_NO_SSLv2)
|
||||
|
||||
dir = os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]))
|
||||
sslkeyname = tools.config.get('sslkey',os.path.join(dir, 'server.pkey'))
|
||||
sslcertname = tools.config.get('sslcert',os.path.join(dir, 'server.cert'))
|
||||
try:
|
||||
ctx.use_privatekey_file (sslkeyname)
|
||||
ctx.use_certificate_file(sslcertname)
|
||||
except:
|
||||
logger.notifyChannel("init", netsvc.LOG_ERROR,"SSL key exception: " + str(sys.exc_info()))
|
||||
raise Exception, "No ssl keys found in %s, %s" % (sslcertname,sslkeyname)
|
||||
|
||||
self.socket = SSLBugFix(SSL.Connection(ctx, socket.socket(self.address_family,
|
||||
self.socket_type)))
|
||||
self.server_bind()
|
||||
self.server_activate()
|
||||
|
||||
def handle_error(self, request, client_address):
|
||||
""" Override the error handler
|
||||
"""
|
||||
import traceback
|
||||
logger.notifyChannel("init", netsvc.LOG_ERROR,"SSL Server error in request from %s:\n%s" %
|
||||
(client_address,traceback.format_exc()))
|
||||
|
||||
|
||||
class SecureXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
||||
def setup(self):
|
||||
"""
|
||||
We need to use socket._fileobject Because SSL.Connection
|
||||
doesn't have a 'dup'. Not exactly sure WHY this is, but
|
||||
this is backed up by comments in socket.py and SSL/connection.c
|
||||
"""
|
||||
self.connection = self.request # for doPOST
|
||||
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
|
||||
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
|
||||
|
||||
|
||||
class SecureXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, SecureTCPServer):
|
||||
encoding = None
|
||||
allow_none = False
|
||||
def __init__(self, addr,
|
||||
requestHandler=SecureXMLRPCRequestHandler,
|
||||
logRequests=1):
|
||||
"""
|
||||
This is the exact same code as SimpleXMLRPCServer.__init__
|
||||
except it calls SecureTCPServer.__init__ instead of plain
|
||||
old TCPServer.__init__
|
||||
"""
|
||||
self.funcs = {}
|
||||
self.logRequests = logRequests
|
||||
self.instance = None
|
||||
SecureTCPServer.__init__(self, addr, requestHandler)
|
||||
|
||||
def handle_error(self, request, client_address):
|
||||
""" Override the error handler
|
||||
"""
|
||||
import traceback
|
||||
e_type, e_value, e_traceback = sys.exc_info()
|
||||
logger.notifyChannel("init", netsvc.LOG_ERROR,"SSL Request handler error in request from %s: %s\n%s" %
|
||||
(client_address,str(e_type),traceback.format_exc()))
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -1,14 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICNDCCAZ0CAQEwDQYJKoZIhvcNAQEEBQAweTEQMA4GA1UEChMHVGlueUVSUDEM
|
||||
MAoGA1UECxMDRVJQMRkwFwYJKoZIhvcNAQkBFgpmcEB0aW55LmJlMRAwDgYDVQQH
|
||||
EwdXYWxoYWluMQswCQYDVQQIEwJCVzELMAkGA1UEBhMCQkUxEDAOBgNVBAMTB1Rp
|
||||
bnlFUlAwHhcNMDYwNTI0MDgzODUxWhcNMDcwNTI0MDgzODUxWjBMMQswCQYDVQQG
|
||||
EwJCRTELMAkGA1UECBMCQlcxEDAOBgNVBAoTB1RpbnlFUlAxDDAKBgNVBAsTA0VS
|
||||
UDEQMA4GA1UEAxMHVGlueUVSUDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
|
||||
xzIDlU2PrczPsgXtxCskYxuwMPgNCNSCBfWsUZ9nJzlZfRAEXEq4LxaTPIgkzkIF
|
||||
82bmJLgFz6/CyCFid4mkBLQBj30Opp2Vco39WRncNKHKxbk+/wZpZtQ0bSpvf+F4
|
||||
MBqCLldYIqsoyenombVCb8X62IUu0ENF1wR22owvyKcCAwEAATANBgkqhkiG9w0B
|
||||
AQQFAAOBgQB2yUqJ3gbQ8I6rcmaVJlcLDHfC5w1Jr1cUzcJevOPh3wygSZYYoUoe
|
||||
yeYlzEag/DpPSHyRiJJVOKdiwU0yfmZPhfDNtDiBr47bz8qzIsYq5VeMmSeXrq/f
|
||||
AA3iI4xE8YFzJHWtiBCqqyUok+j9pVad7iV7+UVIePHZLEkGGWIjDA==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,15 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQDHMgOVTY+tzM+yBe3EKyRjG7Aw+A0I1IIF9axRn2cnOVl9EARc
|
||||
SrgvFpM8iCTOQgXzZuYkuAXPr8LIIWJ3iaQEtAGPfQ6mnZVyjf1ZGdw0ocrFuT7/
|
||||
Bmlm1DRtKm9/4XgwGoIuV1giqyjJ6eiZtUJvxfrYhS7QQ0XXBHbajC/IpwIDAQAB
|
||||
AoGAVwAxMHS/3FkoHckZICT3r5HYUosEpmaqo4+5w6yrkSYrP8RPI0A/UdG6XSXZ
|
||||
bXzIvJakzkTRxPQvTtnF+A/V4rF9hxwB8cGXSywv5eDGmZ91qIsxY7Sv99VqSKNH
|
||||
dNr9aZHloTvI51e/oramIJ/O3A+TbAS5i+u1DJC2IIFJcAECQQD8iRPTlPIqzjYD
|
||||
Lg7KYGvwW9TE4ONAhC86kJbzV5o3amlV5duJgnkl/mNlfN1ihA7f3Gx9dfCjfRKp
|
||||
V1rcjtCBAkEAye2aMw2v1m+MEqcPxyTUzVf5Y8BIXWbk15T43czXec9YclZSOBCX
|
||||
Dgv4a3Fk+yxQUE0cZUH0U4FJq6mTgpuFJwJASFqZ9KATNlJ4xTZ4BGHV6zrUXkg0
|
||||
tDJrObNdnID37XKulW7TFLXuMgWNwvEgmO5POLJ13whglubp5tzhapn8gQJAJz9Z
|
||||
U0b7wFAaB54VAP31ppvMy0iaSB0xqX05CdNAplpYtJB2lpMS6RYGiMuXdwJb8d+q
|
||||
/ztcg8aDTSw+kYoszQJBAPBrt694VkGT1k9Be6e5wyVDrE05bkHhFxPk/HMeWMDX
|
||||
sZqHPs9vVaLBqu/uU84FdwRMOV71RG90g6eUEl7HWsg=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -27,6 +27,7 @@ from graph import graph
|
||||
from amount_to_text import *
|
||||
from amount_to_text_en import *
|
||||
from pdf_utils import *
|
||||
from sql import *
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
+65
-23
@@ -28,11 +28,19 @@ import netsvc
|
||||
import logging
|
||||
import release
|
||||
|
||||
def check_ssl():
|
||||
try:
|
||||
from OpenSSL import SSL
|
||||
import socket
|
||||
|
||||
return hasattr(socket, 'ssl')
|
||||
except:
|
||||
return False
|
||||
|
||||
class configmanager(object):
|
||||
def __init__(self, fname=None):
|
||||
self.options = {
|
||||
'email_from':False,
|
||||
'verbose': False,
|
||||
'interface': '', # this will bind the server to all interfaces
|
||||
'port': '8069',
|
||||
'netinterface': '',
|
||||
@@ -58,28 +66,29 @@ class configmanager(object):
|
||||
'import_partial': "",
|
||||
'pidfile': None,
|
||||
'logfile': None,
|
||||
'secure': False,
|
||||
'smtp_server': 'localhost',
|
||||
'smtp_user': False,
|
||||
'smtp_port':25,
|
||||
'smtp_password': False,
|
||||
'stop_after_init': False, # this will stop the server after initialization
|
||||
'price_accuracy': 2,
|
||||
|
||||
'secure' : False,
|
||||
'syslog' : False,
|
||||
'log_level': logging.INFO,
|
||||
'assert_exit_level': logging.WARNING, # level above which a failed assert will be raise
|
||||
}
|
||||
|
||||
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC')])
|
||||
|
||||
hasSSL = check_ssl()
|
||||
|
||||
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x))
|
||||
for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC', 'NOTSET')])
|
||||
|
||||
version = "%s %s" % (release.description, release.version)
|
||||
parser = optparse.OptionParser(version=version)
|
||||
|
||||
parser.add_option("-c", "--config", dest="config", help="specify alternate config file")
|
||||
parser.add_option("-s", "--save", action="store_true", dest="save", default=False, help="save configuration to ~/.openerp_serverrc")
|
||||
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="enable debugging")
|
||||
parser.add_option("--pidfile", dest="pidfile", help="file where the server pid will be stored")
|
||||
parser.add_option("--logfile", dest="logfile", help="file where the server log will be stored")
|
||||
|
||||
parser.add_option("-n", "--interface", dest="interface", help="specify the TCP IP address")
|
||||
parser.add_option("-p", "--port", dest="port", help="specify the TCP port")
|
||||
@@ -94,17 +103,38 @@ class configmanager(object):
|
||||
# stops the server from launching after initialization
|
||||
parser.add_option("--stop-after-init", action="store_true", dest="stop_after_init", default=False, help="stop the server after it initializes")
|
||||
parser.add_option('--debug', dest='debug_mode', action='store_true', default=False, help='enable debug mode')
|
||||
parser.add_option('--log-level', dest='log_level', type='choice', choices=loglevels.keys(), help='specify the level of the logging. Accepted values: ' + str(loglevels.keys()))
|
||||
parser.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=loglevels.keys(), help="specify the level at which a failed assertion will stop the server. Accepted values: " + str(loglevels.keys()))
|
||||
parser.add_option("-S", "--secure", dest="secure", action="store_true", help="launch server over https instead of http", default=False)
|
||||
if hasSSL:
|
||||
group = optparse.OptionGroup(parser, "SSL Configuration")
|
||||
group.add_option("-S", "--secure", dest="secure", action="store_true", help="launch server over https instead of http", default=False)
|
||||
group.add_option("--cert-file", dest="secure_cert_file",
|
||||
default="server.cert",
|
||||
help="specify the certificate file for the SSL connection")
|
||||
group.add_option("--pkey-file", dest="secure_pkey_file",
|
||||
default="server.pkey",
|
||||
help="specify the private key file for the SSL connection")
|
||||
parser.add_option_group(group)
|
||||
|
||||
parser.add_option('--email-from', dest='email_from', default='', help='specify the SMTP email address for sending email')
|
||||
parser.add_option('--smtp', dest='smtp_server', default='', help='specify the SMTP server for sending email')
|
||||
parser.add_option('--smtp-port', dest='smtp_port', default='25', help='specify the SMTP port')
|
||||
parser.add_option('--smtp-ssl', dest='smtp_ssl', default='', help='specify the SMTP server support SSL or not')
|
||||
parser.add_option('--smtp-user', dest='smtp_user', default='', help='specify the SMTP username for sending email')
|
||||
parser.add_option('--smtp-password', dest='smtp_password', default='', help='specify the SMTP password for sending email')
|
||||
parser.add_option('--price_accuracy', dest='price_accuracy', default='2', help='specify the price accuracy')
|
||||
# Logging Group
|
||||
group = optparse.OptionGroup(parser, "Logging Configuration")
|
||||
group.add_option("--logfile", dest="logfile", help="file where the server log will be stored")
|
||||
group.add_option("--syslog", action="store_true", dest="syslog",
|
||||
default=False, help="Send the log to the syslog server")
|
||||
group.add_option('--log-level', dest='log_level', type='choice', choices=loglevels.keys(),
|
||||
help='specify the level of the logging. Accepted values: ' + str(loglevels.keys()))
|
||||
parser.add_option_group(group)
|
||||
|
||||
# SMTP Group
|
||||
group = optparse.OptionGroup(parser, "SMTP Configuration")
|
||||
group.add_option('--email-from', dest='email_from', default='', help='specify the SMTP email address for sending email')
|
||||
group.add_option('--smtp', dest='smtp_server', default='', help='specify the SMTP server for sending email')
|
||||
group.add_option('--smtp-port', dest='smtp_port', default='25', help='specify the SMTP port')
|
||||
if hasSSL:
|
||||
group.add_option('--smtp-ssl', dest='smtp_ssl', default='', help='specify the SMTP server support SSL or not')
|
||||
group.add_option('--smtp-user', dest='smtp_user', default='', help='specify the SMTP username for sending email')
|
||||
group.add_option('--smtp-password', dest='smtp_password', default='', help='specify the SMTP password for sending email')
|
||||
group.add_option('--price_accuracy', dest='price_accuracy', default='2', help='specify the price accuracy')
|
||||
parser.add_option_group(group)
|
||||
|
||||
group = optparse.OptionGroup(parser, "Modules related options")
|
||||
group.add_option("-g", "--upgrade", action="store_true", dest="upgrade", default=False, help="Upgrade/install/uninstall modules")
|
||||
@@ -157,19 +187,31 @@ class configmanager(object):
|
||||
# the same for the pidfile
|
||||
if self.options['pidfile'] in ('None', 'False'):
|
||||
self.options['pidfile'] = False
|
||||
|
||||
for arg in ('interface', 'port', 'db_name', 'db_user', 'db_password', 'db_host',
|
||||
'db_port', 'logfile', 'pidfile', 'secure', 'smtp_ssl', 'smtp_port', 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy', 'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path'):
|
||||
|
||||
keys = ['interface', 'port', 'db_name', 'db_user', 'db_password', 'db_host',
|
||||
'db_port', 'logfile', 'pidfile', 'smtp_port',
|
||||
'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy',
|
||||
'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path']
|
||||
|
||||
if hasSSL:
|
||||
keys.extend(['smtp_ssl', 'secure_cert_file', 'secure_pkey_file'])
|
||||
|
||||
for arg in keys:
|
||||
if getattr(opt, arg):
|
||||
self.options[arg] = getattr(opt, arg)
|
||||
|
||||
for arg in ('language', 'translate_out', 'translate_in',
|
||||
'upgrade', 'verbose', 'debug_mode',
|
||||
'stop_after_init', 'without_demo', 'netrpc', 'xmlrpc'):
|
||||
keys = ['language', 'translate_out', 'translate_in', 'upgrade', 'debug_mode',
|
||||
'stop_after_init', 'without_demo', 'netrpc', 'xmlrpc', 'syslog']
|
||||
|
||||
if hasSSL:
|
||||
keys.append('secure')
|
||||
|
||||
for arg in keys:
|
||||
self.options[arg] = getattr(opt, arg)
|
||||
|
||||
|
||||
if opt.assert_exit_level:
|
||||
self.options['assert_exit_level'] = loglevels[opt.assert_exit_level]
|
||||
|
||||
if opt.log_level:
|
||||
self.options['log_level'] = loglevels[opt.log_level]
|
||||
|
||||
|
||||
@@ -669,10 +669,7 @@ form: module.record_id""" % (xml_id,)
|
||||
rec_id = rec.getAttribute("id").encode('ascii')
|
||||
self._test_xml_id(rec_id)
|
||||
|
||||
# if not rec_id and not self.isnoupdate(data_node):
|
||||
# print "Warning", rec_model
|
||||
|
||||
if self.isnoupdate(data_node) and not self.mode in ('init','update'):
|
||||
if self.isnoupdate(data_node) and self.mode != 'init':
|
||||
# check if the xml record has an id string
|
||||
if rec_id:
|
||||
id = self.pool.get('ir.model.data')._update_dummy(cr, self.uid, rec_model, self.module, rec_id)
|
||||
@@ -737,7 +734,7 @@ form: module.record_id""" % (xml_id,)
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, rec_model, self.module, res, rec_id or False, not self.isnoupdate(data_node), noupdate=self.isnoupdate(data_node), mode=self.mode )
|
||||
if rec_id:
|
||||
self.idref[rec_id] = int(id)
|
||||
if config.get('i mport_partial', False):
|
||||
if config.get('import_partial', False):
|
||||
cr.commit()
|
||||
return rec_model, id
|
||||
|
||||
|
||||
+52
-11
@@ -542,11 +542,20 @@ class cache(object):
|
||||
self.timeout = timeout
|
||||
self.skiparg = skiparg
|
||||
self.multi = multi
|
||||
self.lasttime = time.time()
|
||||
self.cache = {}
|
||||
|
||||
def __call__(self, fn):
|
||||
arg_names = inspect.getargspec(fn)[0][self.skiparg:]
|
||||
|
||||
def cached_result(self2, cr=None, *args, **kwargs):
|
||||
if time.time()-self.timeout > self.lasttime:
|
||||
self.lasttime = time.time()
|
||||
t = time.time()-self.timeout
|
||||
for key in self.cache:
|
||||
if self.cache[key][1]<t:
|
||||
del self.cache[key]
|
||||
|
||||
if cr is None:
|
||||
self.cache = {}
|
||||
return True
|
||||
@@ -563,22 +572,44 @@ class cache(object):
|
||||
kwargs2[k] = tuple(kwargs2[k])
|
||||
elif not is_hashable(kwargs2[k]):
|
||||
kwargs2[k] = repr(kwargs2[k])
|
||||
|
||||
if self.multi:
|
||||
kwargs3 = kwargs2.copy()
|
||||
notincache = []
|
||||
result = {}
|
||||
for id in kwargs3[self.multi]:
|
||||
kwargs2[self.multi] = [id]
|
||||
kwargs4 = kwargs2.items()
|
||||
kwargs4.sort()
|
||||
|
||||
# Work out key as a tuple of ('argname', value) pairs
|
||||
key = (('dbname', cr.dbname),) + tuple(kwargs4)
|
||||
if key in self.cache:
|
||||
result[id] = self.cache[key][0]
|
||||
else:
|
||||
notincache.append(id)
|
||||
|
||||
|
||||
|
||||
if notincache:
|
||||
kwargs2[self.multi] = notincache
|
||||
result2 = fn(self2, cr, *args[2:self.skip], **kwargs3)
|
||||
for id in result2:
|
||||
kwargs2[self.multi] = [id]
|
||||
kwargs4 = kwargs2.items()
|
||||
kwargs4.sort()
|
||||
key = (('dbname', cr.dbname),) + tuple(kwargs4)
|
||||
self.cache[key] = result2[id]
|
||||
result.updat(result2)
|
||||
return result
|
||||
|
||||
kwargs2 = kwargs2.items()
|
||||
kwargs2.sort()
|
||||
|
||||
# Work out key as a tuple of ('argname', value) pairs
|
||||
key = (('dbname', cr.dbname),) + tuple(kwargs2)
|
||||
|
||||
# Check cache and return cached value if possible
|
||||
if key in self.cache:
|
||||
(value, last_time) = self.cache[key]
|
||||
mintime = time.time() - self.timeout
|
||||
if self.timeout <= 0 or mintime <= last_time:
|
||||
return value
|
||||
return self.cache[key][0]
|
||||
|
||||
# Work out new value, cache it and return it
|
||||
# FIXME Should copy() this value to avoid futur modifications of the cache ?
|
||||
# FIXME What about exceptions ?
|
||||
result = fn(self2, cr, *args, **kwargs)
|
||||
|
||||
self.cache[key] = (result, time.time())
|
||||
@@ -598,6 +629,10 @@ def ustr(value):
|
||||
@return: unicode string
|
||||
"""
|
||||
|
||||
if (value is None) or (value is False):
|
||||
return value
|
||||
if not value:
|
||||
return u''
|
||||
if isinstance(value, unicode):
|
||||
return value
|
||||
|
||||
@@ -612,6 +647,7 @@ def ustr(value):
|
||||
|
||||
def get_languages():
|
||||
languages={
|
||||
'ar_AR': u'Arabic / الْعَرَبيّة',
|
||||
'bg_BG': u'Bulgarian / български',
|
||||
'ca_ES': u'Catalan / Català',
|
||||
'cs_CZ': u'Czech / Čeština',
|
||||
@@ -631,12 +667,14 @@ def get_languages():
|
||||
'it_IT': u'Italian / Italiano',
|
||||
'lt_LT': u'Lithuanian / Lietuvių kalba',
|
||||
'nl_NL': u'Dutch / Nederlands',
|
||||
'pl_PL': u'Polish / Język polski',
|
||||
'pt_BR': u'Portugese (BR) / português (BR)',
|
||||
'pt_PT': u'Portugese / português',
|
||||
'ro_RO': u'Romanian / limba română',
|
||||
'ru_RU': u'Russian / русский язык',
|
||||
'sl_SL': u'Slovenian / slovenščina',
|
||||
'sv_SE': u'Swedish / svenska',
|
||||
'tr_TR': u'Turkish / Türkçe',
|
||||
'uk_UK': u'Ukrainian / украї́нська мо́ва',
|
||||
'zh_CN': u'Chinese (CN) / 简体中文' ,
|
||||
'zh_TW': u'Chinese (TW) / 正體字',
|
||||
@@ -748,7 +786,10 @@ def debug(what):
|
||||
st = stack()[1]
|
||||
param = re.split("debug *\((.+)\)", st[4][0].strip())[1].strip()
|
||||
while param.count(')') > param.count('('): param = param[:param.rfind(')')]
|
||||
netsvc.Logger().notifyChannel(st[3], netsvc.LOG_DEBUG, "%s = %s" % (param, pformat(what)))
|
||||
what = pformat(what)
|
||||
if param != what:
|
||||
what = "%s = %s" % (param, what)
|
||||
netsvc.Logger().notifyChannel(st[3], netsvc.LOG_DEBUG, what)
|
||||
|
||||
|
||||
icons = map(lambda x: (x,x), ['STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',
|
||||
|
||||
+13
-12
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -26,7 +26,7 @@
|
||||
import re
|
||||
|
||||
component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE)
|
||||
replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c','dev':'@'}.get
|
||||
replace = {'pre':'c', 'preview':'c','-':'final-','_':'final-','rc':'c','dev':'@'}.get
|
||||
|
||||
def _parse_version_parts(s):
|
||||
for part in component_re.split(s):
|
||||
@@ -82,15 +82,16 @@ def parse_version(s):
|
||||
return tuple(parts)
|
||||
|
||||
if __name__ == '__main__':
|
||||
pvs = []
|
||||
for v in ('0', '4.2', '4.2.3.4', '5.0.0-alpha', '5.0.0-rc1', '5.0.0-rc1.1', '5.0.0'):
|
||||
pv = parse_version(v)
|
||||
print v, pv
|
||||
pvs.append(pv)
|
||||
pvs = []
|
||||
for v in ('0', '4.2', '4.2.3.4', '5.0.0-alpha', '5.0.0-rc1', '5.0.0-rc1.1', '5.0.0_rc2', '5.0.0'):
|
||||
pv = parse_version(v)
|
||||
print v, pv
|
||||
pvs.append(pv)
|
||||
|
||||
def cmp(a, b):
|
||||
assert(a < b)
|
||||
return b
|
||||
def cmp(a, b):
|
||||
print a, b
|
||||
assert(a < b)
|
||||
return b
|
||||
|
||||
reduce(cmp, pvs)
|
||||
|
||||
reduce(cmp, pvs)
|
||||
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
import SecureXMLRPCServer
|
||||
def drop_view_if_exists(cr, viewname):
|
||||
cr.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,))
|
||||
if cr.fetchone()[0]:
|
||||
cr.execute("DROP view %s" % (viewname,))
|
||||
cr.commit()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -386,10 +386,10 @@ def trans_generate(lang, modules, dbname=None):
|
||||
if result['type'] != 'form':
|
||||
continue
|
||||
name = "%s,%s" % (encode(obj.wiz_name), state_name)
|
||||
|
||||
|
||||
def_params = {
|
||||
'string': ('wizard_field', lambda s: [encode(s)]),
|
||||
'selection': ('selection', lambda s: [encode(e[1]) for e in s]),
|
||||
'selection': ('selection', lambda s: [encode(e[1]) for e in (callable(s) and s(None, cr, uid, {}) or s)]),
|
||||
'help': ('help', lambda s: [encode(s)]),
|
||||
}
|
||||
|
||||
@@ -468,9 +468,9 @@ def trans_generate(lang, modules, dbname=None):
|
||||
d = xml.dom.minidom.parseString(xmlstr)
|
||||
for t in parse_func(d.documentElement):
|
||||
push_translation(module, report_type, name, 0, t)
|
||||
except IOError:
|
||||
except IOError, xml.dom.expatbuilder.expat.ExpatError:
|
||||
if fname:
|
||||
logger.notifyChannel("init", netsvc.LOG_WARNING, "couldn't export translation for report %s %s %s" % (name, report_type, fname))
|
||||
logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't export translation for report %s %s %s" % (name, report_type, fname))
|
||||
|
||||
for constraint in pool.get(model)._constraints:
|
||||
msg = constraint[1]
|
||||
|
||||
@@ -26,14 +26,16 @@
|
||||
import netsvc
|
||||
|
||||
def log(cr,ident,act_id,info=''):
|
||||
msg = """
|
||||
res_type: %r
|
||||
res_id: %d
|
||||
uid: %d
|
||||
act_id: %d
|
||||
info: %s
|
||||
""" % (ident[1], ident[2], ident[0], act_id, info)
|
||||
netsvc.Logger().notifyChannel('wkf_log', netsvc.LOG_DEBUG, msg)
|
||||
return
|
||||
# msg = """
|
||||
#res_type: %r
|
||||
#res_id: %d
|
||||
#uid: %d
|
||||
#act_id: %d
|
||||
#info: %s
|
||||
#""" % (ident[1], ident[2], ident[0], act_id, info)
|
||||
|
||||
#netsvc.Logger().notifyChannel('wkf_log', netsvc.LOG_DEBUG, msg)
|
||||
|
||||
#cr.execute('insert into wkf_logs (res_type, res_id, uid, act_id, time, info) values (%s,%s,%s,%s,current_time,%s)', (ident[1],int(ident[2]),int(ident[0]),int(act_id),info))
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ db_user = tinyerp
|
||||
db_password = False
|
||||
; Uncomment these for xml-rpc over SSL
|
||||
; secure = True
|
||||
; sslcert = /etc/openerp/server.cert
|
||||
; sslkey = /etc/openerp/server.key
|
||||
; secure_cert_file = /etc/openerp/server.cert
|
||||
; secure_pkey_file = /etc/openerp/server.key
|
||||
root_path = None
|
||||
soap = False
|
||||
translate_modules = ['all']
|
||||
|
||||
@@ -27,9 +27,6 @@
|
||||
!error "Do not forget to specify the version of OpenERP - /DVERSION=<VERSION>"
|
||||
!endif
|
||||
|
||||
;--------------------------------
|
||||
;Include Modern UI
|
||||
|
||||
!include "MUI.nsh"
|
||||
|
||||
;--------------------------------
|
||||
@@ -45,7 +42,7 @@ SetCompress auto
|
||||
InstallDir "$PROGRAMFILES\OpenERP Server"
|
||||
|
||||
;Get installation folder from registry if available
|
||||
InstallDirRegKey HKCU "Software\OpenERP Server" ""
|
||||
InstallDirRegKey HKLM "Software\OpenERP Server" ""
|
||||
|
||||
BrandingText "OpenERP Server ${VERSION}"
|
||||
|
||||
@@ -63,6 +60,12 @@ Var STARTMENU_FOLDER
|
||||
|
||||
!define MUI_ABORTWARNING
|
||||
|
||||
!define REGKEY "SOFTWARE\$(^Name)"
|
||||
!define MUI_LANGDLL_REGISTRY_ROOT HKLM
|
||||
!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY}
|
||||
!define MUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage
|
||||
|
||||
!insertmacro MUI_RESERVEFILE_LANGDLL
|
||||
;--------------------------------
|
||||
;Pages
|
||||
|
||||
@@ -73,14 +76,15 @@ Var STARTMENU_FOLDER
|
||||
!define MUI_HEADERIMAGE_BITMAP_NOSTRETCH
|
||||
!define MUI_HEADER_TRANSPARENT_TEXT ""
|
||||
!define MUI_HEADERIMAGE_BITMAP ".\pixmaps\openerp-slogan.bmp"
|
||||
!define MUI_LICENSEPAGE_TEXT_BOTTOM "Usually, a proprietary license provides with the software: limited number of users, limited in time usage, etc. This Open Source license is the opposite: it garantees you the right to use, copy, study, distribute and modify Open ERP for free."
|
||||
!define MUI_LICENSEPAGE_TEXT_BOTTOM "$(LicenseText)"
|
||||
!define MUI_LICENSEPAGE_BUTTON "$(LicenseNext)"
|
||||
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_LICENSE "doc\License.rtf"
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
|
||||
;Start Menu Folder Page Configuration
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\OpenERP Server"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "OpenERP Server"
|
||||
|
||||
@@ -91,7 +95,7 @@ Var STARTMENU_FOLDER
|
||||
!define MUI_FINISHPAGE_NOAUTOCLOSE
|
||||
!define MUI_FINISHPAGE_RUN
|
||||
!define MUI_FINISHPAGE_RUN_CHECKED
|
||||
!define MUI_FINISHPAGE_RUN_TEXT "Start OpenERP Server"
|
||||
!define MUI_FINISHPAGE_RUN_TEXT "$(FinishPageText)"
|
||||
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
|
||||
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
|
||||
!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\README.txt
|
||||
@@ -106,6 +110,7 @@ Var STARTMENU_FOLDER
|
||||
;Languages
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
|
||||
!macro CreateInternetShortcut FILENAME URL
|
||||
WriteINIStr "${FILENAME}.url" "InternetShortcut" "URL" "${URL}"
|
||||
@@ -114,10 +119,26 @@ Var STARTMENU_FOLDER
|
||||
;--------------------------------
|
||||
;Installer Sections
|
||||
Function .onInit
|
||||
!ifndef ALLINONE
|
||||
;Language selection dialog
|
||||
Push ""
|
||||
Push ${LANG_ENGLISH}
|
||||
Push English
|
||||
Push ${LANG_FRENCH}
|
||||
Push French
|
||||
Push A ; A means auto count languages
|
||||
; for the auto count to work the first empty push (Push "") must remain
|
||||
LangDLL::LangDialog "Installer Language" "Please select the language of the installer"
|
||||
|
||||
Pop $LANGUAGE
|
||||
StrCmp $LANGUAGE "cancel" 0 +2
|
||||
Abort
|
||||
!endif
|
||||
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKCU "Software\OpenERP Server" ""
|
||||
ReadRegStr $0 HKLM "Software\OpenERP Server" ""
|
||||
IfErrors DoInstall 0
|
||||
MessageBox MB_OK "Can not install the Open ERP Server because a previous installation already exists on this system. Please uninstall your current installation and relaunch this setup wizard."
|
||||
MessageBox MB_OK "$(CannotInstallServerText)"
|
||||
Quit
|
||||
DoInstall:
|
||||
FunctionEnd
|
||||
@@ -137,11 +158,15 @@ Section "OpenERP Server" SecOpenERPServer
|
||||
File "win32\stop.bat"
|
||||
|
||||
;Store installation folder
|
||||
WriteRegStr HKCU "Software\OpenERP Server" "" $INSTDIR
|
||||
WriteRegStr HKLM "Software\OpenERP Server" "" $INSTDIR
|
||||
|
||||
!ifndef ALLINONE
|
||||
;Create uninstaller
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenERP Server" "DisplayName" "OpenERP Server ${VERSION}"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenERP Server" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||
!else
|
||||
WriteRegStr HKLM "Software\OpenERP AllInOne" "UninstallServer" "$INSTDIR\Uninstall.exe"
|
||||
!endif
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||
@@ -152,7 +177,9 @@ Section "OpenERP Server" SecOpenERPServer
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Stop service.lnk" "$INSTDIR\service\stop.bat"
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Edit config.lnk" "notepad.exe" "$INSTDIR\openerp-server.conf"
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\View log.lnk" "notepad.exe" "$INSTDIR\openerp-server.log"
|
||||
!ifndef ALLINONE
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\uninstall.exe"
|
||||
!endif
|
||||
!insertmacro CreateInternetShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Forum" "http://www.openerp.com/forum"
|
||||
!insertmacro CreateInternetShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Translation" "https://translations.launchpad.net/openobject"
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
@@ -164,13 +191,6 @@ SectionEnd
|
||||
|
||||
;Descriptions
|
||||
|
||||
;Language strings
|
||||
LangString DESC_SecOpenERPServer ${LANG_ENGLISH} "OpenERP Server."
|
||||
|
||||
;Assign language strings to sections
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SecOpenERPServer} $(DESC_SecOpenERPServer)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
|
||||
;--------------------------------
|
||||
;Uninstaller Section
|
||||
@@ -186,7 +206,9 @@ Section "Uninstall"
|
||||
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Forum.url"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Translation.url"
|
||||
!ifndef ALLINONE
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
!endif
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\OpenERP Server.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Start service.lnk"
|
||||
@@ -208,8 +230,12 @@ Section "Uninstall"
|
||||
|
||||
startMenuDeleteLoopDone:
|
||||
|
||||
!ifndef ALLINONE
|
||||
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenERP Server"
|
||||
DeleteRegKey /ifempty HKCU "Software\OpenERP Server"
|
||||
!else
|
||||
DeleteRegKey HKLM "Software\OpenERP AllInOne\UninstallServer"
|
||||
!endif
|
||||
DeleteRegKey /ifempty HKLM "Software\OpenERP Server"
|
||||
|
||||
SectionEnd
|
||||
|
||||
@@ -217,3 +243,24 @@ Function LaunchLink
|
||||
nsExec::Exec "net start openerp-service"
|
||||
FunctionEnd
|
||||
|
||||
LangString LicenseText ${LANG_ENGLISH} "Usually, a proprietary license is provided with the software: limited number of users, limited in time usage, etc. This Open Source license is the opposite: it garantees you the right to use, copy, study, distribute and modify Open ERP for free."
|
||||
LangString LicenseText ${LANG_FRENCH} "Normalement, une licence propriétaire est fournie avec le logiciel: limitation du nombre d'utilisateurs, limitation dans le temps, etc. Cette licence Open Source est l'opposé: Elle vous garantie le droit d'utiliser, de copier, d'étudier, de distribuer et de modifier Open ERP librement."
|
||||
|
||||
LangString LicenseNext ${LANG_ENGLISH} "Next >"
|
||||
LangString LicenseNext ${LANG_FRENCH} "Suivant >"
|
||||
|
||||
LangString FinishPageText ${LANG_ENGLISH} "Start OpenERP Server"
|
||||
LangString FinishPageText ${LANG_FRENCH} "Lancer le serveur OpenERP"
|
||||
|
||||
;Language strings
|
||||
LangString DESC_SecOpenERPServer ${LANG_ENGLISH} "OpenERP Server."
|
||||
LangString DESC_SecOpenERPServer ${LANG_FRENCH} "Serveur OpenERP."
|
||||
|
||||
LangString CannotInstallServerText ${LANG_ENGLISH} "Can not install the Open ERP Server because a previous installation already exists on this system. Please uninstall your current installation and relaunch this setup wizard."
|
||||
LangString CannotInstallServerText ${LANG_FRENCH} "Ne peut pas installer le serveur Open ERP parce qu'une installation existe déjà sur ce système. S'il vous plait, désinstallez votre installation actuelle et relancer l'installeur."
|
||||
|
||||
|
||||
;Assign language strings to sections
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SecOpenERPServer} $(DESC_SecOpenERPServer)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
@@ -85,6 +85,9 @@ def data_files():
|
||||
os.chdir('..')
|
||||
for (dp,dn,names) in os.walk('doc'):
|
||||
files.append((dp, map(lambda x: opj(dp, x), names)))
|
||||
files.append(('.', [opj('bin', 'import_xml.rng'),
|
||||
opj('bin', 'server.pkey'),
|
||||
opj('bin', 'server.cert')]))
|
||||
else:
|
||||
man_directory = opj('share', 'man')
|
||||
files.append((opj(man_directory, 'man1'), ['man/openerp-server.1']))
|
||||
@@ -97,6 +100,10 @@ def data_files():
|
||||
|
||||
openerp_site_packages = opj('lib', 'python%s' % py_short_version, 'site-packages', 'openerp-server')
|
||||
|
||||
files.append((openerp_site_packages, [opj('bin', 'import_xml.rng'),
|
||||
opj('bin', 'server.pkey'),
|
||||
opj('bin', 'server.cert')]))
|
||||
|
||||
for addon in find_addons():
|
||||
add_path = addon.replace('.', os.path.sep).replace('openerp-server', 'bin', 1)
|
||||
addon_path = opj('lib', 'python%s' % py_short_version, 'site-packages', add_path.replace('bin', 'openerp-server', 1))
|
||||
@@ -132,7 +139,8 @@ options = {
|
||||
"packages": ["lxml", "lxml.builder", "lxml._elementpath", "lxml.etree",
|
||||
"lxml.objectify", "decimal", "xml", "xml.dom", "xml.xpath",
|
||||
"encodings","mx.DateTime","wizard","pychart","PIL", "pyparsing",
|
||||
"pydot","asyncore","asynchat", "reportlab", "vobject", "HTMLParser"],
|
||||
"pydot","asyncore","asynchat", "reportlab", "vobject",
|
||||
"HTMLParser", "OpenSSL", "select"],
|
||||
"excludes" : ["Tkconstants","Tkinter","tcl"],
|
||||
}
|
||||
}
|
||||
@@ -155,7 +163,6 @@ setup(name = name,
|
||||
'openerp-server.addons',
|
||||
'openerp-server.ir',
|
||||
'openerp-server.osv',
|
||||
'openerp-server.ssl',
|
||||
'openerp-server.service',
|
||||
'openerp-server.tools',
|
||||
'openerp-server.report',
|
||||
|
||||
Reference in New Issue
Block a user