def _process(self): files = request.files.getlist('image') num = 0 for f in files: filename = secure_client_filename(f.filename) data = BytesIO() shutil.copyfileobj(f, data) data.seek(0) try: image_type = Image.open(data).format.lower() except OSError: # Invalid image data continue data.seek(0) # XXX: mpo is basically JPEG and JPEGs from some cameras are (wrongfully) detected as mpo if image_type == 'mpo': image_type = 'jpeg' elif image_type not in {'jpeg', 'gif', 'png'}: flash(_("The image '{name}' has an invalid type ({type}); only JPG, GIF and PNG are allowed.") .format(name=f.filename, type=image_type), 'error') continue content_type = 'image/' + image_type image = ImageFile(event=self.event, filename=filename, content_type=content_type) image.save(data) num += 1 db.session.flush() logger.info('Image %s uploaded by %s', image, session.user) signals.event_management.image_created.send(image, user=session.user) flash(ngettext('The image has been uploaded', '{count} images have been uploaded', num) .format(count=len(files)), 'success') return jsonify_data(image_list=_render_image_list(self.event))
def add_abstract_files(abstract, files, log_action=True): if not files: return for f in files: filename = secure_client_filename(f.filename) content_type = mimetypes.guess_type( f.filename)[0] or f.mimetype or 'application/octet-stream' abstract_file = AbstractFile(filename=filename, content_type=content_type, abstract=abstract) abstract_file.save(f.stream) db.session.flush() if log_action: logger.info('%d abstract file(s) added to %s by %s', len(files), abstract, session.user) num = len(files) if num == 1: msg = f'Added file to abstract {abstract.verbose_title}' else: msg = f'Added {num} files to abstract {abstract.verbose_title}' abstract.log( EventLogRealm.reviewing, LogKind.positive, 'Abstracts', msg, session.user, data={'Files': ', '.join(f.filename for f in abstract.files)})
def _process(self): defaults = FormDefaults(self.attachment, protected=self.attachment.is_self_protected, skip_attrs={'file'}) if self.attachment.type == AttachmentType.file: form = EditAttachmentFileForm(linked_object=self.object, obj=defaults, file=self.attachment) else: form = EditAttachmentLinkForm(linked_object=self.object, obj=defaults) if form.validate_on_submit(): folder = form.folder.data or AttachmentFolder.get_or_create_default(linked_object=self.object) logger.info('Attachment %s edited by %s', self.attachment, session.user) form.populate_obj(self.attachment, skip={'acl', 'file'}) self.attachment.folder = folder if self.attachment.is_self_protected: # can't use `=` because of https://bitbucket.org/zzzeek/sqlalchemy/issues/3583 self.attachment.acl |= form.acl.data self.attachment.acl &= form.acl.data # files need special handling; links are already updated in `populate_obj` if self.attachment.type == AttachmentType.file: file = form.file.data['added'] if file: self.attachment.file = AttachmentFile(user=session.user, content_type=file.mimetype, filename=secure_client_filename(file.filename)) self.attachment.file.save(file.stream) signals.attachments.attachment_updated.send(self.attachment, user=session.user) flash(_("The attachment \"{name}\" has been updated").format(name=self.attachment.title), 'success') return jsonify_data(attachment_list=_render_attachment_list(self.object)) template = ('attachments/upload.html' if self.attachment.type == AttachmentType.file else 'attachments/add_link.html') return jsonify_template(template, form=form, existing_attachment=self.attachment, action=url_for('.modify_attachment', self.attachment), protection_message=_render_protection_message(self.object), folders_protection_info=_get_folders_protection_info(self.object))
def _store_paper_template_file(template, file): content_type = mimetypes.guess_type(file.filename)[0] or file.mimetype or 'application/octet-stream' # reset fields in case an existing file is replaced so we can save() again template.storage_backend = None template.storage_file_id = None template.size = None template.content_type = content_type template.filename = secure_client_filename(file.filename) template.save(file.stream)
def create_paper_revision(paper, submitter, files): revision = PaperRevision(paper=paper, submitter=submitter) for f in files: filename = secure_client_filename(f.filename) content_type = mimetypes.guess_type(f.filename)[0] or f.mimetype or 'application/octet-stream' pf = PaperFile(filename=filename, content_type=content_type, paper_revision=revision, _contribution=paper.contribution) pf.save(f.stream) db.session.flush() db.session.expire(revision._contribution, ['_paper_last_revision']) notify_paper_revision_submission(revision) logger.info('Paper revision %r submitted by %r', revision, session.user) paper.event.log(EventLogRealm.reviewing, EventLogKind.positive, 'Papers', "Paper revision {} submitted for contribution {} ({})" .format(revision.id, paper.contribution.title, paper.contribution.friendly_id), session.user) return revision
def _process(self): form = AddAttachmentFilesForm(linked_object=self.object) if form.validate_on_submit(): files = form.files.data folder = form.folder.data or AttachmentFolder.get_or_create_default( linked_object=self.object) for f in files: filename = secure_client_filename(f.filename) attachment = Attachment( folder=folder, user=session.user, title=f.filename, type=AttachmentType.file, protection_mode=form.protection_mode.data) if attachment.is_self_protected: attachment.acl = form.acl.data content_type = mimetypes.guess_type( f.filename)[0] or f.mimetype or 'application/octet-stream' attachment.file = AttachmentFile(user=session.user, filename=filename, content_type=content_type) attachment.file.save(f.stream) db.session.add(attachment) db.session.flush() logger.info('Attachment %s uploaded by %s', attachment, session.user) signals.attachments.attachment_created.send(attachment, user=session.user) flash( ngettext("The attachment has been uploaded", "{count} attachments have been uploaded", len(files)).format(count=len(files)), 'success') return jsonify_data( attachment_list=_render_attachment_list(self.object)) return jsonify_template( 'attachments/upload.html', form=form, action=url_for('.upload', self.object), protection_message=_render_protection_message(self.object), folders_protection_info=_get_folders_protection_info(self.object), existing_attachment=None)
def process_form_data(self, registration, value, old_data=None, billable_items_locked=False): data = {'field_data': self.form_item.current_data} if not value: return data file_ = value['uploaded_file'] if file_: # we have a file -> always save it data['file'] = { 'data': file_.stream, 'name': secure_client_filename(file_.filename), 'content_type': mimetypes.guess_type(file_.filename)[0] or file_.mimetype or 'application/octet-stream' } elif not value['keep_existing']: data['file'] = None return data
def test_secure_client_filename(filename, expected): assert secure_client_filename(filename) == expected