Changeset 8467


Ignore:
Timestamp:
18 May 2012, 00:13:37 (12 years ago)
Author:
uli
Message:

Use fileformat recognition when uploading student files.

Location:
main/waeup.kofa/trunk/src/waeup/kofa/students
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py

    r8436 r8467  
    2626import grok
    2727from zope.event import notify
    28 from zope.component import createObject, queryUtility, getUtility
     28from zope.component import createObject, queryUtility
    2929from zope.component.hooks import setSite, clearSite
    3030from zope.catalog.interfaces import ICatalog
     
    3535from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase
    3636from waeup.kofa.app import University
    37 from waeup.kofa.configuration import SessionConfiguration
    3837from waeup.kofa.students.student import Student
    3938from waeup.kofa.students.studylevel import StudentStudyLevel
    4039from waeup.kofa.university.faculty import Faculty
    4140from waeup.kofa.university.department import Department
    42 from waeup.kofa.interfaces import IUserAccount, IKofaUtils
     41from waeup.kofa.interfaces import IUserAccount
    4342from waeup.kofa.authentication import LocalRoleSetEvent
    4443from waeup.kofa.hostels.hostel import Hostel, Bed, NOT_OCCUPIED
    4544
    4645PH_LEN = 2059  # Length of placeholder file
     46
     47SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
     48SAMPLE_IMAGE_BMP = os.path.join(os.path.dirname(__file__), 'test_image.bmp')
    4749
    4850def lookup_submit_value(name, value, browser):
     
    522524        # as birth certificate
    523525        self.browser.open(self.manage_clearance_path)
    524         pseudo_image = StringIO('I pretend to be a graphics file')
     526        image = open(SAMPLE_IMAGE, 'rb')
    525527        ctrl = self.browser.getControl(name='birthcertificateupload')
    526528        file_ctrl = ctrl.mech_control
    527         file_ctrl.add_file(pseudo_image, filename='my_birth_certificate.jpg')
     529        file_ctrl.add_file(image, filename='my_birth_certificate.jpg')
    528530        # The Save action does not upload files
    529531        self.browser.getControl("Save").click() # submit form
     
    532534            in self.browser.contents)
    533535        # ... but the correct upload submit button does
    534         pseudo_image = StringIO('I pretend to be a graphics file')
     536        image = open(SAMPLE_IMAGE)
    535537        ctrl = self.browser.getControl(name='birthcertificateupload')
    536538        file_ctrl = ctrl.mech_control
    537         file_ctrl.add_file(pseudo_image, filename='my_birth_certificate.jpg')
     539        file_ctrl.add_file(image, filename='my_birth_certificate.jpg')
    538540        self.browser.getControl(
    539541            name='upload_birthcertificateupload').click()
     
    546548        self.assertEqual(
    547549            self.browser.headers['content-type'], 'image/jpeg')
    548         self.assertEqual(len(self.browser.contents), 31)
     550        self.assertEqual(len(self.browser.contents), 2787)
    549551        # Reuploading a file which is bigger than 150k will raise an error
    550552        self.browser.open(self.manage_clearance_path)
    551         photo_content = 'A' * 1024 * 151  # A string of 21 KB size
    552         pseudo_image = StringIO(photo_content)
     553        # An image > 150K
     554        big_image = StringIO(open(SAMPLE_IMAGE, 'rb').read() * 75)
    553555        ctrl = self.browser.getControl(name='birthcertificateupload')
    554556        file_ctrl = ctrl.mech_control
    555         file_ctrl.add_file(pseudo_image, filename='my_birth_certificate.jpg')
     557        file_ctrl.add_file(big_image, filename='my_birth_certificate.jpg')
    556558        self.browser.getControl(
    557559            name='upload_birthcertificateupload').click()
    558560        self.assertTrue(
    559561            'Uploaded file is too big' in self.browser.contents)
    560         # File names must meet several conditions
    561         pseudo_image = StringIO('I pretend to be a graphics file')
     562        # we do not rely on filename extensions given by uploaders
     563        image = open(SAMPLE_IMAGE, 'rb') # a jpg-file
    562564        ctrl = self.browser.getControl(name='birthcertificateupload')
    563565        file_ctrl = ctrl.mech_control
    564         file_ctrl.add_file(pseudo_image, filename='my.photo.jpg')
     566        # tell uploaded file is bmp
     567        file_ctrl.add_file(image, filename='my_birth_certificate.bmp')
    565568        self.browser.getControl(
    566569            name='upload_birthcertificateupload').click()
    567         self.assertTrue('File name contains more than one dot'
    568             in self.browser.contents)
     570        self.assertTrue(
     571            # jpg file was recognized
     572            'File birth_certificate.jpg uploaded.' in self.browser.contents)
     573        # File names must meet several conditions
     574        bmp_image = open(SAMPLE_IMAGE_BMP, 'rb')
    569575        ctrl = self.browser.getControl(name='birthcertificateupload')
    570576        file_ctrl = ctrl.mech_control
    571         file_ctrl.add_file(pseudo_image, filename='my_birth_certificate')
    572         self.browser.getControl(
    573             name='upload_birthcertificateupload').click()
    574         self.assertTrue('File name has no extension' in self.browser.contents)
    575         ctrl = self.browser.getControl(name='birthcertificateupload')
    576         file_ctrl = ctrl.mech_control
    577         file_ctrl.add_file(pseudo_image, filename='my_birth_certificate.bmp')
     577        file_ctrl.add_file(bmp_image, filename='my_birth_certificate.bmp')
    578578        self.browser.getControl(
    579579            name='upload_birthcertificateupload').click()
     
    586586        # Managers can add and delete second file
    587587        self.browser.open(self.manage_clearance_path)
    588         pseudo_image = StringIO('I pretend to be a graphics file')
     588        image = open(SAMPLE_IMAGE, 'rb')
    589589        ctrl = self.browser.getControl(name='birthcertificateupload')
    590590        file_ctrl = ctrl.mech_control
    591         file_ctrl.add_file(pseudo_image, filename='my_acceptance_letter.jpg')
     591        file_ctrl.add_file(image, filename='my_acceptance_letter.jpg')
    592592        self.browser.getControl(
    593593            name='upload_acceptanceletterupload').click()
     
    597597        ctrl = self.browser.getControl(name='acceptanceletterupload')
    598598        file_ctrl = ctrl.mech_control
    599         file_ctrl.add_file(pseudo_image, filename='my_acceptance_letter.jpg')
     599        image.seek(0)
     600        file_ctrl.add_file(image, filename='my_acceptance_letter.jpg')
    600601        self.browser.getControl(
    601602            name='upload_acceptanceletterupload').click()
     
    610611        # Managers can upload a file via the StudentBaseManageFormPage
    611612        self.browser.open(self.manage_student_path)
    612         pseudo_image = StringIO('I pretend to be a graphics file')
     613        image = open(SAMPLE_IMAGE_BMP, 'rb')
    613614        ctrl = self.browser.getControl(name='passportuploadmanage')
    614615        file_ctrl = ctrl.mech_control
    615         file_ctrl.add_file(pseudo_image, filename='my_photo.bmp')
     616        file_ctrl.add_file(image, filename='my_photo.bmp')
    616617        self.browser.getControl(
    617618            name='upload_passportuploadmanage').click()
     
    620621        ctrl = self.browser.getControl(name='passportuploadmanage')
    621622        file_ctrl = ctrl.mech_control
    622         file_ctrl.add_file(pseudo_image, filename='my_photo.jpg')
     623        image = open(SAMPLE_IMAGE, 'rb')
     624        file_ctrl.add_file(image, filename='my_photo.jpg')
    623625        self.browser.getControl(
    624626            name='upload_passportuploadmanage').click()
     
    631633        self.browser.open(self.student_path + '/clearance.pdf')
    632634        self.assertEqual(self.browser.headers['Status'], '200 Ok')
    633         self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
     635        self.assertEqual(self.browser.headers['Content-Type'],
     636                         'application/pdf')
    634637
    635638    def test_manage_course_lists(self):
     
    14261429        IWorkflowInfo(self.student).fireTransition('admit')
    14271430        self.browser.open(self.student_path + '/change_portrait')
    1428         pseudo_image = StringIO('I pretend to be a graphics file')
     1431        image = open(SAMPLE_IMAGE, 'rb')
    14291432        ctrl = self.browser.getControl(name='passportuploadedit')
    14301433        file_ctrl = ctrl.mech_control
    1431         file_ctrl.add_file(pseudo_image, filename='my_photo.jpg')
     1434        file_ctrl.add_file(image, filename='my_photo.jpg')
    14321435        self.browser.getControl(
    14331436            name='upload_passportuploadedit').click()
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_student.py

    r8452 r8467  
    130130
    131131    def create_passport_img(self, student):
    132         # create some faked passport file for `student`
     132        # create some passport file for `student`
    133133        storage = getUtility(IExtFileStore)
     134        image_path = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
     135        self.image_contents = open(image_path, 'rb').read()
    134136        file_id = IFileStoreNameChooser(student).chooseName(
    135137            attr='passport.jpg')
    136         storage.createFile(file_id, StringIO('I am a fake image.'))
     138        storage.createFile(file_id, StringIO(self.image_contents))
    137139
    138140    def test_backup_single_student_data(self):
     
    144146        del_dir = self.app['datacenter'].deleted_path
    145147        del_img_path = os.path.join(
    146             del_dir, 'media', 'students', '00111', 'A111111',
     148            del_dir, 'media', 'students', '00110', 'A111111',
    147149            'passport_A111111.jpg')
    148150
     
    151153        self.assertEqual(
    152154            open(del_img_path, 'rb').read(),
    153             'I am a fake image.')
     155            self.image_contents)
    154156
    155157        # The student data were put into CSV files
  • main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py

    r8435 r8467  
    2222from zope.i18n import translate
    2323from waeup.kofa.interfaces import (
    24     IKofaObject, IExtFileStore, IFileStoreNameChooser, IKofaUtils)
     24    IKofaObject, IExtFileStore, IFileStoreNameChooser)
    2525from waeup.kofa.interfaces import MessageFactory as _
    2626from waeup.kofa.utils.helpers import string_from_bytes, file_size
     
    2929    PrimaryNavTab, ManageActionButton, AddActionButton)
    3030from waeup.kofa.browser.layout import (
    31     default_primary_nav_template,
    32     default_filedisplay_template, default_fileupload_template)
    33 from waeup.kofa.students.workflow import (ADMITTED, PAID,
    34     CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED)
     31    default_primary_nav_template, default_filedisplay_template,
     32    default_fileupload_template)
     33from waeup.kofa.students.workflow import (
     34    ADMITTED, PAID, REQUESTED, RETURNING, CLEARED, REGISTERED,
     35    VALIDATED)
    3536from waeup.kofa.students.browser import (
    36     StudentClearanceManageFormPage,
    37     write_log_message, StudentBaseManageFormPage,
    38     StudentFilesUploadPage, ExportPDFClearanceSlipPage, StudentsContainerPage,
     37    StudentClearanceManageFormPage, write_log_message,
     38    StudentBaseManageFormPage, StudentFilesUploadPage,
     39    ExportPDFClearanceSlipPage, StudentsContainerPage,
    3940    StudentsContainerManagePage, StudentBaseDisplayFormPage,
    4041    StudentClearanceDisplayFormPage, StudentPersonalDisplayFormPage,
     
    4445    StudentClearanceEditFormPage, StudentPersonalEditFormPage)
    4546from waeup.kofa.students.interfaces import (
    46     IStudentsContainer, IStudent,
    47     IStudentStudyCourse, IStudentAccommodation, IStudentStudyLevel,
    48     ICourseTicket, IStudentOnlinePayment, IBedTicket,
     47    IStudentsContainer, IStudent, IStudentStudyCourse, IStudentAccommodation,
     48    IStudentStudyLevel, ICourseTicket, IStudentOnlinePayment, IBedTicket,
    4949    )
    50 
    51 from waeup.kofa.interfaces import MessageFactory as _
     50from waeup.kofa.utils.helpers import get_fileformat
    5251
    5352grok.context(IKofaObject) # Make IKofaObject the default context
     
    512511    grok.order(1)
    513512    grok.require('waeup.Authenticated')
    514     pnav = 0 
     513    pnav = 0
    515514    tab_title = u'Some Text'
    516515
     
    553552        targets += [
    554553            {'url':student_url, 'title':'Base Data'},
    555             {'url':student_url + '/view_clearance', 'title':_('Clearance Data')},
     554            {'url':student_url + '/view_clearance',
     555             'title':_('Clearance Data')},
    556556            {'url':student_url + '/view_personal', 'title':_('Personal Data')},
    557557            {'url':student_url + '/studycourse', 'title':_('Study Course')},
    558558            {'url':student_url + '/payments', 'title':_('Payments')},
    559             {'url':student_url + '/accommodation', 'title':_('Accommodation Data')},
     559            {'url':student_url + '/accommodation',
     560             'title':_('Accommodation Data')},
    560561            {'url':student_url + '/history', 'title':_('History')},
    561562            ]
     
    581582    """
    582583    # Check some file requirements first
    583     if upload.filename.count('.') == 0:
    584         view.flash(_('File name has no extension.'))
    585         return False
    586     if upload.filename.count('.') > 1:
    587         view.flash(_('File name contains more than one dot.'))
    588         return False
    589     basename, expected_ext = os.path.splitext(download_name)
    590     dummy, ext = os.path.splitext(upload.filename)
    591     ext.lower()
    592     if expected_ext:
    593         if ext != expected_ext:
    594             view.flash(_('${a} file extension expected.',
    595                 mapping = {'a':expected_ext.replace('.','')}))
    596             return False
    597     else:
    598         if not ext.replace('.','') in ALLOWED_FILE_EXTENSIONS:
    599             view.flash(
    600                 _('Only the following extension are allowed: ${a}',
    601                 mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
    602             return False
    603         download_name += ext
    604584    size = file_size(upload)
    605585    if size > max_size:
     
    607587        return False
    608588    upload.seek(0) # file pointer moved when determining size
     589    file_format = get_fileformat(None, upload.read(512))
     590    upload.seek(0) # same here
     591    if file_format is None:
     592        view.flash(_('Could not determine file type.'))
     593        return False
     594    basename, expected_ext = os.path.splitext(download_name)
     595    if expected_ext:
     596        if '.' + file_format != expected_ext:
     597            view.flash(_('${a} file extension expected.',
     598                mapping = {'a':expected_ext[1:]}))
     599            return False
     600    else:
     601        if not file_format in ALLOWED_FILE_EXTENSIONS:
     602            view.flash(
     603                _('Only the following extensions are allowed: ${a}',
     604                mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
     605            return False
     606        download_name += '.' + file_format
    609607    store = getUtility(IExtFileStore)
    610608    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
    611609    store.createFile(file_id, upload)
    612     write_log_message(view, 'uploaded: %s (%s)' % (download_name,upload.filename))
     610    write_log_message(view, 'uploaded: %s (%s)' % (
     611        download_name,upload.filename))
    613612    view.flash(_('File ${a} uploaded.', mapping = {'a':download_name}))
    614613    return True
Note: See TracChangeset for help on using the changeset viewer.