@@ -7,13 +7,13 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 5.0.4\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-01-03 19:57+0000\n"
|
||||
"PO-Revision-Date: 2010-01-04 06:02+0000\n"
|
||||
"Last-Translator: Kuvaly <kuvaly@seznam.cz>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-01-04 04:38+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-01-05 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -8,13 +8,13 @@ msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-01-03 19:31+0000\n"
|
||||
"Last-Translator: anete <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-01-04 06:03+0000\n"
|
||||
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
|
||||
"Language-Team: Latvian <lv@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-01-04 04:38+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-01-05 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -7,13 +7,13 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-01-03 06:09+0000\n"
|
||||
"PO-Revision-Date: 2010-01-05 06:38+0000\n"
|
||||
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-01-04 04:38+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-01-06 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -295,7 +295,8 @@ class res_partner_address(osv.osv):
|
||||
'mobile': fields.char('Mobile', size=64),
|
||||
'birthdate': fields.char('Birthdate', size=64),
|
||||
'active': fields.boolean('Active', help="Uncheck the active field to hide the contact."),
|
||||
'company_id': fields.related('partner_id','company_id',type='many2one',relation='res.company',string='Company', store=True),
|
||||
# 'company_id': fields.related('partner_id','company_id',type='many2one',relation='res.company',string='Company', store=True),
|
||||
'company_id': fields.many2one('res.company', 'Company',select=1),
|
||||
}
|
||||
_defaults = {
|
||||
'active': lambda *a: 1,
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
<field name="name" select="1"/>
|
||||
<field domain="[('domain', '=', 'contact')]" name="title" />
|
||||
<field name="function"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<newline/>
|
||||
<group string="Postal Address" colspan="2" col="2">
|
||||
<field name="street" select="2"/>
|
||||
@@ -153,6 +154,7 @@
|
||||
<field name="street2"/>
|
||||
<field name="type" select="2"/>
|
||||
<field name="function"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<newline/>
|
||||
<field name="zip" select="2"/>
|
||||
<field name="city" select="2"/>
|
||||
|
||||
@@ -103,15 +103,12 @@ class res_company(osv.osv):
|
||||
args.append(('field_id.name','=',field))
|
||||
else:
|
||||
args.append(('field_id','=',False))
|
||||
print args
|
||||
ids = proxy.search(cr, uid, args, context=context)
|
||||
for rule in proxy.browse(cr, uid, ids, context):
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid)
|
||||
if eval(rule.expression, {'context': context, 'user': user}):
|
||||
print 'found', object
|
||||
return rule.company_dest_id.id
|
||||
user_company_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.id
|
||||
print 'not found', object
|
||||
return user_company_id
|
||||
|
||||
def _get_child_ids(self, cr, uid, uid2, context={}):
|
||||
|
||||
@@ -443,7 +443,10 @@ GNU Public Licence.
|
||||
return info
|
||||
|
||||
def exp_timezone_get(self, db, login, password):
|
||||
return time.tzname[0]
|
||||
#timezone detection is safe in multithread, so lazy init is ok here
|
||||
if (not tools.config['timezone']):
|
||||
tools.config['timezone'] = tools.misc.detect_server_timezone()
|
||||
return tools.config['timezone']
|
||||
|
||||
|
||||
def exp_get_available_updates(self, contract_id, contract_password):
|
||||
|
||||
+15
-2
@@ -77,10 +77,11 @@ class configmanager(object):
|
||||
'secure' : False,
|
||||
'syslog' : False,
|
||||
'log_level': logging.INFO,
|
||||
'assert_exit_level': logging.WARNING, # level above which a failed assert will be raise
|
||||
'assert_exit_level': logging.WARNING, # level above which a failed assert will be raised
|
||||
'cache_timeout': 100000,
|
||||
'login_message': False,
|
||||
'list_db' : True,
|
||||
'timezone' : False, # to override the default TZ
|
||||
}
|
||||
|
||||
self.misc = {}
|
||||
@@ -111,6 +112,7 @@ class configmanager(object):
|
||||
help="update a module (use \"all\" for all modules)")
|
||||
parser.add_option("--cache-timeout", dest="cache_timeout",
|
||||
help="set the timeout for the cache system", default=100000, type="int")
|
||||
parser.add_option("-t", "--timezone", dest="timezone", help="specify reference timezone for the server (e.g. Europe/Brussels")
|
||||
|
||||
# stops the server from launching after initialization
|
||||
parser.add_option("--stop-after-init", action="store_true", dest="stop_after_init", default=False,
|
||||
@@ -227,7 +229,7 @@ class configmanager(object):
|
||||
'db_port', 'list_db', 'logfile', 'pidfile', 'smtp_port', 'cache_timeout',
|
||||
'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy',
|
||||
'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path',
|
||||
'netrpc', 'xmlrpc', 'syslog', 'without_demo']
|
||||
'netrpc', 'xmlrpc', 'syslog', 'without_demo', 'timezone',]
|
||||
|
||||
if hasSSL:
|
||||
keys.extend(['smtp_ssl', 'secure_cert_file', 'secure_pkey_file'])
|
||||
@@ -266,6 +268,17 @@ class configmanager(object):
|
||||
self.options['translate_modules'] = opt.translate_modules and map(lambda m: m.strip(), opt.translate_modules.split(',')) or ['all']
|
||||
self.options['translate_modules'].sort()
|
||||
|
||||
if self.options['timezone']:
|
||||
# If an explicit TZ was provided in the config, make sure it is known
|
||||
try:
|
||||
import pytz
|
||||
tz = pytz.timezone(self.options['timezone'])
|
||||
except pytz.UnknownTimeZoneError:
|
||||
die(True, "The specified timezone (%s) is invalid" % self.options['timezone'])
|
||||
except:
|
||||
# If pytz is missing, don't check the provided TZ, it will be ignored anyway.
|
||||
pass
|
||||
|
||||
if opt.pg_path:
|
||||
self.options['pg_path'] = opt.pg_path
|
||||
|
||||
|
||||
+190
-9
@@ -31,6 +31,7 @@ from config import config
|
||||
import zipfile
|
||||
import release
|
||||
import socket
|
||||
import re
|
||||
|
||||
if sys.version_info[:2] < (2, 4):
|
||||
from threadinglocal import local
|
||||
@@ -302,8 +303,103 @@ def reverse_enumerate(l):
|
||||
#----------------------------------------------------------
|
||||
# Emails
|
||||
#----------------------------------------------------------
|
||||
email_re = re.compile(r"""
|
||||
([a-zA-Z][\w\.-]*[a-zA-Z0-9] # username part
|
||||
@ # mandatory @ sign
|
||||
[a-zA-Z0-9][\w\.-]* # domain must start with a letter ... Ged> why do we include a 0-9 then?
|
||||
\.
|
||||
[a-z]{2,3} # TLD
|
||||
)
|
||||
""", re.VERBOSE)
|
||||
res_re = re.compile(r"\[([0-9]+)\]", re.UNICODE)
|
||||
command_re = re.compile("^Set-([a-z]+) *: *(.+)$", re.I + re.UNICODE)
|
||||
reference_re = re.compile("<.*-openobject-(\\d+)@(.*)>", re.UNICODE)
|
||||
|
||||
priorities = {
|
||||
'1': '1 (Highest)',
|
||||
'2': '2 (High)',
|
||||
'3': '3 (Normal)',
|
||||
'4': '4 (Low)',
|
||||
'5': '5 (Lowest)',
|
||||
}
|
||||
|
||||
def html2plaintext(html, body_id=None, encoding='utf-8'):
|
||||
## (c) Fry-IT, www.fry-it.com, 2007
|
||||
## <peter@fry-it.com>
|
||||
## download here: http://www.peterbe.com/plog/html2plaintext
|
||||
|
||||
|
||||
""" from an HTML text, convert the HTML to plain text.
|
||||
If @body_id is provided then this is the tag where the
|
||||
body (not necessarily <body>) starts.
|
||||
"""
|
||||
try:
|
||||
from BeautifulSoup import BeautifulSoup, SoupStrainer, Comment
|
||||
except:
|
||||
return html
|
||||
|
||||
urls = []
|
||||
if body_id is not None:
|
||||
strainer = SoupStrainer(id=body_id)
|
||||
else:
|
||||
strainer = SoupStrainer('body')
|
||||
|
||||
soup = BeautifulSoup(html, parseOnlyThese=strainer, fromEncoding=encoding)
|
||||
for link in soup.findAll('a'):
|
||||
title = link.renderContents()
|
||||
for url in [x[1] for x in link.attrs if x[0]=='href']:
|
||||
urls.append(dict(url=url, tag=str(link), title=title))
|
||||
|
||||
html = soup.__str__()
|
||||
|
||||
url_index = []
|
||||
i = 0
|
||||
for d in urls:
|
||||
if d['title'] == d['url'] or 'http://'+d['title'] == d['url']:
|
||||
html = html.replace(d['tag'], d['url'])
|
||||
else:
|
||||
i += 1
|
||||
html = html.replace(d['tag'], '%s [%s]' % (d['title'], i))
|
||||
url_index.append(d['url'])
|
||||
|
||||
html = html.replace('<strong>','*').replace('</strong>','*')
|
||||
html = html.replace('<b>','*').replace('</b>','*')
|
||||
html = html.replace('<h3>','*').replace('</h3>','*')
|
||||
html = html.replace('<h2>','**').replace('</h2>','**')
|
||||
html = html.replace('<h1>','**').replace('</h1>','**')
|
||||
html = html.replace('<em>','/').replace('</em>','/')
|
||||
|
||||
|
||||
# the only line breaks we respect is those of ending tags and
|
||||
# breaks
|
||||
|
||||
html = html.replace('\n',' ')
|
||||
html = html.replace('<br>', '\n')
|
||||
html = html.replace('<tr>', '\n')
|
||||
html = html.replace('</p>', '\n\n')
|
||||
html = re.sub('<br\s*/>', '\n', html)
|
||||
html = html.replace(' ' * 2, ' ')
|
||||
|
||||
|
||||
# for all other tags we failed to clean up, just remove then and
|
||||
# complain about them on the stderr
|
||||
def desperate_fixer(g):
|
||||
#print >>sys.stderr, "failed to clean up %s" % str(g.group())
|
||||
return ' '
|
||||
|
||||
html = re.sub('<.*?>', desperate_fixer, html)
|
||||
|
||||
# lstrip all lines
|
||||
html = '\n'.join([x.lstrip() for x in html.splitlines()])
|
||||
|
||||
for i, url in enumerate(url_index):
|
||||
if i == 0:
|
||||
html += '\n\n'
|
||||
html += '[%s] %s\n' % (i+1, url)
|
||||
return html
|
||||
|
||||
def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False,
|
||||
attach=None, tinycrm=False, ssl=False, debug=False, subtype='plain', x_headers=None):
|
||||
attach=None, openobject_id=False, ssl=False, debug=False, subtype='plain', x_headers=None, priority='3'):
|
||||
|
||||
"""Send an email."""
|
||||
import smtplib
|
||||
@@ -314,7 +410,7 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
||||
from email.Utils import formatdate, COMMASPACE
|
||||
from email.Utils import formatdate, COMMASPACE
|
||||
from email import Encoders
|
||||
import netsvc
|
||||
import netsvc
|
||||
|
||||
if x_headers is None:
|
||||
x_headers = {}
|
||||
@@ -325,6 +421,9 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
||||
if not email_from and not config['email_from']:
|
||||
raise Exception("No Email sender by default, see config file")
|
||||
|
||||
if not email_from:
|
||||
email_from = config.get('email_from', False)
|
||||
|
||||
if not email_cc:
|
||||
email_cc = []
|
||||
if not email_bcc:
|
||||
@@ -356,13 +455,15 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
||||
msg['X-Generated-By'] = 'OpenERP (http://www.openerp.com)'
|
||||
msg['X-OpenERP-Server-Host'] = socket.gethostname()
|
||||
msg['X-OpenERP-Server-Version'] = release.version
|
||||
if priority:
|
||||
msg['X-Priority'] = priorities.get(priority, '3 (Normal)')
|
||||
|
||||
# Add dynamic X Header
|
||||
for key, value in x_headers.items():
|
||||
msg['X-OpenERP-%s' % key] = str(value)
|
||||
|
||||
if tinycrm:
|
||||
msg['Message-Id'] = "<%s-tinycrm-%s@%s>" % (time.time(), tinycrm, socket.gethostname())
|
||||
if openobject_id:
|
||||
msg['Message-Id'] = "<%s-openobject-%s@%s>" % (time.time(), openobject_id, socket.gethostname())
|
||||
|
||||
if attach:
|
||||
try:
|
||||
@@ -393,12 +494,11 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
||||
return True
|
||||
except Exception,e:
|
||||
netsvc.Logger().notifyChannel('email_send (maildir)', netsvc.LOG_ERROR, e)
|
||||
return False
|
||||
return False
|
||||
|
||||
try:
|
||||
oldstderr = smtplib.stderr
|
||||
s = smtplib.SMTP()
|
||||
|
||||
try:
|
||||
# in case of debug, the messages are printed to stderr.
|
||||
if debug:
|
||||
@@ -412,13 +512,11 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
||||
s.ehlo()
|
||||
|
||||
if config['smtp_user'] or config['smtp_password']:
|
||||
s.login(config['smtp_user'], config['smtp_password'])
|
||||
|
||||
s.login(config['smtp_user'], config['smtp_password'])
|
||||
s.sendmail(email_from,
|
||||
flatten([email_to, email_cc, email_bcc]),
|
||||
msg.as_string()
|
||||
)
|
||||
|
||||
finally:
|
||||
s.quit()
|
||||
if debug:
|
||||
@@ -1076,6 +1174,89 @@ def detect_ip_addr():
|
||||
ip_addr = 'localhost'
|
||||
return ip_addr
|
||||
|
||||
# RATIONALE BEHIND TIMESTAMP CALCULATIONS AND TIMEZONE MANAGEMENT:
|
||||
# The server side never does any timestamp calculation, always
|
||||
# sends them in a naive (timezone agnostic) format supposed to be
|
||||
# expressed within the server timezone, and expects the clients to
|
||||
# provide timestamps in the server timezone as well.
|
||||
# It stores all timestamps in the database in naive format as well,
|
||||
# which also expresses the time in the server timezone.
|
||||
# For this reason the server makes its timezone name available via the
|
||||
# common/timezone_get() rpc method, which clients need to read
|
||||
# to know the appropriate time offset to use when reading/writing
|
||||
# times.
|
||||
def get_win32_timezone():
|
||||
"""Attempt to return the "standard name" of the current timezone on a win32 system.
|
||||
@return: the standard name of the current win32 timezone, or False if it cannot be found.
|
||||
"""
|
||||
res = False
|
||||
if (sys.platform == "win32"):
|
||||
try:
|
||||
import _winreg
|
||||
hklm = _winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
|
||||
current_tz_key = _winreg.OpenKey(hklm, r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation", 0,_winreg.KEY_ALL_ACCESS)
|
||||
res = str(_winreg.QueryValueEx(current_tz_key,"StandardName")[0]) # [0] is value, [1] is type code
|
||||
_winreg.CloseKey(current_tz_key)
|
||||
_winreg.CloseKey(hklm)
|
||||
except:
|
||||
pass
|
||||
return res
|
||||
|
||||
def detect_server_timezone():
|
||||
"""Attempt to detect the timezone to use on the server side.
|
||||
Defaults to UTC if no working timezone can be found.
|
||||
@return: the timezone identifier as expected by pytz.timezone.
|
||||
"""
|
||||
import time
|
||||
import netsvc
|
||||
try:
|
||||
import pytz
|
||||
except:
|
||||
netsvc.Logger().notifyChannel("detect_server_timezone", netsvc.LOG_WARNING,
|
||||
"Python pytz module is not available. Timezone will be set to UTC by default.")
|
||||
return 'UTC'
|
||||
|
||||
# Option 1: the configuration option (did not exist before, so no backwards compatibility issue)
|
||||
# Option 2: to be backwards compatible with 5.0 or earlier, the value from time.tzname[0], but only if it is known to pytz
|
||||
# Option 3: the environment variable TZ
|
||||
sources = [ (config['timezone'], 'OpenERP configuration'),
|
||||
(time.tzname[0], 'time.tzname'),
|
||||
(os.environ.get('TZ',False),'TZ environment variable'), ]
|
||||
# Option 4: OS-specific: /etc/timezone on Unix
|
||||
if (os.path.exists("/etc/timezone")):
|
||||
tz_value = False
|
||||
try:
|
||||
f = open("/etc/timezone")
|
||||
tz_value = f.read(128).strip()
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
f.close()
|
||||
sources.append((tz_value,"/etc/timezone file"))
|
||||
# Option 5: timezone info from registry on Win32
|
||||
if (sys.platform == "win32"):
|
||||
# Timezone info is stored in windows registry.
|
||||
# However this is not likely to work very well as the standard name
|
||||
# of timezones in windows is rarely something that is known to pytz.
|
||||
# But that's ok, it is always possible to use a config option to set
|
||||
# it explicitly.
|
||||
sources.append((get_win32_timezone(),"Windows Registry"))
|
||||
|
||||
for (value,source) in sources:
|
||||
if value:
|
||||
try:
|
||||
tz = pytz.timezone(value)
|
||||
netsvc.Logger().notifyChannel("detect_server_timezone", netsvc.LOG_INFO,
|
||||
"Using timezone %s obtained from %s." % (tz.zone,source))
|
||||
return value
|
||||
except pytz.UnknownTimeZoneError:
|
||||
netsvc.Logger().notifyChannel("detect_server_timezone", netsvc.LOG_WARNING,
|
||||
"The timezone specified in %s (%s) is invalid, ignoring it." % (source,value))
|
||||
|
||||
netsvc.Logger().notifyChannel("detect_server_timezone", netsvc.LOG_WARNING,
|
||||
"No valid timezone could be detected, using default UTC timezone. You can specify it explicitly with option 'timezone' in the server configuration.")
|
||||
return 'UTC'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
|
||||
Reference in New Issue
Block a user