Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/documents.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/documents.py	(revision 12160)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/documents.py	(revision 12161)
@@ -21,4 +21,5 @@
 import os
 import grok
+from hashlib import md5
 from zope.component import queryUtility, getUtility
 from zope.component.interfaces import IFactory
@@ -66,4 +67,6 @@
     grok.baseclass()
 
+    filenames = ()
+
     @property
     def customer(self):
@@ -105,8 +108,34 @@
             return
 
+    @property
+    def connected_files(self):
+        store = getUtility(IExtFileStore)
+        files = []
+        try:
+            for filename in self.filenames:
+                attrname = filename.replace('.','_')
+                file = store.getFileByContext(self, attr=filename)
+                files.append((attrname, file))
+        except AttributeError:
+            # In unit tests we don't have a customer to
+            # determine the file path.
+            return
+        return files
+
+    def setMD5(self):
+        """Set md5 checksum attribute for all files connected to this document.
+        """
+        for file in self.connected_files:
+            attrname = '%s_md5' % file[0]
+            checksum = md5(file[1].read()).hexdigest()
+            setattr(self, attrname, checksum)
+        return
+
 
 class CustomerSampleDocument(CustomerDocumentBase):
     """This is a sample customer document.
     """
+
+    filenames = ('sample',)
 
 CustomerSampleDocument = attrs_to_fields(CustomerSampleDocument)
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py	(revision 12160)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py	(revision 12161)
@@ -160,5 +160,7 @@
                   'translated_state',
                   'formatted_transition_date',
-                  'translated_class_name']))) 
+                  'translated_class_name',
+                  'connected_files',   # Could be used to export file URLs
+                  ])))
 
     #: The title under which this exporter will be displayed
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12160)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12161)
@@ -43,5 +43,9 @@
 from waeup.ikoba.customers.customer import Customer
 from waeup.ikoba.interfaces import (
-    IUserAccount, IJobManager, APPROVED, SUBMITTED)
+    IUserAccount, IJobManager, APPROVED, SUBMITTED,
+    IFileStoreNameChooser, IExtFileStore, IFileStoreHandler)
+from waeup.ikoba.imagestorage import (
+    FileStoreNameChooser, ExtFileStore, DefaultFileStoreHandler,
+    DefaultStorage)
 from waeup.ikoba.authentication import LocalRoleSetEvent
 from waeup.ikoba.tests.test_async import FunctionalAsyncTestCase
@@ -1212,6 +1216,5 @@
 
     def test_contract_approval(self):
-        # This is not a UI test. It just tests the approval
-        # of contracts.
+        # This is not a UI test. It just a functional test.
         self.assertRaises(ConstraintNotSatisfied,
             self.contract.document_object, self.document)
@@ -1227,5 +1230,4 @@
         self.assertEqual(IWorkflowState(self.contract).getState(), 'approved')
 
-
     def test_contract_approval_in_UI(self):
         # Now let's see what the UI says why trying to approve a contract
@@ -1246,2 +1248,17 @@
         self.browser.getControl("Save").click()
         self.assertEqual(IWorkflowState(self.contract).getState(), 'approved')
+
+    def test_get_setmd5_file(self):
+        # A proper file name chooser is registered for customer documents.
+        # This is not a UI test. It just a functional test.
+        file_id = IFileStoreNameChooser(self.document).chooseName(attr='sample')
+        fs = ExtFileStore(root=self.dc_root)
+        fs.createFile(file_id, StringIO('my sample 1'))
+        result = fs.getFileByContext(self.document, attr='sample')
+        self.assertEqual(file_id, '__file-customerdocument__01000/K1000000/sample_d101_K1000000')
+        self.assertEqual(result.read(), 'my sample 1')
+        self.assertEqual(self.document.connected_files[0][1].read(), 'my sample 1')
+        self.document.setMD5()
+        self.assertEqual(self.document.sample_md5, 'a406995ee8eb6772bacf51aa4b0caa24')
+        return
+
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/document.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/document.py	(revision 12160)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/document.py	(revision 12161)
@@ -87,11 +87,12 @@
         return
 
-    def setMD5(self, files):
-        """Set md5 checksum of selected files connected to this document.
+    def setMD5(self):
+        """Determine md5 checksum of all files and store checksums as
+        document attributes.
         """
         return
         
+Document = attrs_to_fields(Document)
 
-Document = attrs_to_fields(Document)
 
 class DocumentFactory(grok.GlobalUtility):
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py	(revision 12160)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py	(revision 12161)
@@ -52,5 +52,5 @@
     formatted_transition_date = Attribute('Last transition formatted date string')
     user_id = Attribute('Id of a user')
-    connected_files = Attribute('Get files connected to a document')
+    connected_files = Attribute('Names of files connected to a document')
 
     title = schema.TextLine(
@@ -65,6 +65,7 @@
         )
 
-    def setMD5(files):
-        """Set md5 checksum of selected files connected to this document.
+    def setMD5():
+        """Determine md5 checksum of selected files and store checksums as
+        document attributes.
         """
 
