diff --git a/bt5/erp5_corporate_identity/SkinTemplateItem/portal_skins/erp5_corporate_identity/WebPage_finishPdfCreation.py b/bt5/erp5_corporate_identity/SkinTemplateItem/portal_skins/erp5_corporate_identity/WebPage_finishPdfCreation.py
index 0fdc074e8cb0aaf10a7fac25c0ee6566e7552526..0fa3ce91d22bcd4bc2e638ea40e22e18572f5c34 100644
--- a/bt5/erp5_corporate_identity/SkinTemplateItem/portal_skins/erp5_corporate_identity/WebPage_finishPdfCreation.py
+++ b/bt5/erp5_corporate_identity/SkinTemplateItem/portal_skins/erp5_corporate_identity/WebPage_finishPdfCreation.py
@@ -17,6 +17,8 @@ Save, download or return generated PDF Document
 # doc_pdf_file                        pdf content to store
 # doc_aggregate_list                  not applicable (only used for events)
 
+from io import BytesIO
+
 if doc_save:
   dms_module = getattr(context, 'document_module', None)
   if dms_module is not None:
@@ -31,7 +33,7 @@ if doc_save:
     )
     document.edit(
       source_reference=''.join([doc_reference, '.pdf']),
-      file=doc_pdf_file
+      file=BytesIO(doc_pdf_file)
     )
     document.setContentType("application/pdf")
 
diff --git a/product/ERP5/Document/File.py b/product/ERP5/Document/File.py
index 10cb3668d63f4de1f04888ae8b448a9a1ff9e14b..df829d234afeb2eb1e6f47360f582a987f225f89 100644
--- a/product/ERP5/Document/File.py
+++ b/product/ERP5/Document/File.py
@@ -27,6 +27,7 @@
 #
 ##############################################################################
 
+from DateTime import DateTime
 from AccessControl import ClassSecurityInfo
 from Products.ERP5Type.Base import WorkflowMethod
 from Products.ERP5Type import Permissions, PropertySheet
@@ -34,8 +35,7 @@ from Products.ERP5.Document.Document import Document, VALID_TEXT_FORMAT_LIST
 from Products.ERP5.Document.Document import VALID_IMAGE_FORMAT_LIST
 from Products.ERP5.Document.Document import ConversionError
 from Products.ERP5Type.Base import Base, removeIContentishInterface
-from Products.CMFDefault.File import File as CMFFile
-from OFS.Image import Pdata
+from OFS.Image import File as OFS_File
 from cStringIO import StringIO
 from Products.ERP5Type.Utils import deprecated
 
@@ -48,7 +48,7 @@ def _unpackData(data):
 
 _MARKER = object()
 
-class File(Document, CMFFile):
+class File(Document, OFS_File):
   """
       A File can contain raw data which can be uploaded and downloaded.
       It is the root class of Image, OOoDocument (ERP5OOo product),
@@ -112,8 +112,14 @@ class File(Document, CMFFile):
         filename = kw.get('filename')
       if filename:
         self._setFilename(filename)
-      if self._isNotEmpty(file_object):
-        self._setFile(file_object, precondition=precondition)
+      if file_object is not None:
+        # XXX: Rather than doing nothing if empty, consider changing:
+        #      - _update_image_info to clear metadata
+        #      - interactions to do nothing (or else?)
+        file_object.seek(0, 2)
+        if file_object.tell():
+          file_object.seek(0)
+          self._setFile(file_object, precondition=precondition)
     Base._edit(self, **kw)
 
   security.declareProtected( Permissions.ModifyPortalContent, 'edit' )
@@ -140,11 +146,17 @@ class File(Document, CMFFile):
     return None
 
   def _setFile(self, data, precondition=None):
-    if data is not None and self.hasData() and \
-      str(data.read()) == str(self.getData()):
-      # Same data as previous, no need to change it's content
+    if data is not None and \
+       str(data.read()) == (self.hasData() and str(self.getData())):
+      # Same data as previous, no need to change its content
       return
-    CMFFile._edit(self, precondition=precondition, file=data)
+
+    # from Products.CMFDefault.File
+    if precondition: self.precondition = precondition
+    elif self.precondition: del self.precondition
+    if data is not None and data.tell():
+      data.seek(0)
+      self.manage_upload(data)
 
   security.declareProtected(Permissions.ModifyPortalContent,'setFile')
   def setFile(self, data, precondition=None):
@@ -192,11 +204,16 @@ class File(Document, CMFFile):
       return str(data)
 
   # DAV Support
-  PUT = CMFFile.PUT
+  security.declareProtected(Permissions.ModifyPortalContent, 'PUT')
+  def PUT(self, REQUEST, RESPONSE):
+    """from Products.CMFDefault.File"""
+    OFS_File.PUT(self, REQUEST, RESPONSE)
+    self.reindexObject()
+
   security.declareProtected(Permissions.FTPAccess, 'manage_FTPstat',
                                                    'manage_FTPlist')
-  manage_FTPlist = CMFFile.manage_FTPlist
-  manage_FTPstat = CMFFile.manage_FTPstat
+  manage_FTPlist = OFS_File.manage_FTPlist
+  manage_FTPstat = OFS_File.manage_FTPstat
 
   security.declareProtected(Permissions.AccessContentsInformation, 'getMimeTypeAndContent')
   def getMimeTypeAndContent(self):
diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py
index 45d7697a477ec8b8fdba64d9cab8aeb0566c75bb..0648ed29979f32af15ae907f61fb471334f9e8b4 100644
--- a/product/ERP5/ERP5Site.py
+++ b/product/ERP5/ERP5Site.py
@@ -15,6 +15,7 @@
   Portal class
 """
 
+from DateTime import DateTime
 from six.moves import map
 import threading
 from weakref import ref as weakref
@@ -26,7 +27,7 @@ from Products.SiteErrorLog.SiteErrorLog import manage_addErrorLog
 from ZPublisher import BeforeTraverse
 from ZPublisher.BaseRequest import RequestContainer
 from AccessControl import ClassSecurityInfo
-from Products.CMFDefault.Portal import CMFSite
+from Products.CMFCore.PortalObject import PortalObjectBase
 from Products.ERP5Type import Permissions
 from Products.ERP5Type.Core.Folder import FolderMixIn
 from Acquisition import aq_base
@@ -230,7 +231,7 @@ getSite, setSite = _site()
 
 _missing_tools_registered = None
 
-class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
+class ERP5Site(FolderMixIn, PortalObjectBase, CacheCookieMixin):
   """
   The *only* function this class should have is to help in the setup
   of a new ERP5.  It should not assist in the functionality at all.
@@ -271,6 +272,15 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
   security = ClassSecurityInfo()
   security.declareObjectProtected(Permissions.AccessContentsInformation)
 
+  def __init__(self, id):
+    PortalObjectBase.__init__(self, id)
+    self.creation_date = DateTime()
+
+  security.declarePrivate('reindexObject')
+  def reindexObject(self, idxs=[]):
+    """from Products.CMFDefault.Portal"""
+    pass
+
   security.declarePublic('isSubtreeIndexable')
   def isSubtreeIndexable(self):
     """
@@ -409,7 +419,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
     return self.index_html()
 
   def __of__(self, parent):
-    self = CMFSite.__of__(self, parent)
+    self = PortalObjectBase.__of__(self, parent)
     # Use a transactional variable for performance reason,
     # since ERP5Site.__of__ is called quite often.
     tv = getTransactionalVariable()
@@ -479,7 +489,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
                                        path_item_list=path_item_list,
                                        new_id=new_id)
     # Rename the object
-    return CMFSite.manage_renameObject(self, id=id, new_id=new_id,
+    return PortalObjectBase.manage_renameObject(self, id=id, new_id=new_id,
                                        REQUEST=REQUEST)
 
 
@@ -597,7 +607,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
 
   # _getProperty is missing, but since there are no protected properties
   # on an ERP5 Site, we can just use getProperty instead.
-  _getProperty = CMFSite.getProperty
+  _getProperty = PortalObjectBase.getProperty
 
   security.declareProtected(Permissions.AccessContentsInformation, 'getUid')
   def getUid(self):
@@ -711,7 +721,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
                              email_from_address, email_from_name,
                              validate_email
                              ):
-    CMFSite.setupDefaultProperties(self, p, title, description,
+    PortalObjectBase.setupDefaultProperties(self, p, title, description,
                            email_from_address, email_from_name,
                            validate_email)
 
@@ -1862,7 +1872,7 @@ factory_type_information = () # No original CMF portal_types installed by defaul
 
 class PortalGenerator:
 
-    klass = CMFSite
+    klass = PortalObjectBase
 
     def setupTools(self, p):
         """Set up initial tools"""
diff --git a/product/ERP5OOo/tests/testDms.py b/product/ERP5OOo/tests/testDms.py
index afde50399761f418ad99de234832e4a86f822553..4398cce99eaccfa99b8195654caa478b8481ecdb 100644
--- a/product/ERP5OOo/tests/testDms.py
+++ b/product/ERP5OOo/tests/testDms.py
@@ -680,10 +680,9 @@ class TestDocument(TestDocumentMixin):
     for document_type in portal.getPortalDocumentTypeList():
       module = portal.getDefaultModule(document_type)
       obj = module.newContent(portal_type=document_type)
-      self.assertNotEquals(obj.getCreationDate(),
-                           module.getCreationDate())
-      self.assertNotEquals(obj.getCreationDate(),
-                           portal.CreationDate())
+      self.assertIsInstance(portal.creation_date, DateTime)
+      self.assertLess(portal.creation_date, obj.getCreationDate())
+      self.assertIsNone(module.getCreationDate())
 
   def test_06_ProcessingStateOfAClonedDocument(self):
     """
@@ -2884,7 +2883,7 @@ class TestDocumentWithSecurity(TestDocumentMixin):
                                                reference='Foo_001',
                                                title='Foo_OO1')
     f = makeFileUpload('Foo_001.odt')
-    text_document.edit(file=f.read())
+    text_document.edit(file=f)
     f.close()
     self.tic()
 
diff --git a/product/ERP5Type/Base.py b/product/ERP5Type/Base.py
index 109a5c2aaefb0d72d1ade274aa63a77c60b00404..efbcdbf830c6b5245c7635a74699c345bbb3ffa9 100644
--- a/product/ERP5Type/Base.py
+++ b/product/ERP5Type/Base.py
@@ -83,7 +83,6 @@ from CopySupport import CopyContainer, CopyError,\
 from Errors import DeferredCatalogError, UnsupportedWorkflowMethod
 from Products.CMFActivity.ActiveObject import ActiveObject
 from Products.ERP5Type.Accessor.Accessor import Accessor as Method
-from Products.ERP5Type.Accessor.TypeDefinition import asDate
 from Products.ERP5Type.Message import Message
 from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage
 from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod, super_user
@@ -3226,9 +3225,8 @@ class Base( CopyContainer,
             if history)
         except ValueError:
           pass
-    if getattr(aq_base(self), 'CreationDate', None) is not None:
-      return asDate(self.CreationDate())
-    return None # JPS-XXX - try to find a way to return a creation date instead of None
+    if getattr(aq_base(self), 'creation_date', None):
+      return self.creation_date.toZone(DateTime().timezone())
 
   security.declareProtected(Permissions.AccessContentsInformation, 'getModificationDate')
   def getModificationDate(self):
@@ -3257,7 +3255,13 @@ class Base( CopyContainer,
         # Return a copy of history time, to prevent modification
         return DateTime(max_date)
     if self._p_serial:
-      return DateTime(TimeStamp(self._p_serial).timeTime())
+      return DateTime(self._p_mtime)
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'modified')
+  def modified(self):
+    warnings.warn('modified is a deprecated alias to getModificationDate.',
+                  DeprecationWarning)
+    return self.getModificationDate()
 
   # Layout management
   security.declareProtected(Permissions.AccessContentsInformation, 'getApplicableLayout')
diff --git a/product/ERP5Type/WebDAVSupport.py b/product/ERP5Type/WebDAVSupport.py
index 5d5be52a4718001aea75bdcc7b8870990adf511e..3b0133f592e2f1326481502bfb1770634a0dc64d 100644
--- a/product/ERP5Type/WebDAVSupport.py
+++ b/product/ERP5Type/WebDAVSupport.py
@@ -15,6 +15,7 @@
 
 import collections
 import email
+from io import BytesIO
 import re
 import transaction
 from lxml import html
@@ -80,7 +81,7 @@ class TextContent:
       headers = self.parseHeadersFromText(body)
       content_type = REQUEST.get_header('Content-Type', '')
       headers.setdefault('content_type', content_type)
-      headers['file'] = body
+      headers['file'] = BytesIO(body)
       self._edit(**headers)
     except ResourceLockedError, msg:
       transaction.abort()
diff --git a/product/ERP5Type/tests/testERP5Type.py b/product/ERP5Type/tests/testERP5Type.py
index 5a25527190aca45ceb228ed61b1e2ea95198ac74..3aa3e0d380638db8b068c86e19e528f306f8b32d 100644
--- a/product/ERP5Type/tests/testERP5Type.py
+++ b/product/ERP5Type/tests/testERP5Type.py
@@ -38,6 +38,7 @@ import transaction
 from random import randint
 from unittest import expectedFailure
 from Acquisition import aq_base
+from DateTime import DateTime
 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
 from Products.ERP5Type.tests.utils import DummyLocalizer
 from zLOG import INFO
@@ -2590,8 +2591,9 @@ class TestERP5Type(PropertySheetTestCase, LogInterceptor):
       portal = self.getPortalObject()
       folder = self.getOrganisationModule()
       object = folder.newContent(portal_type='Organisation')
-      self.assertNotEquals(object.getCreationDate(), portal.CreationDate())
-      self.assertNotEquals(object.getCreationDate(), folder.getCreationDate())
+      self.assertIsInstance(portal.creation_date, DateTime)
+      self.assertLess(portal.creation_date, object.getCreationDate())
+      self.assertIsNone(folder.getCreationDate())
 
     def test_copyWithoutModificationRight(self):
       """