def _get_base_path(self, attachment):
        # TODO: adapt to new models (needs extra properties to use event TZ)
        obj = linked_object = attachment.folder.object
        paths = []
        while obj != self.event:
            start_date = _get_start_dt(obj)
            if start_date is not None:
                if isinstance(obj, SubContribution):
                    paths.append(
                        secure_filename(
                            '{}_{}'.format(obj.position, obj.title), ''))
                else:
                    time = format_time(start_date,
                                       format='HHmm',
                                       timezone=self.event.timezone)
                    paths.append(
                        secure_filename(
                            '{}_{}'.format(to_unicode(time), obj.title), ''))
            else:
                if isinstance(obj, SubContribution):
                    paths.append(
                        secure_filename(
                            '{}){}'.format(obj.position, obj.title),
                            unicode(obj.id)))
                else:
                    paths.append(secure_filename(obj.title, unicode(obj.id)))
            obj = _get_obj_parent(obj)

        linked_obj_start_date = _get_start_dt(linked_object)
        if attachment.folder.object != self.event and linked_obj_start_date is not None:
            paths.append(
                secure_filename(linked_obj_start_date.strftime('%Y%m%d_%A'),
                                ''))

        return reversed(paths)
 def _prepare_folder_structure(self, item):
     paper_title = secure_filename(
         '{}_{}'.format(item.paper.contribution.friendly_id,
                        item.paper.contribution.title), 'paper')
     file_name = secure_filename('{}_{}'.format(item.id, item.filename),
                                 'paper')
     return os.path.join(
         *self._adjust_path_length([paper_title, file_name]))
 def _prepare_folder_structure(self, item):
     abstract_title = secure_filename(
         '{}_{}'.format(item.abstract.title, unicode(item.abstract.id)),
         'abstract')
     file_name = secure_filename(
         '{}_{}'.format(unicode(item.id), item.filename), item.filename)
     return os.path.join(
         *self._adjust_path_length([abstract_title, file_name]))
 def _prepare_folder_structure(self, attachment):
     registration = attachment.registration
     regform_title = secure_filename(attachment.registration.registration_form.title, 'registration_form')
     registrant_name = secure_filename("{}_{}".format(registration.get_full_name(),
                                       unicode(registration.friendly_id)), registration.friendly_id)
     file_name = secure_filename("{}_{}_{}".format(attachment.field_data.field.title, attachment.field_data.field_id,
                                                   attachment.filename), attachment.filename)
     return os.path.join(*self._adjust_path_length([regform_title, registrant_name, file_name]))
def add_abstract_files(abstract, files, log_action=True):
    if not files:
        return
    for f in files:
        filename = secure_filename(f.filename, 'attachment')
        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 = 'Added file to abstract {}'.format(abstract.verbose_title)
        else:
            msg = 'Added {} files to abstract {}'.format(
                num, abstract.verbose_title)
        abstract.event.log(
            EventLogRealm.management,
            EventLogKind.positive,
            'Abstracts',
            msg,
            session.user,
            data={'Files': ', '.join(f.filename for f in abstract.files)})
Example #6
0
    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_filename(file.filename, 'attachment'))
                    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))
Example #7
0
 def _process(self):
     f = request.files['logo']
     try:
         img = Image.open(f)
     except IOError:
         flash(_('You cannot upload this file as a logo.'), 'error')
         return jsonify_data(content=None)
     if img.format.lower() not in {'jpeg', 'png', 'gif'}:
         flash(_('The file has an invalid format ({format})').format(format=img.format), 'error')
         return jsonify_data(content=None)
     if img.mode == 'CMYK':
         flash(_('The logo you uploaded is using the CMYK colorspace and has been converted to RGB. Please check if '
                 'the colors are correct and convert it manually if necessary.'), 'warning')
         img = img.convert('RGB')
     image_bytes = BytesIO()
     img.save(image_bytes, 'PNG')
     image_bytes.seek(0)
     content = image_bytes.read()
     self.event.logo = content
     self.event.logo_metadata = {
         'hash': crc32(content),
         'size': len(content),
         'filename': os.path.splitext(secure_filename(f.filename, 'logo'))[0] + '.png',
         'content_type': 'image/png'
     }
     flash(_('New logo saved'), 'success')
     logger.info("New logo '%s' uploaded by %s (%s)", f.filename, session.user, self.event)
     return jsonify_data(content=get_logo_data(self.event))
Example #8
0
 def _process(self):
     filename = '{}-category.ics'.format(
         secure_filename(self.category.title, str(self.category.id)))
     buf = serialize_categories_ical([self.category.id], session.user,
                                     Event.end_dt >=
                                     (now_utc() - timedelta(weeks=4)))
     return send_file(filename, buf, 'text/calendar')
Example #9
0
 def _process(self):
     filename = '{}-category.atom'.format(
         secure_filename(self.category.title, str(self.category.id)))
     buf = serialize_category_atom(
         self.category,
         url_for(request.endpoint, self.category, _external=True),
         session.user, Event.end_dt >= now_utc())
     return send_file(filename, buf, 'application/atom+xml')
def _store_paper_template_file(template, file):
    content_type = mimetypes.guess_type(file.filename)[0] or file.mimetype or 'application/octet-stream'
    filename = secure_filename(file.filename, 'template')
    # 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 = filename
    template.save(file.stream)
 def _prepare_folder_structure(self, item):
     attachment = item.attachment
     event_dir = secure_filename(self.event.title, None)
     segments = [event_dir] if event_dir else []
     if _get_start_dt(attachment.folder.object) is None:
         segments.append('Unscheduled')
     segments.extend(self._get_base_path(attachment))
     if not attachment.folder.is_default:
         segments.append(
             secure_filename(attachment.folder.title,
                             unicode(attachment.folder.id)))
     segments.append(attachment.file.filename)
     path = os.path.join(*self._adjust_path_length(filter(None, segments)))
     while path in self.used_filenames:
         # prepend the id if there's a path collision
         segments[-1] = '{}-{}'.format(attachment.id, segments[-1])
         path = os.path.join(
             *self._adjust_path_length(filter(None, segments)))
     return path
Example #12
0
 def _process(self):
     f = request.files['css_file']
     self.event.stylesheet = to_unicode(f.read()).strip()
     self.event.stylesheet_metadata = {
         'hash': crc32(self.event.stylesheet),
         'size': len(self.event.stylesheet),
         'filename': secure_filename(f.filename, 'stylesheet.css')
     }
     db.session.flush()
     flash(_('New CSS file saved. Do not forget to enable it ("Use custom CSS") after verifying that it is correct '
             'using the preview.'), 'success')
     logger.info('CSS file for %s uploaded by %s', self.event, session.user)
     return jsonify_data(content=get_css_file_data(self.event))
def create_paper_revision(paper, submitter, files):
    revision = PaperRevision(paper=paper, submitter=submitter)
    for f in files:
        filename = secure_filename(f.filename, 'paper')
        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.management, 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):
     f = request.files['file']
     filename = secure_filename(f.filename, 'image')
     data = BytesIO()
     shutil.copyfileobj(f, data)
     data.seek(0)
     try:
         image_type = Image.open(data).format.lower()
     except IOError:
         # Invalid image data
         return jsonify(error="Invalid image data!")
     data.seek(0)
     if image_type not in {'jpeg', 'gif', 'png'}:
         return jsonify(error="File format not accepted!")
     content_type = 'image/' + image_type
     image = DesignerImageFile(template=self.template, filename=filename, content_type=content_type)
     self.template.background_image = image
     image.save(data)
     flash(_("The image has been uploaded"), 'success')
     return jsonify_data(image_url=image.download_url)
Example #15
0
 def _process_POST(self):
     f = request.files[self.IMAGE_TYPE]
     try:
         img = Image.open(f)
     except IOError:
         flash(_('You cannot upload this file as an icon/logo.'), 'error')
         return jsonify_data(content=None)
     if img.format.lower() not in {'jpeg', 'png', 'gif'}:
         flash(
             _('The file has an invalid format ({format})').format(
                 format=img.format), 'error')
         return jsonify_data(content=None)
     if img.mode == 'CMYK':
         flash(
             _('The image you uploaded is using the CMYK colorspace and has been converted to RGB.  '
               'Please check if the colors are correct and convert it manually if necessary.'
               ), 'warning')
         img = img.convert('RGB')
     img = self._resize(img)
     image_bytes = BytesIO()
     img.save(image_bytes, 'PNG')
     image_bytes.seek(0)
     content = image_bytes.read()
     metadata = {
         'hash':
         crc32(content),
         'size':
         len(content),
         'filename':
         os.path.splitext(secure_filename(f.filename, self.IMAGE_TYPE))[0] +
         '.png',
         'content_type':
         'image/png'
     }
     self._set_image(content, metadata)
     flash(self.SAVED_FLASH_MSG, 'success')
     logger.info("New {} '%s' uploaded by %s (%s)".format(self.IMAGE_TYPE),
                 f.filename, session.user, self.category)
     return jsonify_data(
         content=get_image_data(self.IMAGE_TYPE, self.category))
Example #16
0
 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_filename(file_.filename, 'attachment'),
             '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
Example #17
0
 def _process(self):
     files = request.files.getlist('image')
     num = 0
     for f in files:
         filename = secure_filename(f.filename, 'image')
         data = BytesIO()
         shutil.copyfileobj(f, data)
         data.seek(0)
         try:
             image_type = Image.open(data).format.lower()
         except IOError:
             # 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))
Example #18
0
 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_filename(f.filename, 'attachment')
             attachment = Attachment(folder=folder, user=session.user, title=to_unicode(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))
Example #19
0
 def _prepare_folder_structure(self, item):
     file_name = secure_filename(
         '{}_{}'.format(unicode(item.id), item.filename), item.filename)
     return os.path.join(*self._adjust_path_length([file_name]))
def test_secure_filename(filename, expected):
    assert secure_filename(filename, 'fallback') == expected
Example #21
0
def send_file(name,
              path_or_fd,
              mimetype,
              last_modified=None,
              no_cache=True,
              inline=None,
              conditional=False,
              safe=True):
    """Sends a file to the user.

    `name` is required and should be the filename visible to the user.
    `path_or_fd` is either the physical path to the file or a file-like object (e.g. a StringIO).
    `mimetype` SHOULD be a proper MIME type such as image/png. It may also be an fossir-style file type such as JPG.
    `last_modified` may contain a unix timestamp or datetime object indicating the last modification of the file.
    `no_cache` can be set to False to disable no-cache headers.
    `inline` defaults to true except for certain filetypes like XML and CSV. It SHOULD be set to false only when you
    want to force the user's browser to download the file. Usually it is much nicer if e.g. a PDF file can be displayed
    inline so don't disable it unless really necessary.
    `conditional` is very useful when sending static files such as CSS/JS/images. It will allow the browser to retrieve
    the file only if it has been modified (based on mtime and size).
    `safe` adds some basic security features such a adding a content-security-policy and forcing inline=False for
    text/html mimetypes
    """

    name = secure_filename(name, 'file')
    assert '/' in mimetype
    if inline is None:
        inline = mimetype not in ('text/csv', 'text/xml', 'application/xml')
    if request.user_agent.platform == 'android':
        # Android is just full of fail when it comes to inline content-disposition...
        inline = False
    if _is_office_mimetype(mimetype):
        inline = False
    if safe and mimetype in ('text/html', 'image/svg+xml'):
        inline = False
    try:
        rv = _send_file(path_or_fd,
                        mimetype=mimetype,
                        as_attachment=not inline,
                        attachment_filename=name,
                        conditional=conditional)
    except IOError:
        if not current_app.debug:
            raise
        raise NotFound('File not found: %s' % path_or_fd)
    if safe:
        rv.headers.add('Content-Security-Policy',
                       "script-src 'self'; object-src 'self'")
    if inline:
        # send_file does not add this header if as_attachment is False
        rv.headers.add('Content-Disposition', 'inline', filename=name)
    if last_modified:
        if not isinstance(last_modified, int):
            last_modified = int(time.mktime(last_modified.timetuple()))
        rv.last_modified = last_modified
    if no_cache:
        del rv.expires
        del rv.cache_control.max_age
        rv.cache_control.public = False
        rv.cache_control.private = True
        rv.cache_control.no_cache = True
    return rv