Index: /main/waeup.futminna/trunk/src/waeup/futminna/applicants/applicant.py
===================================================================
--- /main/waeup.futminna/trunk/src/waeup/futminna/applicants/applicant.py	(revision 10219)
+++ /main/waeup.futminna/trunk/src/waeup/futminna/applicants/applicant.py	(revision 10220)
@@ -34,4 +34,5 @@
     file_store.deleteFileByContext(applicant, attr='extraform.pdf')
     file_store.deleteFileByContext(applicant, attr='refereeform.pdf')
+    file_store.deleteFileByContext(applicant, attr='credentialform.pdf')
     return
 
Index: /main/waeup.futminna/trunk/src/waeup/futminna/applicants/browser.py
===================================================================
--- /main/waeup.futminna/trunk/src/waeup/futminna/applicants/browser.py	(revision 10219)
+++ /main/waeup.futminna/trunk/src/waeup/futminna/applicants/browser.py	(revision 10220)
@@ -92,5 +92,9 @@
             self.context, attr='refereeform.pdf')
         if pdf:
-            html += '<a href="refereeform.pdf">Referee\'s Form</a>'
+            html += '<a href="refereeform.pdf">Referee\'s Form</a>, '
+        pdf = getUtility(IExtFileStore).getFileByContext(
+            self.context, attr='credentialform.pdf')
+        if pdf:
+            html += '<a href="credentialform.pdf">Credential Form</a>'
         return html
 
@@ -125,4 +129,5 @@
         self.extraform_url = self.url(self.context, 'extraform.pdf')
         self.referreeform_url = self.url(self.context, 'refereeform.pdf')
+        self.credentialform_url = self.url(self.context, 'credentialform.pdf')
         return
 
@@ -201,4 +206,13 @@
             else:
                 self.upload_success = False
+        upload_credentialform = self.request.form.get('form.credentialform', None)
+        if upload_credentialform:
+            # We got a fresh credentialform upload
+            success = handle_file_upload(
+                upload_credentialform, self.context, self, attr='credentialform.pdf')
+            if success:
+                self.context.writeLogMessage(self, 'saved: credentialform')
+            else:
+                self.upload_success = False
         self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
         return
@@ -238,4 +252,6 @@
         if not store.getFileByContext(self.context, attr=u'refereeform.pdf'):
             return _('No referee form pdf file uploaded.')
+        if not store.getFileByContext(self.context, attr=u'credentialform.pdf'):
+            return _('No credential form pdf file uploaded.')
         if not self.request.form.get('confirm_passport', False):
             return _('Passport picture confirmation box not ticked.')
@@ -263,4 +279,11 @@
             if not success:
                 self.upload_success = False
+        upload_credentialform = self.request.form.get('form.credentialform', None)
+        if upload_credentialform:
+            # We got a fresh credentialform upload
+            success = handle_file_upload(
+                upload_credentialform, self.context, self, attr='credentialform.pdf')
+            if not success:
+                self.upload_success = False
         self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
         return
@@ -291,2 +314,15 @@
         self.response.setHeader('Content-Type', 'application/pdf')
         return pdf
+
+class CredentialForm(grok.View):
+    """Renders the pdf credential's form for applicants.
+    """
+    grok.name('credentialform.pdf')
+    grok.context(ICustomApplicant)
+    grok.require('waeup.viewApplication')
+
+    def render(self):
+        pdf = getUtility(IExtFileStore).getFileByContext(
+            self.context, attr='credentialform.pdf')
+        self.response.setHeader('Content-Type', 'application/pdf')
+        return pdf
Index: /main/waeup.futminna/trunk/src/waeup/futminna/applicants/browser_templates/applicanteditpage.pt
===================================================================
--- /main/waeup.futminna/trunk/src/waeup/futminna/applicants/browser_templates/applicanteditpage.pt	(revision 10219)
+++ /main/waeup.futminna/trunk/src/waeup/futminna/applicants/browser_templates/applicanteditpage.pt	(revision 10220)
@@ -79,4 +79,22 @@
           </p>
           <input type="file" name="form.refereeform" />
+          <br />
+          <span i18n:translate="">
+            Max. file size:
+          </span>
+          <span tal:replace="view/max_file_upload_size">10 KB</span>
+      </tr>
+      <tr>
+        <td class="fieldname" i18n:translate="">
+          Credential Form:
+        </td>
+        <td>
+          <p tal:condition="python: view.file_exists('credentialform.pdf')">
+            <a href="credentialform.pdf"
+               i18n:translate="">
+              Download pdf file
+            </a>
+          </p>
+          <input type="file" name="form.credentialform" />
           <br />
           <span i18n:translate="">
Index: /main/waeup.futminna/trunk/src/waeup/futminna/applicants/tests/test_browser.py
===================================================================
--- /main/waeup.futminna/trunk/src/waeup/futminna/applicants/tests/test_browser.py	(revision 10219)
+++ /main/waeup.futminna/trunk/src/waeup/futminna/applicants/tests/test_browser.py	(revision 10220)
@@ -249,4 +249,95 @@
         self.assertTrue(fd is None)
 
+    def test_upload_credentialform_by_student(self):
+        self.login()
+        self.browser.open(self.edit_path)
+        # Create a pseudo file and select it to be uploaded in form
+        pdf_content = 'A' * 1024 * 600  # A string of 600 KB size
+        pseudo_pdf = StringIO(pdf_content)
+        ctrl = self.browser.getControl(name='form.credentialform')
+        file_ctrl = ctrl.mech_control
+        file_ctrl.add_file(pseudo_pdf, filename='myform.pdf')
+        self.browser.getControl("Save").click() # submit form
+        # We get a warning message
+        self.assertTrue(
+            'Uploaded file is too big' in self.browser.contents)
+        # Create a pseudo file with acceptable size
+        pdf_content = 'A' * 1024 * 300  # A string of 300 KB size
+        pseudo_pdf = StringIO(pdf_content)
+        ctrl = self.browser.getControl(name='form.credentialform')
+        file_ctrl = ctrl.mech_control
+        file_ctrl.add_file(pseudo_pdf, filename='myform.pdf')
+        self.browser.getControl("Save").click() # submit form
+        # Even though the form could not be saved ...
+        self.assertTrue('Required input is missing' in self.browser.contents)
+        # ... the file has been successfully uploaded
+        pdf_url = self.edit_path.replace('edit', 'credentialform.pdf')
+        self.browser.open(pdf_url)
+        self.assertEqual(
+            self.browser.headers['content-type'], 'application/pdf')
+        self.assertEqual(len(self.browser.contents), 307200)
+        # There is really a file stored for the applicant
+        storage = getUtility(IExtFileStore)
+        file_id = IFileStoreNameChooser(self.applicant).chooseName(
+            attr='credentialform.pdf')
+        # The stored file can be fetched
+        fd = storage.getFile(file_id)
+        file_len = len(fd.read())
+        self.assertEqual(file_len, 307200)
+        # A file link is displayed on the edit view ...
+        self.browser.open(self.edit_path)
+        self.assertTrue('<a href="credentialform.pdf">' in self.browser.contents)
+        # ... and on the dislay view
+        self.browser.open(self.view_path)
+        self.assertTrue('<a href="credentialform.pdf">Credential Form</a>'
+            in self.browser.contents)
+
+    def test_upload_credentialform_by_manager(self):
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.manage_path)
+        # Create a pseudo file with acceptable size
+        pdf_content = 'A' * 1024 * 300  # A string of 300 KB size
+        pseudo_pdf = StringIO(pdf_content)
+        ctrl = self.browser.getControl(name='form.credentialform')
+        file_ctrl = ctrl.mech_control
+        file_ctrl.add_file(pseudo_pdf, filename='myform.pdf')
+        self.browser.getControl("Save").click() # submit form
+        # Even though the form could not be saved ...
+        self.assertTrue('Required input is missing' in self.browser.contents)
+        # ... the file has been successfully uploaded
+        pdf_url = self.manage_path.replace('manage', 'credentialform.pdf')
+        self.browser.open(pdf_url)
+        self.assertEqual(
+            self.browser.headers['content-type'], 'application/pdf')
+        self.assertEqual(len(self.browser.contents), 307200)
+        # There is rally a file stored for the applicant
+        storage = getUtility(IExtFileStore)
+        file_id = IFileStoreNameChooser(self.applicant).chooseName(
+            attr='credentialform.pdf')
+        # The stored file can be fetched
+        fd = storage.getFile(file_id)
+        file_len = len(fd.read())
+        self.assertEqual(file_len, 307200)
+        # A file link is displayed on the edit view ...
+        self.browser.open(self.manage_path)
+        self.assertTrue('<a href="credentialform.pdf">' in self.browser.contents)
+        # ... and on the dislay view
+        self.browser.open(self.view_path)
+        self.assertTrue('<a href="credentialform.pdf">Credential Form</a>'
+            in self.browser.contents)
+        # Adding file is properly logged
+        logfile = os.path.join(
+            self.app['datacenter'].storage, 'logs', 'applicants.log')
+        logcontent = open(logfile).read()
+        self.assertTrue(
+            'zope.mgr - waeup.futminna.applicants.browser.CustomApplicantManageFormPage'
+            ' - %s - saved: credentialform'
+            % (self.applicant.applicant_id)
+            in logcontent)
+        # When an applicant is removed, also the pdf files are gone.
+        del self.app['applicants']['app2011'][self.applicant.application_number]
+        fd = storage.getFile(file_id)
+        self.assertTrue(fd is None)
+
     def test_certificate_source(self):
         # We add a second 'alternative' certificate
