diff --git a/product/CMFCategory/CategoryTool.py b/product/CMFCategory/CategoryTool.py
index 8323bad8a5bcadcb72e339f0de0a8ebd4e5b9ec7..c48a078b7e9161a01976e85925cebb0a4ed9e270 100644
--- a/product/CMFCategory/CategoryTool.py
+++ b/product/CMFCategory/CategoryTool.py
@@ -34,6 +34,7 @@ from OFS.Folder import Folder
 from Products.CMFCore.utils import UniqueObject
 from Globals import InitializeClass, DTMLFile
 from AccessControl import ClassSecurityInfo
+from AccessControl import Unauthorized, getSecurityManager
 from Acquisition import aq_base
 from Products.ERP5Type import Permissions
 from Products.ERP5Type.Base import Base
@@ -45,7 +46,7 @@ from OFS.Traversable import NotFound
 
 import re
 
-from zLOG import LOG, PROBLEM
+from zLOG import LOG, PROBLEM, WARNING
 
 _marker = object()
 
@@ -1511,23 +1512,76 @@ class CategoryTool( UniqueObject, Folder, Base ):
           except KeyError:
             pass
 
-        try:
-          obj = self.restrictedTraverse(relative_url)
-          if obj is None:
-            REQUEST = self.REQUEST
-            url = '%s/%s' % ('/'.join(self.getPhysicalPath()), relative_url)
-            #LOG("CMFCategory:",0,"Trying url %s" % url )
-            obj = self.portal_catalog.resolve_url(url, REQUEST)
-          #LOG('Obj type', 0, str(obj.getUid()))
-          value = obj
-        except (KeyError, AttributeError) :
-          LOG("CMFCategory WARNING",0,"Could not access object relative_url %s" % relative_url )
-          value = None
+        # This below is complicated, because we want to avoid acquisitions
+        # in most cases, but we still need to restrict the access.
+        # For instance, if the relative url is source/person_module/yo,
+        # only person_module should be acquired. This becomes very critical,
+        # for example, with source/sale_order_module/1/1/1, because
+        # we do not want to acquire a Sale Order when a Line or a Cell is
+        # not present.
+        # 
+        # In addition, the behavior of resolveCategory is weird, in that
+        # the relative url might not start with a base category. It can
+        # be without a base category, and this means that the first
+        # part must be acquired. This notation makes things quite
+        # unpredictable. Therefore, we will have to redesign this method
+        # in the future.
+        if isinstance(relative_url, basestring):
+          stack = relative_url.split('/')
+        else:
+          stack = list(relative_url)
+        stack.reverse()
+
+        validate = getSecurityManager().validate
+        key = stack.pop()
+        obj = self._getOb(key, None)
+        if obj is not None:
+          # The first one is a base category.
+          if not validate(self, self, key, obj):
+            raise Unauthorized('unauthorized access to element %s' % key)
+          base_category = obj
+
+          # Next, an object must be retrieved from a base category or
+          # a portal.
+          if stack:
+            key = stack.pop()
+            obj = base_category._getOb(key, None)
+            if obj is None:
+              portal = self.getPortalObject()
+              obj = portal._getOb(key, None)
+              if obj is not None:
+                if not validate(portal, base_category, key, obj):
+                  raise Unauthorized('unauthorized access to element %s' % key)
+                obj = obj.__of__(base_category)
+            else:
+              if not validate(base_category, base_category, key, obj):
+                raise Unauthorized('unauthorized access to element %s' % key)
+        else:
+          # The first one is a module.
+          portal = self.getPortalObject()
+          obj = portal._getOb(key, None)
+          if obj is not None:
+            if not validate(portal, portal, key, obj):
+              raise Unauthorized('unauthorized access to element %s' % key)
+
+        if obj is not None:
+          while stack:
+            container = obj
+            key = stack.pop()
+            obj = container._getOb(key, None)
+            if obj is None:
+              break
+            if not validate(container, container, key, obj):
+              raise Unauthorized('unauthorized access to element %s' % key)
+
+        if obj is None:
+          LOG('CMFCategory', WARNING, 
+              'Could not access object %s' % relative_url)
 
         if cache is not None:
-          cache[key] = value
+          cache[key] = obj
 
-        return value
+        return obj
 
 InitializeClass( CategoryTool )
 
diff --git a/product/CMFCategory/tests/testCMFCategory.py b/product/CMFCategory/tests/testCMFCategory.py
index d92371ce24eb150325c1c66918d7fb15293eb92a..d015e532b310e3ee20a29a138e7b64f2c6c3509c 100644
--- a/product/CMFCategory/tests/testCMFCategory.py
+++ b/product/CMFCategory/tests/testCMFCategory.py
@@ -1016,7 +1016,7 @@ class TestCMFCategory(ERP5TypeTestCase):
       bc.getCategoryChildTitleItemList(checked_permission=checked_permission,
                                        cache=0))
 
-  def test_renameBaseCategory(self):
+  def test_29_renameBaseCategory(self):
     bc = self.portal.portal_categories.newContent(
                           portal_type='Base Category',
                           id='first_id')
@@ -1025,6 +1025,36 @@ class TestCMFCategory(ERP5TypeTestCase):
     bc.setId('new_id')
     self.assertEquals('new_id', bc.getId())
 
+  def test_30_resolveCategory(self):
+    portal = self.getPortal()
+    category_tool = portal.portal_categories
+    module = portal.sale_order_module
+    order = module.newContent(id='foo', portal_type='Sale Order')
+    self.assertNotEquals(order, None)
+    line = order.newContent(id='bar', portal_type='Sale Order Line')
+    self.assertNotEquals(line, None)
+    cell = line.newContent(id='baz', portal_type='Sale Order Cell')
+    self.assertNotEquals(cell, None)
+    get_transaction().commit()
+    self.tic()
+
+    for relative_url, value in (
+            ('sale_order_module', module),
+            ('sale_order_module/foo', order),
+            ('sale_order_module/bar', None),
+            ('sale_order_module/sale_order_module', None),
+            ('sale_order_module/foo/bar', line),
+            ('sale_order_module/foo/foo', None),
+            ('sale_order_module/foo/sale_order_module', None),
+            ('sale_order_module/foo/bar/baz', cell),
+            ('sale_order_module/foo/bar/bar', None),
+            ('sale_order_module/foo/bar/foo', None),
+            ('sale_order_module/foo/bar/sale_order_module', None),
+            ):
+      obj = category_tool.resolveCategory(relative_url)
+      self.assertEquals(obj, value)
+      obj = category_tool.resolveCategory('order/' + relative_url)
+      self.assertEquals(obj, value)
 
 def test_suite():
   suite = unittest.TestSuite()