Пример #1
0
 def __init__(self, *args, **kw):
   BaseTool.__init__(self, *args, **kw)
   # XXX Cache information about running test results, because the protocol
   #     is synchronous and we can't rely on the catalog.
   #     This is a hack until a better (and asynchronous) protocol is
   #     implemented.
   self.test_result_dict = {}
Пример #2
0
    def manage_afterAdd(self, item, container):
        """Init permissions right after creation.

    Permissions in tool are simple:
     o Each member can access the tool.
     o Only manager can view and create.
     o Anonymous can not access
    """
        item.manage_permission(Permissions.AddPortalContent, ["Manager"])
        item.manage_permission(Permissions.AccessContentsInformation, ["Member", "Manager"])
        item.manage_permission(Permissions.View, ["Manager"])
        BaseTool.inheritedAttribute("manage_afterAdd")(self, item, container)
Пример #3
0
  def manage_afterAdd(self, item, container) :
    """Init permissions right after creation.

    Permissions in tool are simple:
     o Each member can access the tool.
     o Only manager can view and create.
     o Anonymous can not access
    """
    item.manage_permission(Permissions.AddPortalContent,
          ['Manager'])
    item.manage_permission(Permissions.AccessContentsInformation,
          ['Member', 'Manager'])
    item.manage_permission(Permissions.View,
          ['Manager',])
    BaseTool.inheritedAttribute('manage_afterAdd')(self, item, container)
Пример #4
0
 def manage_afterAdd(self, item, container) :
   """ init the permissions right after creation """
   item.manage_permission(Permissions.AddPortalContent,
         ['Member', 'Author', 'Manager'])
   item.manage_permission(Permissions.AddPortalFolders,
         ['Member', 'Author', 'Manager'])
   item.manage_permission(Permissions.View,
         ['Member', 'Auditor', 'Manager'])
   item.manage_permission(Permissions.CopyOrMove,
         ['Member', 'Auditor', 'Manager'])
   item.manage_permission(Permissions.ManageProperties,
         ['Manager'], acquire=0)
   item.manage_permission(Permissions.SetOwnPassword,
         ['Member', 'Author', 'Manager'])
   BaseTool.inheritedAttribute('manage_afterAdd')(self, item, container)
Пример #5
0
 def manage_afterAdd(self, item, container):
     """ init the permissions right after creation """
     item.manage_permission(Permissions.AddPortalContent,
                            ['Member', 'Author', 'Manager'])
     item.manage_permission(Permissions.AddPortalFolders,
                            ['Member', 'Author', 'Manager'])
     item.manage_permission(Permissions.View,
                            ['Member', 'Auditor', 'Manager'])
     item.manage_permission(Permissions.CopyOrMove,
                            ['Member', 'Auditor', 'Manager'])
     item.manage_permission(Permissions.ManageProperties, ['Manager'],
                            acquire=0)
     item.manage_permission(Permissions.SetOwnPassword,
                            ['Member', 'Author', 'Manager'])
     BaseTool.inheritedAttribute('manage_afterAdd')(self, item, container)
Пример #6
0
 def filtered_meta_types(self, user=None):
   # Filters the list of available meta types.
   all = BaseTool.inheritedAttribute('filtered_meta_types')(self)
   meta_types = []
   for meta_type in self.all_meta_types():
     if meta_type['name'] in self.allowed_types:
       meta_types.append(meta_type)
   return meta_types
Пример #7
0
  def _getOb(self, id, default=_marker):
    """
    Check for volatile temp object info first
    and try to find it
    """
    # Use the document cache if possible and return result immediately
    # this is only useful for webdav
    volatile_cache = getattr(self, '_v_document_cache', None)
    if volatile_cache is not None:
      document_url = volatile_cache.get(id)
      if document_url is not None:
        del volatile_cache[id]
        return self.getPortalObject().unrestrictedTraverse(document_url)

    # Try first to return the real object inside
    # This is much safer than trying to access objects displayed by listDAVObjects
    # because the behaviour of catalog is unpredicatble if a string is passed
    # for a UID. For example 
    #   select path from catalog where uid = "001193.html";
    # will return the same as
    #   select path from catalog where uid = 1193;
    # This was the source of an error in which the contribution tool
    # was creating a web page and was returning a Base Category
    # when
    #   o = folder._getOb(id)
    # was called in DocumentConstructor
    if default is _marker:
      result = BaseTool._getOb(self, id)
    else:
      result = BaseTool._getOb(self, id, default=default)
    if result is not None:
      # if result is None, ignore it at this stage
      # we can be more lucky with portal_catalog
      return result

    # Return an object listed by listDAVObjects
    # ids are concatenation of uid + '-' + standard file name of documents
    # get the uid
    uid = str(id).split('-', 1)[0]
    object = self.getPortalObject().portal_catalog.unrestrictedGetResultValue(uid=uid)
    if object is not None:
      return object.getObject() # Make sure this does not break security. XXX
    if default is not _marker:
      return default
    # Raise an AttributeError the same way as in OFS.ObjectManager._getOb
    raise AttributeError, id
Пример #8
0
 def filtered_meta_types(self, user=None):
     # Filters the list of available meta types.
     all = BaseTool.inheritedAttribute('filtered_meta_types')(self)
     meta_types = []
     for meta_type in self.all_meta_types():
         if meta_type['name'] in self.allowed_types:
             meta_types.append(meta_type)
     return meta_types
Пример #9
0
 def getTypeInfo(self, *args):
     if not args:
         return BaseTool.getTypeInfo(self)
     portal_type, = args
     if not isinstance(portal_type, basestring):
         try:
             portal_type = aq_base(portal_type).getPortalType()
         except AttributeError:
             return None
     return getattr(self, portal_type, None)
Пример #10
0
 def getTypeInfo(self, *args):
     if not args:
         return BaseTool.getTypeInfo(self)
     portal_type, = args
     if not isinstance(portal_type, basestring):
         try:
             portal_type = aq_base(portal_type).getPortalType()
         except AttributeError:
             return None
     return getattr(self, portal_type, None)
Пример #11
0
 def newContent(self, *args, **kw):
   """
     the newContent is overriden to not use generateNewId
   """
   if id not in kw:
     new_id = self._generateNextId()
     if new_id is not None:
       kw['id'] = new_id
     else:
       raise ValueError('Failed to gererate id')
   return BaseTool.newContent(self, *args, **kw)
Пример #12
0
 def newContent(self, *args, **kw):
   """
     the newContent is overriden to not use generateNewId
   """
   if not kw.has_key(id):
     new_id = self._generateNextId()
     if new_id is not None:
       kw['id'] = new_id
     else:
       raise ValueError('Failed to gererate id')
   return BaseTool.newContent(self, *args, **kw)
Пример #13
0
 def __setstate__(self, value):
   """
   Delete object() attributes which has never been used and whose classes
   code has been deleted and dummy classes kept only to allow unpickle of
   portal_oauth which happens before __setstate__() is called...
   """
   BaseTool.__setstate__(self, value)
   is_already_migrated = True
   for attribute_name in ('consumer', 'my_access_token', 'my_request_token', 'signature_methods'):
     try:
       delattr(self, attribute_name)
       is_already_migrated = False
     except AttributeError:
       pass
   if not is_already_migrated:
     # str attributes
     for attribute_name in ('verifier', 'nonce'):
       try:
         delattr(self, attribute_name)
       except AttributeError:
         pass
Пример #14
0
    def _aq_dynamic(self, id):
        """Get a type information from a provider
    """
        result = BaseTool._aq_dynamic(self, id)
        if result is not None:
            return result

        if id in self.type_provider_list:
            return None

        default = []
        for provider in self.type_provider_list:
            provider_value = getattr(self, provider, None)
            if provider_value is not None:
                ob = provider_value._getOb(id, default=default)
                if ob is not default:
                    return ob
        return None
Пример #15
0
    def _aq_dynamic(self, id):
        """Get a type information from a provider
    """
        result = BaseTool._aq_dynamic(self, id)
        if result is not None:
            return result

        if id in self.type_provider_list:
            return None

        default = []
        for provider in self.type_provider_list:
            provider_value = getattr(self, provider, None)
            if provider_value is not None:
                ob = provider_value._getOb(id, default=default)
                if ob is not default:
                    return ob
        return None
Пример #16
0
 def manage_beforeDelete(self, item, container):
   self.unsubscribe()
   BaseTool.inheritedAttribute('manage_beforeDelete')(self, item, container)
Пример #17
0
 def __init__(self, id=''):
     ZCatalog.__init__(self, self.getId())
     BaseTool.__init__(self, self.getId())
Пример #18
0
 def _verifyObjectPaste(self, *args, **kw):
   return BaseTool._verifyObjectPaste(self, *args, **kw)
Пример #19
0
 def _verifyObjectPaste(self, *args, **kw):
     return BaseTool._verifyObjectPaste(self, *args, **kw)
Пример #20
0
 def manage_afterAdd(self, item, container):
   self.subscribe()
   BaseTool.inheritedAttribute('manage_afterAdd')(self, item, container)
Пример #21
0
    def _setObject(self,
                   id,
                   ob,
                   portal_type=None,
                   user_login=None,
                   container=None,
                   discover_metadata=True,
                   filename=None,
                   input_parameter_dict=None):
        """
      portal_contribution_registry will find appropriate portal type
      name by filename and content itself.

      The ContributionTool instance must be configured in such
      way that _verifyObjectPaste will return TRUE.

    """
        # _setObject is called by constructInstance at a time
        # when the object has no portal_type defined yet. It
        # will be removed later on. We can safely store the
        # document inside us at this stage. Else we
        # must find out where to store it.
        if ob is not None:
            # Called from webdav API
            # Object is already created by PUT_factory
            # fill the volatile cache _v_document_cache
            # then return the document
            document = ob
        else:
            if not portal_type:
                document = BaseTool.newContent(self,
                                               id=id,
                                               portal_type=portal_type,
                                               is_indexable=0)
            elif ob is None:
                # We give the system a last chance to analyse the
                # portal_type based on the document content
                # (ex. a Memo is a kind of Text which can be identified
                # by the fact it includes some specific content)

                # Now we know the portal_type, let us find the module
                # to which we should move the document to
                if container is None:
                    module = self.getDefaultModule(portal_type)
                else:
                    module = container
                # There is no preexisting document - we can therefore
                # set the new object
                new_content_kw = {
                    'portal_type': portal_type,
                    'is_indexable': False
                }
                if id is not None:
                    new_content_kw['id'] = id
                document = module.newContent(**new_content_kw)
                # We can now discover metadata
                if discover_metadata:
                    # Metadata disovery is done as an activity by default
                    # If we need to discoverMetadata synchronously, it must
                    # be for user interface and should thus be handled by
                    # ZODB scripts
                    document.activate(after_path_and_method_id=(
                        document.getPath(),
                        ('convertToBaseFormat',
                         'Document_tryToConvertToBaseFormat'),
                    ), ).discoverMetadata(
                        filename=filename,
                        user_login=user_login,
                        input_parameter_dict=input_parameter_dict)
        # Keep the document close to us - this is only useful for
        # file upload from webdav
        volatile_cache = getattr(self, '_v_document_cache', None)
        if volatile_cache is None:
            self._v_document_cache = {}
            volatile_cache = self._v_document_cache
        volatile_cache[document.getId()] = document.getRelativeUrl()
        # Return document to newContent method
        return document
Пример #22
0
    def newContent(self, REQUEST=None, **kw):
        """
      The newContent method is overriden to implement smart content
      creation by detecting the portal type based on whatever information
      was provided and finding out the most appropriate module to store
      the content.

      explicit named parameters was:
        id - id of document
        portal_type - explicit portal_type parameter, must be honoured
        url - Identifier of external resource. Content will be downloaded
              from it
        container - if specified, it is possible to define
                    where to contribute the content. Else, ContributionTool
                    tries to guess.
        container_path - if specified, defines the container path
                         and has precedence over container
        discover_metadata - Enable metadata extraction and discovery
                            (default True)
        temp_object - build tempObject or not (default False)
        user_login - is the name under which the content will be created
                     XXX - this is a security hole which needs to be fixed by
                     making sure only Manager can use this parameter
        data - Binary representation of content
        filename - explicit filename of content
    """
        # Useful for metadata discovery, keep it as it as been provided
        input_parameter_dict = kw.copy()
        # But file and data are exceptions.
        # They are potentialy too big to be keept into memory.
        # We want to keep only one reference of thoses values
        # on futur created document only !
        if 'file' in input_parameter_dict:
            del input_parameter_dict['file']
        if 'data' in input_parameter_dict:
            del input_parameter_dict['data']
        if 'container' in input_parameter_dict:
            # Container is a persistent object
            # keep only its path in container_path key
            container = input_parameter_dict.pop('container')
            input_parameter_dict['container_path'] = container.getPath()
        # pop: remove keys which are not document properties
        url = kw.pop('url', None)
        container = kw.pop('container', None)
        container_path = kw.pop('container_path', None)
        discover_metadata = kw.pop('discover_metadata', True)
        user_login = kw.pop('user_login', None)
        document_id = kw.pop('id', None)
        # check file_name argument for backward compatibility.
        if 'file_name' in kw:
            if 'filename' not in kw:
                kw['filename'] = kw['file_name']
            del (kw['file_name'])
        filename = kw.get('filename', None)
        temp_object = kw.get('temp_object', False)

        document = None
        portal = self.getPortalObject()
        if container is None and container_path:
            # Get persistent object from its path.
            # Container may disappear, be smoother by passing default value
            container = portal.restrictedTraverse(container_path, None)
        # Try to find the filename
        if not url:
            # check if file was provided
            file_object = kw.get('file')
            if file_object is not None:
                if not filename:
                    filename = getattr(file_object, 'filename', None)
            else:
                # some channels supply data and file-name separately
                # this is the case for example for email ingestion
                # in this case, we build a file wrapper for it
                try:
                    data = kw.pop('data')
                except KeyError:
                    raise ValueError('data must be provided')
                if data is not None:
                    file_object = cStringIO.StringIO()
                    file_object.write(data)
                    file_object.seek(0)
                    kw['file'] = file_object
            content_type = kw.pop('content_type', None)
        else:
            file_object, filename, content_type = self._openURL(url)
            content_type = kw.pop('content_type', None) or content_type
            kw['file'] = file_object

        if not filename and url is None:
            raise ValueError('filename must be provided')

        if not content_type:
            # fallback to a default content_type according provided
            # filename
            content_type = self.guessMimeTypeFromFilename(filename)
        if content_type:
            kw['content_type'] = content_type

        portal_type = kw.pop('portal_type', None)
        if not portal_type:
            # Guess it with help of portal_contribution_registry
            portal_type = portal.portal_contribution_registry.findPortalTypeName(
                filename=filename, content_type=content_type)
            if not (container is None or container.isModuleType()
                    or container.getTypeInfo().allowType(portal_type)):
                portal_type = 'Embedded File'

        if container is None:
            # If the portal_type was provided, we can go faster
            if portal_type:
                # We know the portal_type, let us find the default module
                # and use it as container
                try:
                    container = portal.getDefaultModule(portal_type)
                except ValueError:
                    pass

        elif not url:
            # Simplify things here and return a document immediately
            # XXX Nicolas: This will break support of WebDAV
            # if _setObject is not called
            document = container.newContent(document_id, portal_type, **kw)
            if discover_metadata:
                document.activate(after_path_and_method_id=(document.getPath(),
                    ('convertToBaseFormat', 'Document_tryToConvertToBaseFormat')))\
                      .discoverMetadata(filename=filename,
                                        user_login=user_login,
                                        input_parameter_dict=input_parameter_dict)
            if REQUEST is not None:
                response = REQUEST.RESPONSE
                response.setHeader('X-Location', document.absolute_url())
                return response.redirect(self.absolute_url())
            return document

        #
        # Check if same file is already exists. if it exists, then update it.
        #
        property_dict = self.getMatchedFilenamePatternDict(filename)
        reference = property_dict.get('reference', None)
        version = property_dict.get('version', None)
        language = property_dict.get('language', None)
        if portal_type and reference and version and language:
            portal_catalog = portal.portal_catalog
            document = portal_catalog.getResultValue(portal_type=portal_type,
                                                     reference=reference,
                                                     version=version,
                                                     language=language)

            if document is not None:
                # document is already uploaded. So overrides file.
                if not _checkPermission(Permissions.ModifyPortalContent,
                                        document):
                    raise Unauthorized, "[DMS] You are not allowed to update the existing document which has the same coordinates (id %s)" % document.getId(
                    )
                document.edit(file=kw['file'])
                return document
        # Temp objects use the standard newContent from Folder
        if temp_object:
            # For temp_object creation, use the standard method
            return BaseTool.newContent(self, portal_type=portal_type, **kw)

        # Then put the file inside ourselves for a short while
        document = self._setObject(document_id,
                                   None,
                                   portal_type=portal_type,
                                   user_login=user_login,
                                   container=container,
                                   discover_metadata=discover_metadata,
                                   filename=filename,
                                   input_parameter_dict=input_parameter_dict)
        object_id = document.getId()
        document = self[object_id]  # Call __getitem__ to purge cache

        kw['filename'] = filename  # Override filename property
        # Then edit the document contents (so that upload can happen)
        document._edit(**kw)
        if url:
            document.fromURL(url)

        # Allow reindexing, reindex it and return the document
        try:
            del document.isIndexable
        except AttributeError:
            # Document does not have such attribute
            pass
        document.reindexObject()
        if REQUEST is not None:
            return REQUEST.RESPONSE.redirect(self.absolute_url())
        return document
Пример #23
0
  def newContent(self, REQUEST=None, **kw):
    """
      The newContent method is overriden to implement smart content
      creation by detecting the portal type based on whatever information
      was provided and finding out the most appropriate module to store
      the content.

      explicit named parameters was:
        id - id of document
        portal_type - explicit portal_type parameter, must be honoured
        url - Identifier of external resource. Content will be downloaded
              from it
        container - if specified, it is possible to define
                    where to contribute the content. Else, ContributionTool
                    tries to guess.
        container_path - if specified, defines the container path
                         and has precedence over container
        discover_metadata - Enable metadata extraction and discovery
                            (default True)
        temp_object - build tempObject or not (default False)
        user_login - is the name under which the content will be created
                     XXX - this is a security hole which needs to be fixed by
                     making sure only Manager can use this parameter
        data - Binary representation of content
        filename - explicit filename of content
    """
    # Useful for metadata discovery, keep it as it as been provided
    input_parameter_dict = kw.copy()
    # But file and data are exceptions.
    # They are potentialy too big to be keept into memory.
    # We want to keep only one reference of thoses values
    # on futur created document only !
    if 'file' in input_parameter_dict:
      del input_parameter_dict['file']
    if 'data' in input_parameter_dict:
      del input_parameter_dict['data']
    if 'container' in input_parameter_dict:
      # Container is a persistent object
      # keep only its path in container_path key
      container = input_parameter_dict.pop('container')
      input_parameter_dict['container_path'] = container.getPath()
    # pop: remove keys which are not document properties
    url = kw.pop('url', None)
    container = kw.pop('container', None)
    container_path = kw.pop('container_path', None)
    discover_metadata = kw.pop('discover_metadata', True)
    user_login = kw.pop('user_login', None)
    document_id = kw.pop('id', None)
    # check file_name argument for backward compatibility.
    if 'file_name' in kw:
      if 'filename' not in kw:
        kw['filename'] = kw['file_name']
      del(kw['file_name'])
    filename = kw.get('filename', None)
    temp_object = kw.get('temp_object', False)

    document = None
    portal = self.getPortalObject()
    if container is None and container_path:
      # Get persistent object from its path.
      # Container may disappear, be smoother by passing default value
      container = portal.restrictedTraverse(container_path, None)
    # Try to find the filename
    if not url:
      # check if file was provided
      file_object = kw.get('file')
      if file_object is not None:
        if not filename:
          filename = getattr(file_object, 'filename', None)
      else:
        # some channels supply data and file-name separately
        # this is the case for example for email ingestion
        # in this case, we build a file wrapper for it
        try:
          data = kw.pop('data')
        except KeyError:
          raise ValueError('data must be provided')
        if data is not None:
          file_object = cStringIO.StringIO()
          file_object.write(data)
          file_object.seek(0)
          kw['file'] = file_object
      content_type = kw.pop('content_type', None)
    else:
      file_object, filename, content_type = self._openURL(url)
      content_type = kw.pop('content_type', None) or content_type
      kw['file'] = file_object

    if not filename and url is None:
      raise ValueError('filename must be provided')

    if not content_type:
      # fallback to a default content_type according provided
      # filename
      content_type = self.guessMimeTypeFromFilename(filename)
    if content_type:
      kw['content_type'] = content_type

    portal_type = kw.pop('portal_type', None)
    if not portal_type:
      # Guess it with help of portal_contribution_registry
      portal_type = portal.portal_contribution_registry.findPortalTypeName(
        filename=filename, content_type=content_type)
      if not (container is None or container.isModuleType() or
              container.getTypeInfo().allowType(portal_type)):
          portal_type = 'Embedded File'

    if container is None:
      # If the portal_type was provided, we can go faster
      if portal_type:
        # We know the portal_type, let us find the default module
        # and use it as container
        try:
          container = portal.getDefaultModule(portal_type)
        except ValueError:
          pass

    elif not url:
      # Simplify things here and return a document immediately
      # XXX Nicolas: This will break support of WebDAV
      # if _setObject is not called
      document = container.newContent(document_id, portal_type, **kw)
      if discover_metadata:
        document.activate(after_path_and_method_id=(document.getPath(),
            ('convertToBaseFormat', 'Document_tryToConvertToBaseFormat')))\
              .discoverMetadata(filename=filename,
                                user_login=user_login,
                                input_parameter_dict=input_parameter_dict)
      if REQUEST is not None:
        response = REQUEST.RESPONSE
        response.setHeader('X-Location', document.absolute_url())
        return response.redirect(self.absolute_url())
      return document

    #
    # Check if same file is already exists. if it exists, then update it.
    #
    property_dict = self.getMatchedFilenamePatternDict(filename)
    reference = property_dict.get('reference', None)
    version  = property_dict.get('version', None)
    language  = property_dict.get('language', None)
    if portal_type and reference and version and language:
      portal_catalog = portal.portal_catalog
      document = portal_catalog.getResultValue(portal_type=portal_type,
                                               reference=reference,
                                               version=version,
                                               language=language)

      if document is not None:
        # document is already uploaded. So overrides file.
        if not _checkPermission(Permissions.ModifyPortalContent, document):
          raise Unauthorized, "[DMS] You are not allowed to update the existing document which has the same coordinates (id %s)" % document.getId()
        document.edit(file=kw['file'])
        return document
    # Temp objects use the standard newContent from Folder
    if temp_object:
      # For temp_object creation, use the standard method
      return BaseTool.newContent(self, portal_type=portal_type, **kw)

    # Then put the file inside ourselves for a short while
    document = self._setObject(document_id, None, portal_type=portal_type,
                               user_login=user_login, container=container,
                               discover_metadata=discover_metadata,
                               filename=filename,
                               input_parameter_dict=input_parameter_dict
                               )
    object_id = document.getId()
    document = self[object_id] # Call __getitem__ to purge cache

    kw['filename'] = filename # Override filename property
    # Then edit the document contents (so that upload can happen)
    document._edit(**kw)
    if url:
      document.fromURL(url)

    # Allow reindexing, reindex it and return the document
    try:
      del document.isIndexable
    except AttributeError:
      # Document does not have such attribute
      pass
    document.reindexObject()
    if REQUEST is not None:
      return REQUEST.RESPONSE.redirect(self.absolute_url())
    return document
Пример #24
0
  def _setObject(self, id, ob, portal_type=None, user_login=None,
                 container=None, discover_metadata=True, filename=None,
                 input_parameter_dict=None):
    """
      portal_contribution_registry will find appropriate portal type
      name by filename and content itself.

      The ContributionTool instance must be configured in such
      way that _verifyObjectPaste will return TRUE.

    """
    # _setObject is called by constructInstance at a time
    # when the object has no portal_type defined yet. It
    # will be removed later on. We can safely store the
    # document inside us at this stage. Else we
    # must find out where to store it.
    if ob is not None:
      # Called from webdav API
      # Object is already created by PUT_factory
      # fill the volatile cache _v_document_cache
      # then return the document
      document = ob
    else:
      if not portal_type:
        document = BaseTool.newContent(self, id=id,
                                      portal_type=portal_type,
                                      is_indexable=0)
      elif ob is None:
        # We give the system a last chance to analyse the
        # portal_type based on the document content
        # (ex. a Memo is a kind of Text which can be identified
        # by the fact it includes some specific content)

        # Now we know the portal_type, let us find the module
        # to which we should move the document to
        if container is None:
          module = self.getDefaultModule(portal_type)
        else:
          module = container
        # There is no preexisting document - we can therefore
        # set the new object
        new_content_kw = {'portal_type': portal_type,
                          'is_indexable': False}
        if id is not None:
          new_content_kw['id'] = id
        document = module.newContent(**new_content_kw)
        # We can now discover metadata
        if discover_metadata:
          # Metadata disovery is done as an activity by default
          # If we need to discoverMetadata synchronously, it must
          # be for user interface and should thus be handled by
          # ZODB scripts
          document.activate(after_path_and_method_id=(document.getPath(),
            ('convertToBaseFormat', 'Document_tryToConvertToBaseFormat',
             'immediateReindexObject', 'recursiveImmediateReindexObject')))\
          .discoverMetadata(filename=filename,
                            user_login=user_login,
                            input_parameter_dict=input_parameter_dict)
    # Keep the document close to us - this is only useful for
    # file upload from webdav
    volatile_cache = getattr(self, '_v_document_cache', None)
    if volatile_cache is None:
      self._v_document_cache = {}
      volatile_cache = self._v_document_cache
    volatile_cache[document.getId()] = document.getRelativeUrl()
    # Return document to newContent method
    return document