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:
commit
a8229141bc
|
@ -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,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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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,9 +1308,9 @@
|
|||
</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">
|
||||
|
@ -1284,18 +1318,18 @@
|
|||
<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"/>
|
||||
|
|
|
@ -383,9 +383,8 @@ class actions_server(osv.osv):
|
|||
_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,8 +75,7 @@ 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 = []
|
||||
|
@ -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
|
||||
|
|
|
209
bin/netsvc.py
209
bin/netsvc.py
|
@ -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']:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -83,6 +83,9 @@ class Cursor(object):
|
|||
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:
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
@ -158,18 +188,30 @@ class configmanager(object):
|
|||
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
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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:
|
||||
|
|
@ -389,7 +389,7 @@ def trans_generate(lang, modules, dbname=None):
|
|||
|
||||
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
|
11
setup.py
11
setup.py
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue