openerp-dev-web team mailing list archive
-
openerp-dev-web team
-
Mailing list archive
-
Message #01532
[Merge] lp:~xrg/openobject-addons/trunk-patch11 into lp:~openerp-dev/openobject-addons/trunk-dev-addons1
tfr (Openerp) has proposed merging lp:~xrg/openobject-addons/trunk-patch11 into lp:~openerp-dev/openobject-addons/trunk-dev-addons1.
Requested reviews:
OpenERP R&D Team (openerp-dev)
For more details, see:
https://code.launchpad.net/~xrg/openobject-addons/trunk-patch11/+merge/44584
--
https://code.launchpad.net/~xrg/openobject-addons/trunk-patch11/+merge/44584
Your team OpenERP R&D Team is requested to review the proposed merge of lp:~xrg/openobject-addons/trunk-patch11 into lp:~openerp-dev/openobject-addons/trunk-dev-addons1.
=== modified file 'account/account_move_line.py'
--- account/account_move_line.py 2010-12-22 16:09:26 +0000
+++ account/account_move_line.py 2010-12-23 15:39:46 +0000
@@ -309,6 +309,7 @@
context = {}
c = context.copy()
c['initital_bal'] = True
+<<<<<<< TREE
sql = """SELECT l2.id, SUM(l1.debit-l1.credit)
FROM account_move_line l1, account_move_line l2
WHERE l2.account_id = l1.account_id
@@ -316,6 +317,15 @@
AND l2.id IN %s AND """ + \
self._query_get(cr, uid, obj='l1', context=c) + \
" GROUP BY l2.id"
+=======
+ sql = """SELECT l2.id, SUM(l1.debit-l1.credit)
+ FROM account_move_line l1, account_move_line l2
+ WHERE l2.account_id = l1.account_id
+ AND l1.id <= l2.id
+ AND l2.id IN %%s AND """ + \
+ self._query_get(cr, uid, obj='l1', context=c) + \
+ " GROUP BY l2.id"
+>>>>>>> MERGE-SOURCE
cr.execute(sql, [tuple(ids)])
res = dict(cr.fetchall())
=== modified file 'base_iban/base_iban.py'
--- base_iban/base_iban.py 2010-12-06 13:11:02 +0000
+++ base_iban/base_iban.py 2010-12-23 15:39:46 +0000
@@ -117,7 +117,7 @@
iban_country = self.browse(cr, uid, ids)[0].iban[:2]
if default_iban_check(iban_country):
iban_example = iban_country in _ref_iban and _ref_iban[iban_country] + ' \nWhere A = Account number, B = National bank code, S = Branch code, C = account No, N = branch No, K = National check digits....' or ''
- return _('The IBAN does not seems to be correct. You should have entered something like this %s'), (iban_example)
+ return _('The IBAN does not seem to be correct. You should have entered something like this %s'), (iban_example)
return _('The IBAN is invalid, It should begin with the country code'), ()
def name_get(self, cr, uid, ids, context=None):
=== modified file 'board/board.py'
=== modified file 'document/document.py'
--- document/document.py 2010-12-06 13:11:02 +0000
+++ document/document.py 2010-12-23 15:39:46 +0000
@@ -135,6 +135,15 @@
return False
return True
+ def check(self, cr, uid, ids, mode, context=None, values=None):
+ """Check access wrt. res_model, relax the rule of ir.attachment parent
+
+ With 'document' installed, everybody will have access to attachments of
+ any resources they can *read*.
+ """
+ return super(document_file, self).check(cr, uid, ids, mode='read',
+ context=context, values=values)
+
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
=== modified file 'document/wizard/document_configuration.py'
--- document/wizard/document_configuration.py 2010-11-23 07:05:05 +0000
+++ document/wizard/document_configuration.py 2010-12-23 15:39:46 +0000
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,22 +15,24 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
+
from osv import osv, fields
+
class document_configuration(osv.osv_memory):
_name='document.configuration'
_description = 'Auto Directory Configuration'
- _inherit = 'res.config'
+ _inherit = 'res.config'
_columns = {
'sale_order' : fields.boolean('Sale Order', help="Auto directory configuration for Sale Orders and Quotation with report."),
'product' : fields.boolean('Product', help="Auto directory configuration for Products."),
'project': fields.boolean('Project', help="Auto directory configuration for Projects."),
}
-
+
def execute(self, cr, uid, ids, context=None):
conf_id = ids and ids[0] or False
@@ -58,7 +60,7 @@
quta_dir_id = data_pool.browse(cr, uid, dir_data_id, context=context).res_id
else:
quta_dir_id = data_pool.create(cr, uid, {'name': 'Sale Quotations'})
-
+
dir_pool.write(cr, uid, [quta_dir_id], {
'type':'ressource',
'ressource_type_id': mid[0],
@@ -86,7 +88,7 @@
'include_name': 1,
'directory_id': quta_dir_id,
})
-
+
if conf.product and self.pool.get('product.product'):
# Product
@@ -95,12 +97,12 @@
product_dir_id = data_pool.browse(cr, uid, dir_data_id, context=context).res_id
else:
product_dir_id = data_pool.create(cr, uid, {'name': 'Products'})
-
+
mid = model_pool.search(cr, uid, [('model','=','product.product')])
dir_pool.write(cr, uid, [product_dir_id], {
'type':'ressource',
'ressource_type_id': mid[0],
- })
+ })
if conf.project and self.pool.get('account.analytic.account'):
# Project
@@ -109,12 +111,12 @@
project_dir_id = data_pool.browse(cr, uid, dir_data_id, context=context).res_id
else:
project_dir_id = data_pool.create(cr, uid, {'name': 'Projects'})
-
+
mid = model_pool.search(cr, uid, [('model','=','account.analytic.account')])
dir_pool.write(cr, uid, [project_dir_id], {
'type':'ressource',
'ressource_type_id': mid[0],
'domain': '[]',
'ressource_tree': 1
- })
+ })
document_configuration()
=== modified file 'document/wizard/document_configuration_view.xml'
--- document/wizard/document_configuration_view.xml 2010-09-15 06:58:45 +0000
+++ document/wizard/document_configuration_view.xml 2010-12-23 15:39:46 +0000
@@ -45,6 +45,8 @@
<record model="ir.actions.todo" id="config_auto_directory">
<field name="action_id" ref="action_config_auto_directory"/>
<field name="groups_id" eval="[(6,0,[ref('base.group_extended')])]"/>
+ <field name="state" eval="'skip'" />
+ <field name="restart" eval="'onskip'" />
</record>
</data>
</openerp>
=== modified file 'document_ftp/wizard/ftp_browse.py'
--- document_ftp/wizard/ftp_browse.py 2010-12-06 13:11:02 +0000
+++ document_ftp/wizard/ftp_browse.py 2010-12-23 15:39:46 +0000
@@ -43,9 +43,11 @@
url = ftp_url.url and ftp_url.url.split('ftp://') or []
if url:
url = url[1]
+ if url[-1] == '/':
+ url = url[:-1]
else:
url = '%s:%s' %(ftpserver.HOST, ftpserver.PORT)
- res['url'] = 'ftp://%s@%s'%(current_user.login, url)
+ res['url'] = 'ftp://%s@%s/%s'%(current_user.login, url, cr.dbname)
return res
def browse_ftp(self, cr, uid, ids, context=None):
=== modified file 'document_webdav/__openerp__.py'
--- document_webdav/__openerp__.py 2010-11-12 09:48:36 +0000
+++ document_webdav/__openerp__.py 2010-12-23 15:39:46 +0000
@@ -30,7 +30,7 @@
{
"name" : "WebDAV server for Document Management",
- "version" : "2.2",
+ "version" : "2.3",
"author" : "OpenERP SA",
"category" : "Generic Modules/Others",
"website": "http://www.openerp.com",
@@ -49,6 +49,9 @@
; since the messages are routed to the python logging, with
; levels "debug" and "debug_rpc" respectively, you can leave
; these options on
+
+ Also implements IETF RFC 5785 for services discovery on a http server,
+ which needs explicit configuration in openerp-server.conf, too.
""",
"depends" : ["base", "document"],
"init_xml" : [],
=== modified file 'document_webdav/dav_fs.py'
--- document_webdav/dav_fs.py 2010-12-07 13:40:41 +0000
+++ document_webdav/dav_fs.py 2010-12-23 15:39:46 +0000
@@ -686,7 +686,7 @@
except Exception:
node = False
- objname = uri2[-1]
+ objname = misc.ustr(uri2[-1])
ret = None
if not node:
@@ -719,7 +719,7 @@
etag = str(newchild.get_etag(cr))
except Exception, e:
self.parent.log_error("Cannot get etag for node: %s" % e)
- ret = (hurl, etag)
+ ret = (str(hurl), etag)
else:
self._try_function(node.set_data, (cr, data), "save %s" % objname, cr=cr)
=== added directory 'document_webdav/doc'
=== added file 'document_webdav/doc/well-known.rst'
--- document_webdav/doc/well-known.rst 1970-01-01 00:00:00 +0000
+++ document_webdav/doc/well-known.rst 2010-12-23 15:39:46 +0000
@@ -0,0 +1,29 @@
+=================
+Well-known URIs
+=================
+
+In accordance to IETF RFC 5785 [1], we shall publish a few locations
+on the root of our http server, so that clients can discover our
+services (CalDAV, eg.).
+
+This module merely installs a special http request handler, that will
+redirect the URIs from "http://our-server:port/.well-known/xxx' to
+the correct path for each xxx service.
+
+Note that well-known URIs cannot have a database-specific behaviour,
+they are server-wide. So, we have to explicitly chose one of our databases
+to serve at them. By default, the database of the configuration file
+is chosen
+
+Example config:
+
+[http-well-known]
+num_services = 2
+db_name = openerp-main ; must define that for path_1 below
+service_1 = caldav
+path_1 = /webdav/%(db_name)s/Calendars/
+service_2 = foo
+path_2 = /other_db/static/Foo.html
+
+
+[1] http://www.rfc-editor.org/rfc/rfc5785.txt
\ No newline at end of file
=== modified file 'document_webdav/nodes.py'
--- document_webdav/nodes.py 2010-12-07 13:40:41 +0000
+++ document_webdav/nodes.py 2010-12-23 15:39:46 +0000
@@ -299,6 +299,7 @@
return ''
def get_dav_props(self, cr):
+<<<<<<< TREE
return self._get_dav_props_hlpr(cr, nodes.node_dir,
'document.webdav.file.property', 'file_id', self.file_id)
@@ -339,17 +340,24 @@
]
return self._get_dav_eprop_hlpr(cr, ns, prop, nodes.node_file,
'document.webdav.file.property', 'file_id', self.file_id)
+=======
+ return self._get_dav_props_hlpr(cr, nodes.node_file,
+ None, 'file_id', self.file_id)
+ #'document.webdav.dir.property', 'dir_id', self.dir_id)
+
+ #def get_dav_eprop(self, cr, ns, prop):
+>>>>>>> MERGE-SOURCE
class node_database(nodes.node_database):
def get_dav_resourcetype(self, cr):
return ('collection', 'DAV:')
def get_dav_props(self, cr):
- return self._get_dav_props_hlpr(cr, nodes.node_dir,
+ return self._get_dav_props_hlpr(cr, nodes.node_database,
'document.webdav.dir.property', 'dir_id', False)
def get_dav_eprop(self, cr, ns, prop):
- return self._get_dav_eprop_hlpr(cr, nodes.node_dir, ns, prop,
+ return self._get_dav_eprop_hlpr(cr, nodes.node_database, ns, prop,
'document.webdav.dir.property', 'dir_id', False)
class node_res_obj(node_acl_mixin, nodes.node_res_obj):
=== added directory 'document_webdav/public_html'
=== added file 'document_webdav/public_html/index.html'
--- document_webdav/public_html/index.html 1970-01-01 00:00:00 +0000
+++ document_webdav/public_html/index.html 2010-12-23 15:39:46 +0000
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>OpenERP server</title>
+</head>
+<body>
+This is an OpenERP server. Nothing to GET here.
+</body>
+</html>
+
=== added file 'document_webdav/redirect.py'
--- document_webdav/redirect.py 1970-01-01 00:00:00 +0000
+++ document_webdav/redirect.py 2010-12-23 15:39:46 +0000
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+import logging
+import urlparse
+from service.websrv_lib import FixSendError, HTTPHandler, HttpOptions
+from service.http_server import HttpLogHandler
+
+class RedirectHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
+ _logger = logging.getLogger('httpd.well-known')
+ _HTTP_OPTIONS = { 'Allow': ['OPTIONS', 'GET', 'HEAD', 'PROPFIND'] }
+ redirect_paths = {}
+
+ def __init__(self,request, client_address, server):
+ HTTPHandler.__init__(self,request,client_address,server)
+
+ def send_head(self):
+ """Common code for GET and HEAD commands.
+
+ It will either send the correct redirect (Location) response
+ or a 404.
+ """
+
+ if self.path.endswith('/'):
+ self.path = self.path[:-1]
+
+ if not self.path:
+ # Return an empty page
+ self.send_response(200)
+ self.send_header("Content-Length", 0)
+ self.end_headers()
+ return None
+
+ redir_path = self._find_redirect()
+ if redir_path is False:
+ self.send_error(404, "File not found")
+ return None
+ elif redir_path is None:
+ return None
+
+ server_proto = getattr(self.server, 'proto', 'http').lower()
+ addr, port = self.server.server_name, self.server.server_port
+ try:
+ addr, port = self.request.getsockname()
+ except Exception, e:
+ self.log_error("Cannot calculate own address:" , e)
+
+ if self.headers.has_key('Host'):
+ uparts = list(urlparse.urlparse("%s://%s:%d"% (server_proto, addr,port)))
+ uparts[1] = self.headers['Host']
+ baseuri = urlparse.urlunparse(uparts)
+ else:
+ baseuri = "%s://%s:%d"% (server_proto, addr, port )
+
+
+ location = baseuri + redir_path
+ # relative uri: location = self.redirect_paths[self.path]
+
+ self.send_response(301)
+ self.send_header("Location", location)
+ self.send_header("Content-Length", 0)
+ self.end_headers()
+ # Do we need a Cache-content: header here?
+ self._logger.debug("redirecting %s to %s", self.path, redir_path)
+ return None
+
+ def do_PROPFIND(self):
+ self._get_ignore_body()
+ return self.do_HEAD()
+
+ def _find_redirect(self):
+ """ Locate self.path among the redirects we can handle
+ @return The new path, False for 404 or None for already sent error
+ """
+ return self.redirect_paths.get(self.path, False)
+
+ def _get_ignore_body(self):
+ if not self.headers.has_key("content-length"):
+ return
+ max_chunk_size = 10*1024*1024
+ size_remaining = int(self.headers["content-length"])
+ got = ''
+ while size_remaining:
+ chunk_size = min(size_remaining, max_chunk_size)
+ got = self.rfile.read(chunk_size)
+ size_remaining -= len(got)
+
+#eof
+
=== modified file 'document_webdav/webdav.py'
--- document_webdav/webdav.py 2010-12-07 13:40:41 +0000
+++ document_webdav/webdav.py 2010-12-23 15:39:46 +0000
@@ -45,35 +45,33 @@
data = data.replace(">", ">")
writer.write(data)
-def createText2Node(doc, data):
- if not isinstance(data, StringTypes):
- raise TypeError, "node contents must be a string"
- t = Text2()
- t.data = data
- t.ownerDocument = doc
- return t
-
-
-super_mk_prop_response = PROPFIND.mk_prop_response
-def mk_prop_response(self, uri, good_props, bad_props, doc):
- """ make a new <prop> result element
-
- We differ between the good props and the bad ones for
- each generating an extra <propstat>-Node (for each error
- one, that means).
-
+class Prop2xml(object):
+ """ A helper class to convert property structs to DAV:XML
+
+ Written to generalize the use of _prop_child(), a class is
+ needed to hold some persistent data accross the recursions
+ of _prop_elem_child().
"""
- re=doc.createElement("D:response")
- # append namespaces to response
- nsnum=0
- namespaces = self.namespaces[:]
- if 'DAV:' in namespaces:
- namespaces.remove('DAV:')
- for nsname in namespaces:
- re.setAttribute("xmlns:ns"+str(nsnum),nsname)
- nsnum=nsnum+1
-
- def _prop_child(xnode, ns, prop, value):
+
+ def __init__(self, doc, namespaces, nsnum):
+ """ Init the structure
+ @param doc the xml doc element
+ @param namespaces a dict of namespaces
+ @param nsnum the next namespace number to define
+ """
+ self.doc = doc
+ self.namespaces = namespaces
+ self.nsnum = nsnum
+
+ def createText2Node(self, data):
+ if not isinstance(data, StringTypes):
+ raise TypeError, "node contents must be a string"
+ t = Text2()
+ t.data = data
+ t.ownerDocument = self.doc
+ return t
+
+ def _prop_child(self, xnode, ns, prop, value):
"""Append a property xml node to xnode, with <prop>value</prop>
And a little smarter than that, it will consider namespace and
@@ -92,49 +90,49 @@
if ns == 'DAV:':
ns_prefix = 'D:'
else:
- ns_prefix="ns"+str(namespaces.index(ns))+":"
+ ns_prefix="ns"+str(self.namespaces.index(ns))+":"
- pe=doc.createElement(ns_prefix+str(prop))
+ pe = self.doc.createElement(ns_prefix+str(prop))
if hasattr(value, '__class__') and value.__class__.__name__ == 'Element':
pe.appendChild(value)
else:
if ns == 'DAV:' and prop=="resourcetype" and isinstance(value, int):
# hack, to go..
if value == 1:
- ve=doc.createElement("D:collection")
+ ve = self.doc.createElement("D:collection")
pe.appendChild(ve)
else:
- _prop_elem_child(pe, ns, value, ns_prefix)
+ self._prop_elem_child(pe, ns, value, ns_prefix)
xnode.appendChild(pe)
- def _prop_elem_child(pnode, pns, v, pns_prefix):
+ def _prop_elem_child(self, pnode, pns, v, pns_prefix):
if isinstance(v, list):
for vit in v:
- _prop_elem_child(pnode, pns, vit, pns_prefix)
+ self._prop_elem_child(pnode, pns, vit, pns_prefix)
elif isinstance(v,tuple):
need_ns = False
if v[1] == pns:
ns_prefix = pns_prefix
elif v[1] == 'DAV:':
ns_prefix = 'D:'
- elif v[1] in namespaces:
- ns_prefix="ns"+str(namespaces.index(v[1]))+":"
+ elif v[1] in self.namespaces:
+ ns_prefix="ns"+str(self.namespaces.index(v[1]))+":"
else:
- ns_prefix="ns"+str(nsnum)+":"
+ ns_prefix="ns"+str(self.nsnum)+":"
need_ns = True
- ve=doc.createElement(ns_prefix+v[0])
+ ve = self.doc.createElement(ns_prefix+v[0])
if need_ns:
- ve.setAttribute("xmlns:ns"+str(nsnum), v[1])
+ ve.setAttribute("xmlns:ns"+str(self.nsnum), v[1])
if len(v) > 2 and v[2] is not None:
if isinstance(v[2], (list, tuple)):
# support nested elements like:
# ( 'elem', 'ns:', [('sub-elem1', 'ns1'), ...]
- _prop_elem_child(ve, v[1], v[2], ns_prefix)
+ self._prop_elem_child(ve, v[1], v[2], ns_prefix)
else:
- vt=createText2Node(doc,tools.ustr(v[2]))
+ vt = self.createText2Node(tools.ustr(v[2]))
ve.appendChild(vt)
if len(v) > 3 and v[3]:
assert isinstance(v[3], dict)
@@ -142,9 +140,30 @@
ve.setAttribute(ak, av)
pnode.appendChild(ve)
else:
- ve=createText2Node(doc, tools.ustr(v))
+ ve = self.createText2Node(tools.ustr(v))
pnode.appendChild(ve)
+
+super_mk_prop_response = PROPFIND.mk_prop_response
+def mk_prop_response(self, uri, good_props, bad_props, doc):
+ """ make a new <prop> result element
+
+ We differ between the good props and the bad ones for
+ each generating an extra <propstat>-Node (for each error
+ one, that means).
+
+ """
+ re=doc.createElement("D:response")
+ # append namespaces to response
+ nsnum=0
+ namespaces = self.namespaces[:]
+ if 'DAV:' in namespaces:
+ namespaces.remove('DAV:')
+ for nsname in namespaces:
+ re.setAttribute("xmlns:ns"+str(nsnum),nsname)
+ nsnum=nsnum+1
+
+ propgen = Prop2xml(doc, namespaces, nsnum)
# write href information
uparts=urlparse.urlparse(uri)
fileloc=uparts[2]
@@ -180,7 +199,7 @@
for p,v in good_props[ns].items():
if v is None:
continue
- _prop_child(gp, ns, p, v)
+ propgen._prop_child(gp, ns, p, v)
ps.appendChild(gp)
re.appendChild(ps)
=== modified file 'document_webdav/webdav_server.py'
--- document_webdav/webdav_server.py 2010-12-09 09:59:50 +0000
+++ document_webdav/webdav_server.py 2010-12-23 15:39:46 +0000
@@ -1,7 +1,12 @@
# -*- encoding: utf-8 -*-
-
+############################################################################9
#
+<<<<<<< TREE
# Copyright P. Christeas <p_christ@xxxxxx> 2008-2010
+=======
+# Copyright P. Christeas <p_christ@xxxxxx> 2008,2009
+# Copyright OpenERP SA, 2010 (http://www.openerp.com )
+>>>>>>> MERGE-SOURCE
#
# Disclaimer: Many of the functions below borrow code from the
# python-webdav library (http://code.google.com/p/pywebdav/ ),
@@ -19,7 +24,7 @@
#
# 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 2
+# 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,
@@ -33,20 +38,32 @@
###############################################################################
-import netsvc
+import logging
from dav_fs import openerp_dav_handler
from tools.config import config
from DAV.WebDAVServer import DAVRequestHandler
+from service import http_server
from service.websrv_lib import HTTPDir, FixSendError, HttpOptions
from BaseHTTPServer import BaseHTTPRequestHandler
import urlparse
import urllib
import re
+import time
from string import atoi
+<<<<<<< TREE
from DAV.errors import *
from DAV.utils import IfParser, TagList
+=======
+import addons
+from DAV.errors import DAV_Error, DAV_Forbidden, DAV_NotFound
+from DAV.propfind import PROPFIND
+>>>>>>> MERGE-SOURCE
# from DAV.constants import DAV_VERSION_1, DAV_VERSION_2
+<<<<<<< TREE
from xml.dom import minidom
+=======
+from redirect import RedirectHTTPHandler
+>>>>>>> MERGE-SOURCE
khtml_re = re.compile(r' KHTML/([0-9\.]+) ')
@@ -66,6 +83,7 @@
class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
verbose = False
+ _logger = logging.getLogger('webdav')
protocol_version = 'HTTP/1.1'
_HTTP_OPTIONS= { 'DAV' : ['1', '2'],
'Allow' : [ 'GET', 'HEAD', 'COPY', 'MOVE', 'POST', 'PUT',
@@ -75,8 +93,9 @@
def get_userinfo(self,user,pw):
return False
+
def _log(self, message):
- netsvc.Logger().notifyChannel("webdav",netsvc.LOG_DEBUG,message)
+ self._logger.debug(message)
def handle(self):
self._init_buffer()
@@ -118,10 +137,10 @@
return self.davpath
def log_message(self, format, *args):
- netsvc.Logger().notifyChannel('webdav', netsvc.LOG_DEBUG_RPC, format % args)
+ self._logger.log(netsvc.logging.DEBUG_RPC,format % args)
def log_error(self, format, *args):
- netsvc.Logger().notifyChannel('xmlrpc', netsvc.LOG_WARNING, format % args)
+ self._logger.warning(format % args)
def _prep_OPTIONS(self, opts):
ret = opts
@@ -415,6 +434,140 @@
return True
return OpenERPAuthProvider.authenticate(self, db, user, passwd, client_address)
+
+class dummy_dav_interface(object):
+ """ Dummy dav interface """
+ verbose = True
+
+ PROPS={"DAV:" : ('creationdate',
+ 'displayname',
+ 'getlastmodified',
+ 'resourcetype',
+ ),
+ }
+
+ M_NS={"DAV:" : "_get_dav", }
+
+ def __init__(self, parent):
+ self.parent = parent
+
+ def get_propnames(self,uri):
+ return self.PROPS
+
+ def get_prop(self,uri,ns,propname):
+ if self.M_NS.has_key(ns):
+ prefix=self.M_NS[ns]
+ else:
+ raise DAV_NotFound
+ mname=prefix+"_"+propname.replace('-', '_')
+ try:
+ m=getattr(self,mname)
+ r=m(uri)
+ return r
+ except AttributeError:
+ raise DAV_NotFound
+
+ def get_data(self, uri, range=None):
+ raise DAV_NotFound
+
+ def _get_dav_creationdate(self,uri):
+ return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
+
+ def _get_dav_getlastmodified(self,uri):
+ return time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime())
+
+ def _get_dav_displayname(self, uri):
+ return uri
+
+ def _get_dav_resourcetype(self, uri):
+ return ('collection', 'DAV:')
+
+ def exists(self, uri):
+ """ return 1 or None depending on if a resource exists """
+ uri2 = uri.split('/')
+ if len(uri2) < 3:
+ return True
+ logging.getLogger('webdav').debug("Requested uri: %s", uri)
+ return None # no
+
+ def is_collection(self, uri):
+ """ return 1 or None depending on if a resource is a collection """
+ return None # no
+
+class DAVStaticHandler(http_server.StaticHTTPHandler):
+ """ A variant of the Static handler, which will serve dummy DAV requests
+ """
+ verbose = False
+ protocol_version = 'HTTP/1.1'
+ _HTTP_OPTIONS= { 'DAV' : ['1', '2'],
+ 'Allow' : [ 'GET', 'HEAD',
+ 'PROPFIND', 'OPTIONS', 'REPORT', ]
+ }
+
+ def send_body(self, content, code, message='OK', content_type='text/xml'):
+ self.send_response(int(code), message)
+ self.send_header("Content-Type", content_type)
+ # self.send_header('Connection', 'close')
+ self.send_header('Content-Length', len(content) or 0)
+ self.end_headers()
+ if hasattr(self, '_flush'):
+ self._flush()
+
+ if self.command != 'HEAD':
+ self.wfile.write(content)
+
+ def do_PROPFIND(self):
+ """Answer to PROPFIND with generic data.
+
+ A rough copy of python-webdav's do_PROPFIND, but hacked to work
+ statically.
+ """
+
+ dc = dummy_dav_interface(self)
+
+ # read the body containing the xml request
+ # iff there is no body then this is an ALLPROP request
+ body = None
+ if self.headers.has_key('Content-Length'):
+ l = self.headers['Content-Length']
+ body = self.rfile.read(atoi(l))
+
+ path = self.path.rstrip('/')
+ uri = urllib.unquote(path)
+
+ pf = PROPFIND(uri, dc, self.headers.get('Depth', 'infinity'), body)
+
+ try:
+ DATA = '%s\n' % pf.createResponse()
+ except DAV_Error, (ec,dd):
+ return self.send_error(ec,dd)
+ except Exception:
+ self.log_exception("Cannot PROPFIND")
+ raise
+
+ # work around MSIE DAV bug for creation and modified date
+ # taken from Resource.py @ Zope webdav
+ if (self.headers.get('User-Agent') ==
+ 'Microsoft Data Access Internet Publishing Provider DAV 1.1'):
+ DATA = DATA.replace('<ns0:getlastmodified xmlns:ns0="DAV:">',
+ '<ns0:getlastmodified xmlns:n="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">')
+ DATA = DATA.replace('<ns0:creationdate xmlns:ns0="DAV:">',
+ '<ns0:creationdate xmlns:n="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.tz">')
+
+ self.send_body(DATA, '207','Multi-Status','Multiple responses')
+
+ def not_get_baseuri(self):
+ baseuri = '/'
+ if self.headers.has_key('Host'):
+ uparts = list(urlparse.urlparse('/'))
+ uparts[1] = self.headers['Host']
+ baseuri = urlparse.urlunparse(uparts)
+ return baseuri
+
+ def get_davpath(self):
+ return ''
+
+
try:
if (config.get_misc('webdav','enable',True)):
@@ -430,10 +583,80 @@
conf = OpenDAVConfig(**_dc)
handler._config = conf
reg_http_service(HTTPDir(directory,DAVHandler,DAVAuthProvider()))
- netsvc.Logger().notifyChannel('webdav', netsvc.LOG_INFO, "WebDAV service registered at path: %s/ "% directory)
+ logging.getLogger('webdav').info("WebDAV service registered at path: %s/ "% directory)
+
+ if not (config.get_misc('webdav', 'no_root_hack', False)):
+ # Now, replace the static http handler with the dav-enabled one.
+ # If a static-http service has been specified for our server, then
+ # read its configuration and use that dir_path.
+ # NOTE: this will _break_ any other service that would be registered
+ # at the root path in future.
+ base_path = False
+ if config.get_misc('static-http','enable', False):
+ base_path = config.get_misc('static-http', 'base_path', '/')
+ if base_path and base_path == '/':
+ dir_path = config.get_misc('static-http', 'dir_path', False)
+ else:
+ dir_path = addons.get_module_resource('document_webdav','public_html')
+ # an _ugly_ hack: we put that dir back in tools.config.misc, so that
+ # the StaticHttpHandler can find its dir_path.
+ config.misc.setdefault('static-http',{})['dir_path'] = dir_path
+
+ if reg_http_service(HTTPDir('/', DAVStaticHandler)):
+ logging.getLogger("web-services").info("WebDAV registered HTTP dir %s for /" % \
+ (dir_path))
+
except Exception, e:
- logger = netsvc.Logger()
- logger.notifyChannel('webdav', netsvc.LOG_ERROR, 'Cannot launch webdav: %s' % e)
+ logging.getLogger('webdav').error('Cannot launch webdav: %s' % e)
+
+
+def init_well_known():
+ reps = RedirectHTTPHandler.redirect_paths
+
+ num_svcs = config.get_misc('http-well-known', 'num_services', '0')
+
+ for nsv in range(1, int(num_svcs)+1):
+ uri = config.get_misc('http-well-known', 'service_%d' % nsv, False)
+ path = config.get_misc('http-well-known', 'path_%d' % nsv, False)
+ if not (uri and path):
+ continue
+ reps['/'+uri] = path
+
+ if int(num_svcs):
+ if http_server.reg_http_service(HTTPDir('/.well-known', RedirectHTTPHandler)):
+ logging.getLogger("web-services").info("Registered HTTP redirect handler at /.well-known" )
+
+init_well_known()
+
+class PrincipalsRedirect(RedirectHTTPHandler):
+ redirect_paths = {}
+
+ def _find_redirect(self):
+ for b, r in self.redirect_paths.items():
+ if self.path.startswith(b):
+ return r + self.path[len(b):]
+ return False
+
+def init_principals_redirect():
+ """ Some devices like the iPhone will look under /principals/users/xxx for
+ the user's properties. In OpenERP we _cannot_ have a stray /principals/...
+ working path, since we have a database path and the /webdav/ component. So,
+ the best solution is to redirect the url with 301. Luckily, it does work in
+ the device. The trick is that we need to hard-code the database to use, either
+ the one centrally defined in the config, or a "forced" one in the webdav
+ section.
+ """
+ dbname = config.get_misc('webdav', 'principal_dbname', False)
+ if (not dbname) and not config.get_misc('webdav', 'no_principals_redirect', False):
+ dbname = config.get('db_name', False)
+ if dbname:
+ PrincipalsRedirect.redirect_paths[''] = '/webdav/%s/principals' % dbname
+ reg_http_service(HTTPDir('/principals', PrincipalsRedirect))
+ logging.getLogger("web-services").info(
+ "Registered HTTP redirect handler for /principals to the %s db.",
+ dbname)
+
+init_principals_redirect()
#eof
=== modified file 'email_template/email_template.py'
=== modified file 'event_project/__init__.py'
--- event_project/__init__.py 2010-11-18 12:12:42 +0000
+++ event_project/__init__.py 2010-12-23 15:39:46 +0000
@@ -18,7 +18,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
-import event_project
+<<<<<<< TREE
+import event_project
+=======
+
+import event_project
+>>>>>>> MERGE-SOURCE
import wizard
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== removed file 'point_of_sale/pos_workflow.xml.orig'
--- point_of_sale/pos_workflow.xml.orig 2010-08-13 12:20:05 +0000
+++ point_of_sale/pos_workflow.xml.orig 1970-01-01 00:00:00 +0000
@@ -1,238 +0,0 @@
-<?xml version="1.0"?>
-<openerp>
- <data>
- <record model="workflow" id="wkf_pos">
- <field name="name">Pos workflow</field>
- <field name="osv">pos.order</field>
- <field name="on_create">True</field>
- </record>
-
- <!-- Roles definition -->
-
- <record model="res.roles" id="role_pos">
- <field name="name">POS - Confirmation</field>
- </record>
-
- <!--Activities-->
-
- <record model="workflow.activity" id="act_draft">
- <field name="wkf_id" ref="wkf_pos"/>
- <field name="flow_start">True</field>
- <field name="name">draft</field>
- </record>
-
- <record model="workflow.activity" id="act_payment">
- <field name="wkf_id" ref="wkf_pos" />
- <field name="name">payment</field>
- <field name="kind">function</field>
- <field name="action">write({'state': 'payment'})</field>
- </record>
-
- <record model="workflow.activity" id="act_rebate">
- <field name="wkf_id" ref="wkf_pos" />
- <field name="name">rebate</field>
- <field name="kind">function</field>
- <field name="action">write({'state': 'rebate'})</field>
- </record>
-
- <record model="workflow.activity" id="act_unbalanced">
- <field name="wkf_id" ref="wkf_pos" />
- <field name="name">unbalanced</field>
- <field name="kind">function</field>
- <field name="action">write({'state': 'unbalanced'})</field>
- </record>
-
- <record model="workflow.activity" id="act_cofinoga">
- <field name="wkf_id" ref="wkf_pos" />
- <field name="name">cofinoga</field>
- <field name="kind">function</field>
- <field name="action">write({'state': 'cofinoga'})</field>
- </record>
-
- <record model="workflow.activity" id="act_collectivites">
- <field name="wkf_id" ref="wkf_pos" />
- <field name="name">collectivites</field>
- <field name="kind">function</field>
- <field name="action">write({'state': 'collectivites'})</field>
- </record>
-
- <record model="workflow.activity" id="act_cadeaux">
- <field name="wkf_id" ref="wkf_pos" />
- <field name="name">cadeaux</field>
- <field name="kind">function</field>
- <field name="action">write({'state': 'cadeaux'})</field>
- </record>
-
- <record model="workflow.activity" id="act_collectivites">
- <field name="wkf_id" ref="wkf_pos" />
- <field name="name">collectivites</field>
- <field name="kind">function</field>
- <field name="action">write({'state': 'collectivites', 'invoice_wanted': True})</field>
- </record>
-
- <record model="workflow.activity" id="act_cadeaux">
- <field name="wkf_id" ref="wkf_pos" />
- <field name="name">cadeaux</field>
- <field name="kind">function</field>
- <field name="action">write({'state': 'cadeaux'})</field>
- </record>
-
- <record model="workflow.activity" id="act_paid">
- <field name="wkf_id" ref="wkf_pos"/>
- <field name="name">paid</field>
- <field name="action">action_paid()</field>
- <field name="kind">function</field>
- </record>
-
- <record model="workflow.activity" id="act_done">
- <field name="wkf_id" ref="wkf_pos"/>
- <field name="name">done</field>
- <field name="flow_stop">True</field>
- <field name="action">action_done()</field>
- <field name="kind">function</field>
- </record>
-
- <record model="workflow.activity" id="act_invoiced">
- <field name="wkf_id" ref="wkf_pos"/>
- <field name="name">invoiced</field>
- <field name="flow_stop">True</field>
- <field name="action">action_invoice()</field>
- <field name="kind">function</field>
- </record>
-
- <record model="workflow.activity" id="act_cancel">
- <field name="wkf_id" ref="wkf_pos"/>
- <field name="name">cancel</field>
- <field name="flow_stop">True</field>
- <field name="action">action_cancel()</field>
- <field name="kind">function</field>
- </record>
-
-
- <!--Transitions-->
-
- <record model="workflow.transition" id="trans_draft_payment">
- <field name="act_from" ref="act_draft" />
- <field name="act_to" ref="act_payment" />
- <field name="signal">start_payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_payment_paid">
- <field name="act_from" ref="act_payment"/>
- <field name="act_to" ref="act_paid"/>
- <field name="condition">test_paid() and not(test_rebate() or test_cofinoga() or test_cadeaux() or test_collectivites())</field>
- <field name="signal">payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_payment_rebate">
- <field name="act_from" ref="act_payment" />
- <field name="act_to" ref="act_rebate" />
- <field name="condition">test_rebate()</field>
- <field name="signal">payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_rebate_paid">
- <field name="act_from" ref="act_rebate" />
- <field name="act_to" ref="act_paid" />
- <field name="signal">ok_rebate</field>
- </record>
-
- <record model="workflow.transition" id="trans_payment_unbalanced">
- <field name="act_from" ref="act_payment" />
- <field name="act_to" ref="act_unbalanced" />
- <field name="condition">not test_paid()</field>
- <field name="signal">payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_unbalanced">
- <field name="act_from" ref="act_unbalanced" />
- <field name="act_to" ref="act_paid" />
- <field name="condition">test_paid()</field>
- </record>
-
- <record model="workflow.transition" id="trans_payment_cofinoga">
- <field name="act_from" ref="act_payment" />
- <field name="act_to" ref="act_cofinoga" />
- <field name="condition">test_cofinoga()</field>
- <field name="signal">payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_cofinoga_paid">
- <field name="act_from" ref="act_cofinoga" />
- <field name="act_to" ref="act_paid" />
- <field name="signal">ok_cofinoga</field>
- </record>
-
- <record model="workflow.transition" id="trans_payment_collectivites">
- <field name="act_from" ref="act_payment" />
- <field name="act_to" ref="act_collectivites" />
- <field name="condition">test_collectivites()</field>
- <field name="signal">payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_collectivites_paid">
- <field name="act_from" ref="act_collectivites" />
- <field name="act_to" ref="act_paid" />
- <field name="signal">ok_collectivites</field>
- </record>
-
- <record model="workflow.transition" id="trans_payment_cadeaux">
- <field name="act_from" ref="act_payment" />
- <field name="act_to" ref="act_cadeaux" />
- <field name="condition">test_cadeaux()</field>
- <field name="signal">payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_cadeaux_paid">
- <field name="act_from" ref="act_cadeaux" />
- <field name="act_to" ref="act_paid" />
- <field name="signal">ok_cadeaux</field>
- </record>
-
- <record model="workflow.transition" id="trans_payment_collectivites">
- <field name="act_from" ref="act_payment" />
- <field name="act_to" ref="act_collectivites" />
- <field name="condition">test_collectivites()</field>
- <field name="signal">payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_collectivites_paid">
- <field name="act_from" ref="act_collectivites" />
- <field name="act_to" ref="act_invoiced" />
- <field name="signal">ok_collectivites</field>
- </record>
-
- <record model="workflow.transition" id="trans_payment_cadeaux">
- <field name="act_from" ref="act_payment" />
- <field name="act_to" ref="act_cadeaux" />
- <field name="condition">test_cadeaux()</field>
- <field name="signal">payment</field>
- </record>
-
- <record model="workflow.transition" id="trans_cadeaux_paid">
- <field name="act_from" ref="act_cadeaux" />
- <field name="act_to" ref="act_paid" />
- <field name="signal">ok_cadeaux</field>
- </record>
-
- <record model="workflow.transition" id="trans_paid_done">
- <field name="act_from" ref="act_paid"/>
- <field name="act_to" ref="act_done"/>
- <field name="signal">done</field>
- </record>
-
- <record model="workflow.transition" id="trans_paid_invoice">
- <field name="act_from" ref="act_paid"/>
- <field name="act_to" ref="act_invoiced"/>
- <field name="signal">invoice</field>
- </record>
-
- <record model="workflow.transition" id="trans_paid_cancel">
- <field name="act_from" ref="act_paid"/>
- <field name="act_to" ref="act_cancel"/>
- <field name="signal">cancel</field>
- </record>
-
-
- </data>
-</openerp>
=== modified file 'users_ldap/users_ldap.py'
--- users_ldap/users_ldap.py 2010-12-14 15:33:48 +0000
+++ users_ldap/users_ldap.py 2010-12-23 15:39:46 +0000
@@ -136,7 +136,11 @@
def check(self, db, uid, passwd):
try:
return super(users,self).check(db, uid, passwd)
+<<<<<<< TREE
except security.ExceptionNoTb: # AccessDenied
+=======
+ except ExceptionNoTb: # AccessDenied
+>>>>>>> MERGE-SOURCE
pass
cr = pooler.get_db(db).cursor()
user = self.browse(cr, 1, uid)