backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 12 Aug 2010 10:12:52 +0200
changeset 6102 27c47d239739
parent 6096 09f2c4d24d01 (current diff)
parent 6101 1aff7367a20c (diff)
child 6139 f76599a96238
backport stable
--- a/entity.py	Wed Aug 11 10:08:48 2010 +0200
+++ b/entity.py	Thu Aug 12 10:12:52 2010 +0200
@@ -51,6 +51,18 @@
                 return card
     return '1'
 
+def can_use_rest_path(value):
+    """return True if value can be used at the end of a Rest URL path"""
+    if value is None:
+        return False
+    value = unicode(value)
+    # the check for ?, /, & are to prevent problems when running
+    # behind Apache mod_proxy
+    if value == u'' or u'?' in value or u'/' in value or u'&' in value:
+        return False
+    return True
+
+
 
 class Entity(AppObject):
     """an entity instance has e_schema automagically set on
@@ -479,11 +491,15 @@
         # in linksearch mode, we don't want external urls else selecting
         # the object for use in the relation is tricky
         # XXX search_state is web specific
-        if getattr(self._cw, 'search_state', ('normal',))[0] == 'normal':
+        if 'base-url' not in kwargs and \
+               getattr(self._cw, 'search_state', ('normal',))[0] == 'normal':
             kwargs['base_url'] = self.cw_metainformation()['source'].get('base-url')
+            use_ext_id = bool(kwargs['base_url'])
+        else:
+            use_ext_id = False
         if method in (None, 'view'):
             try:
-                kwargs['_restpath'] = self.rest_path(kwargs.get('base_url'))
+                kwargs['_restpath'] = self.rest_path(use_ext_id)
             except TypeError:
                 warn('[3.4] %s: rest_path() now take use_ext_eid argument, '
                      'please update' % self.__regid__, DeprecationWarning)
@@ -499,7 +515,7 @@
         path = etype.lower()
         if mainattr != 'eid':
             value = getattr(self, mainattr)
-            if value is None or unicode(value) == u'':
+            if not can_use_rest_path(value):
                 mainattr = 'eid'
                 path += '/eid'
             elif needcheck:
--- a/hooks/syncschema.py	Wed Aug 11 10:08:48 2010 +0200
+++ b/hooks/syncschema.py	Thu Aug 12 10:12:52 2010 +0200
@@ -119,7 +119,6 @@
     for specialization in eschema.specialized_by(False):
         if (specialization, rdefdef.object) in rschema.rdefs:
             continue
-        print 'adding infered', specialization, rschema.type, object
         sperdef = RelationDefinitionSchema(specialization, rschema,
                                            object, props)
         ss.execschemarql(session.execute, sperdef,
--- a/test/unittest_entity.py	Wed Aug 11 10:08:48 2010 +0200
+++ b/test/unittest_entity.py	Thu Aug 12 10:12:52 2010 +0200
@@ -492,8 +492,14 @@
         # unique attr with None value (wikiid in this case)
         card1 = req.create_entity('Card', title=u'hop')
         self.assertEquals(card1.rest_path(), 'card/eid/%s' % card1.eid)
-        card2 = req.create_entity('Card', title=u'pod', wikiid=u'zob/i')
-        self.assertEquals(card2.rest_path(), 'card/zob%2Fi')
+        # don't use rest if we have /, ? or & in the path (breaks mod_proxy)
+        card2 = req.create_entity('Card', title=u'pod', wikiid=u'zo/bi')
+        self.assertEquals(card2.rest_path(), 'card/eid/%d' % card2.eid)
+        card3 = req.create_entity('Card', title=u'pod', wikiid=u'zo&bi')
+        self.assertEquals(card3.rest_path(), 'card/eid/%d' % card3.eid)
+        card4 = req.create_entity('Card', title=u'pod', wikiid=u'zo?bi')
+        self.assertEquals(card4.rest_path(), 'card/eid/%d' % card4.eid)
+        
 
     def test_set_attributes(self):
         req = self.request()
--- a/web/views/autoform.py	Wed Aug 11 10:08:48 2010 +0200
+++ b/web/views/autoform.py	Thu Aug 12 10:12:52 2010 +0200
@@ -952,6 +952,10 @@
 
     def etype_relation_field(etype, rtype, role='subject'):
         eschema = vreg.schema.eschema(etype)
-        return AutomaticEntityForm.field_by_name(rtype, role, eschema)
+        try:
+            return AutomaticEntityForm.field_by_name(rtype, role, eschema)
+        except f.FieldNotFound:
+            AutomaticEntityForm.error('field for %s %s may not be found in schema' % (rtype, role))
+            return None
 
     vreg.register_all(globals().values(), __name__)