Example #1
0
    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_new:
            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:
                    paths.append(secure_filename('{}_{}'.format(format_time(start_date, format='HHmm',
                                                                            timezone=self.event_new.timezone),
                                                                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_new and linked_obj_start_date is not None:
            paths.append(secure_filename(linked_obj_start_date.strftime('%Y%m%d_%A'), ''))

        return reversed(paths)
Example #2
0
    def _get_base_path(self, attachment):
        obj = linked_object = attachment.folder.linked_object
        paths = []
        while obj != self._conf:
            owner = obj.getOwner()
            if isinstance(obj, SubContribution):
                start_date = owner.getAdjustedStartDate()
            else:
                start_date = obj.getAdjustedStartDate()

            if start_date is not None:
                paths.append(secure_filename(start_date.strftime('%H%M_{}').format(obj.getTitle()), ''))
            else:
                paths.append(secure_filename(obj.getTitle(), unicode(obj.getId())))
            obj = owner

        if isinstance(linked_object, SubContribution):
            linked_obj_start_date = linked_object.getOwner().getAdjustedStartDate()
        else:
            linked_obj_start_date = linked_object.getAdjustedStartDate()

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

        return reversed(paths)
Example #3
0
 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]))
Example #4
0
 def _prepare_folder_structure(self, attachment):
     event_dir = secure_filename(self._conf.getTitle(), None)
     segments = [event_dir] if event_dir else []
     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(*adjust_path_length(filter(None, segments)))
     while path in self.used:
         # prepend the id if there's a path collision
         segments[-1] = '{}-{}'.format(attachment.id, segments[-1])
         path = os.path.join(*adjust_path_length(filter(None, segments)))
     return path
Example #5
0
 def _process(self):
     files = request.files.getlist('file')
     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)
         if image_type not in {'jpeg', 'gif', 'png'}:
             continue
         content_type = 'image/' + image_type
         image = ImageFile(event_id=self._conf.id, filename=filename, content_type=content_type)
         image.save(data)
         db.session.add(image)
         db.session.flush()
         logger.info('Image {} uploaded by {}'.format(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", len(files))
           .format(count=len(files)), 'success')
     return jsonify_data(image_list=_render_image_list(self._conf))
Example #6
0
    def migrate_event_images(self):
        self.print_step('migrating event images')
        for event, picture in committing_iterator(self._iter_pictures()):
            local_file = picture._localFile
            content_type = mimetypes.guess_type(local_file.fileName)[0] or 'application/octet-stream'
            storage_backend, storage_path, size = self._get_local_file_info(local_file)

            if storage_path is None:
                self.print_warning(cformat('%{yellow}[{}]%{reset} -> %{red!}Not found in filesystem').format(
                    local_file.id), event_id=event.id)
                continue

            filename = secure_filename(convert_to_unicode(local_file.fileName), 'image')
            image = ImageFile(event_id=event.id,
                              filename=filename,
                              content_type=content_type,
                              created_dt=now_utc(),
                              size=size,
                              storage_backend=storage_backend,
                              storage_file_id=storage_path)

            db.session.add(image)
            db.session.flush()

            map_entry = LegacyImageMapping(event_id=event.id, legacy_image_id=local_file.id, image_id=image.id)

            db.session.add(map_entry)

            if not self.quiet:
                self.print_success(cformat('%{cyan}[{}]%{reset} -> %{blue!}{}').format(local_file.id, image),
                                   event_id=event.id)
Example #7
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 #8
0
 def _process(self):
     files = request.files.getlist("image")
     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)
         if image_type not in {"jpeg", "gif", "png"}:
             continue
         content_type = "image/" + image_type
         image = ImageFile(event_new=self.event_new, filename=filename, content_type=content_type)
         image.save(data)
         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", len(files)).format(
             count=len(files)
         ),
         "success",
     )
     return jsonify_data(image_list=_render_image_list(self.event_new))
Example #9
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 #10
0
 def _process(self):
     f = request.files["file"]
     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=_logo_data(self.event))
Example #11
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 #12
0
    def _process_logo(self, logo, event):
        path = get_archived_file(logo, self.archive_dirs)[1]
        if path is None:
            self.print_error(cformat('%{red!}Logo not found on disk; skipping it'), event_id=event.id)
            return

        try:
            logo_image = Image.open(path)
        except IOError as e:
            self.print_warning("Cannot open {}: {}".format(path, e), event_id=event.id)
            return

        if logo_image.mode == 'CMYK':
            self.print_warning("Logo is a CMYK {}; converting to RGB".format(logo_image.format),
                               event_id=event.id)
            # this may result in wrong colors, but there's not much we can do...
            logo_image = logo_image.convert('RGB')

        logo_bytes = BytesIO()
        logo_image.save(logo_bytes, 'PNG')
        logo_bytes.seek(0)
        logo_content = logo_bytes.read()
        logo_filename = secure_filename(convert_to_unicode(logo.fileName), 'logo')
        logo_filename = os.path.splitext(logo_filename)[0] + '.png'
        event.logo_metadata = {
            'size': len(logo_content),
            'hash': crc32(logo_content),
            'filename': logo_filename,
            'content_type': 'image/png'
        }
        event.logo = logo_content
        if not self.quiet:
            self.print_success(cformat('- %{cyan}[Logo] {}').format(logo.fileName), event_id=event.id)
Example #13
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 #14
0
 def _prepare_folder_structure(self, item):
     attachment = item.attachment
     event_dir = secure_filename(self.event_new.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 #15
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')
Example #16
0
 def _process(self):
     from indico.modules.events import Event
     filename = '{}-category.atom'.format(secure_filename(self._target.getName(), str(self._target.id)))
     buf = serialize_category_atom(self._target,
                                   url_for(request.endpoint, self._target, _external=True),
                                   session.user,
                                   Event.end_dt >= now_utc())
     return send_file(filename, buf, 'application/atom+xml')
Example #17
0
    def pack(self, fileHandler=None):
        for contribution in self._conf.as_event.contributions:
            reviewingStatus = self._conf.getReviewManager(contribution).getLastReview().getRefereeJudgement().getJudgement()
            if reviewingStatus == "Accept":
                dirName = secure_filename(contribution.title, fallback='')
                self._packContribution(contribution, dirName, fileHandler)

        fileHandler.close()
        return fileHandler.getPath()
Example #18
0
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)
Example #19
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 indico-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')
    if inline is None:
        inline = mimetype not in ('XML', 'CSV')
    if request.user_agent.platform == 'android':
        # Android is just full of fail when it comes to inline content-disposition...
        inline = False
    if mimetype.isupper() and '/' not in mimetype:
        # Indico file type such as "JPG" or "CSV"
        from indico.core.config import Config
        mimetype = Config.getInstance().getFileTypeMimeType(mimetype)
    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:
        from MaKaC.common.info import HelperMaKaCInfo
        if not 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
Example #20
0
 def _attachment_from_resource(self, folder, material, resource, base_object=None):
     modified_dt = (
         getattr(material, "_modificationDS", None)
         or getattr(base_object, "startDate", None)
         or getattr(base_object, "_modificationDS", None)
         or now_utc()
     )
     data = {
         "id": self._get_id(Attachment),
         "folder_id": folder["id"],
         "user_id": self.janitor_user_id,
         "title": convert_to_unicode(resource.name).strip() or folder["title"],
         "description": convert_to_unicode(resource.description),
         "modified_dt": modified_dt,
     }
     if resource.__class__.__name__ == "Link":
         data["type"] = AttachmentType.link
         data["link_url"] = convert_to_unicode(resource.url).strip()
         if not data["link_url"]:
             self.print_error(
                 cformat("%{red!}[{}] Skipping link, missing URL").format(data["title"]), event_id=base_object.id
             )
             return None
     else:
         data["type"] = AttachmentType.file
         storage_backend, storage_path, size = self._get_local_file_info(resource)
         if storage_path is None:
             self.print_error(
                 cformat("%{red!}File {} not found on disk").format(resource._LocalFile__archivedId),
                 event_id=base_object.id,
             )
             return None
         filename = secure_filename(convert_to_unicode(resource.fileName), "attachment")
         file_data = {
             "id": self._get_id(AttachmentFile),
             "attachment_id": data["id"],
             "user_id": self.janitor_user_id,
             "created_dt": modified_dt,
             "filename": filename,
             "content_type": mimetypes.guess_type(filename)[0] or "application/octet-stream",
             "size": size,
             "storage_backend": storage_backend,
             "storage_file_id": storage_path,
         }
         data["file_id"] = file_data["id"]
         self.todo[AttachmentFile].append(file_data)
     tmp = ProtectionTarget()
     protection_from_ac(tmp, resource._Resource__ac)
     self.todo[AttachmentPrincipal] += tmp.make_principal_rows(attachment_id=data["id"])
     data["protection_mode"] = tmp.protection_mode
     self.todo[Attachment].append(data)
     return data
Example #21
0
 def _process(self):
     files = request.files.getlist('file')
     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'
         paper_file = PaperFile(filename=filename, content_type=content_type, contribution=self.contrib)
         paper_file.save(f.file)
         db.session.flush()
         # TODO: logger logger.info('Paper file %s uploaded by %s', paper_file, session.user)
         # TODO: add signal
     flash(ngettext("The paper file has been uploaded", "{count} paper files have been uploaded", len(files))
           .format(count=len(files)), 'success')
     return jsonify_data(html=_render_paper_file_list(self.contrib))
Example #22
0
 def _process(self):
     files = request.files.getlist('paper_file')
     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'
         paper_file = PaperFile(filename=filename, content_type=content_type, contribution=self.contrib)
         paper_file.save(f.file)
         db.session.flush()
         # TODO: logger logger.info('Paper file %s uploaded by %s', paper_file, session.user)
         # TODO: add signal
     flash(ngettext("The paper file has been uploaded", "{count} paper files have been uploaded", len(files))
           .format(count=len(files)), 'success')
     return jsonify_data(html=_render_paper_file_list(self.contrib))
Example #23
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))
Example #24
0
 def process_form_data(self, registration, value, old_data=None, billable_items_locked=False):
     data = {'field_data': self.form_item.current_data}
     file_ = value['uploaded_file']
     if file_:
         # we have a file -> always save it
         data['file'] = {
             'data': file_.file,
             '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 #25
0
 def process_form_data(self, registration, value, old_data=None, billable_items_locked=False):
     data = {'field_data': self.form_item.current_data}
     file_ = value['uploaded_file']
     if file_:
         # we have a file -> always save it
         data['file'] = {
             'data': file_.file,
             '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 #26
0
def set_user_avatar(user, avatar, filename, lastmod=None):
    if lastmod is None:
        lastmod = http_date(now_utc())
    elif isinstance(lastmod, datetime):
        lastmod = http_date(lastmod)
    user.picture = avatar
    user.picture_metadata = {
        'hash': crc32(avatar),
        'size': len(avatar),
        'filename': os.path.splitext(secure_filename(filename, 'avatar'))[0] + '.png',
        'content_type': 'image/png',
        'lastmod': lastmod,
    }
Example #27
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))
Example #28
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 indico-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
Example #29
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.file)

            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 #30
0
    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(f'{obj.position}_{obj.title}', ''))
                else:
                    time = format_time(start_date, format='HHmm', timezone=self.event.timezone)
                    paths.append(secure_filename(f'{time}_{obj.title}', ''))
            else:
                if isinstance(obj, SubContribution):
                    paths.append(secure_filename(f'{obj.position}_{obj.title}', str(obj.id)))
                else:
                    paths.append(secure_filename(obj.title, str(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)
Example #31
0
 def _build_storage_path(self):
     self.registration.registration_form.assign_id()
     self.registration.assign_id()
     path_segments = [
         'event',
         strict_unicode(self.registration.event_id), 'registrations',
         strict_unicode(self.registration.registration_form.id),
         strict_unicode(self.registration.id)
     ]
     assert None not in path_segments
     # add timestamp in case someone uploads the same file again
     filename = '{}-{}-{}'.format(self.field_data.field_id,
                                  int(time.time()),
                                  secure_filename(self.filename, 'file'))
     path = posixpath.join(*(path_segments + [filename]))
     return config.ATTACHMENT_STORAGE, path
Example #32
0
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.reviewing, EventLogKind.positive, 'Papers',
                    "Paper revision {} submitted for contribution {} ({})"
                    .format(revision.id, paper.contribution.title, paper.contribution.friendly_id), session.user)
    return revision
Example #33
0
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
Example #34
0
 def _process_css(self, css):
     stylesheet = css._localFile
     path = get_archived_file(stylesheet, self.archive_dirs)[1]
     if path is None:
         self.print_error('%[red!]CSS file not found on disk; skipping it')
         return
     with open(path, 'rb') as f:
         stylesheet_content = convert_to_unicode(f.read())
     self.event.stylesheet_metadata = {
         'size': len(stylesheet_content),
         'hash': crc32(stylesheet_content),
         'filename': secure_filename(convert_to_unicode(stylesheet.fileName), 'stylesheet.css'),
         'content_type': 'text/css'
     }
     self.event.stylesheet = stylesheet_content
     if not self.quiet:
         self.print_success('- %[cyan][CSS] {}'.format(stylesheet.fileName))
Example #35
0
 def _process_css(self, css, event):
     stylesheet = css._localFile
     path = get_archived_file(stylesheet, self.archive_dirs)[1]
     if path is None:
         self.print_error(cformat('%{red!}CSS file not found on disk; skipping it'), event_id=event.id)
         return
     with open(path, 'rb') as f:
         stylesheet_content = convert_to_unicode(f.read())
     event.stylesheet_metadata = {
         'size': len(stylesheet_content),
         'hash': crc32(stylesheet_content),
         'filename': secure_filename(convert_to_unicode(stylesheet.fileName), 'stylesheet.css'),
         'content_type': 'text/css'
     }
     event.stylesheet = stylesheet_content
     if not self.quiet:
         self.print_success(cformat('- %{cyan}[CSS] {}').format(stylesheet.fileName), event_id=event.id)
Example #36
0
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 #37
0
 def build_storage_path(self, obj, _new_path_re=re.compile(r'^(event/\d+/registrations/\d+/\d+/\d+-)(\d+)(-.*)$')):
     old_filename = obj.filename
     new_filename = secure_filename(obj.filename, None)
     assert new_filename
     obj.filename = new_filename
     new_storage_path = obj._build_storage_path()[1]
     obj.filename = old_filename
     assert new_storage_path
     if not isinstance(obj, RegistrationData):
         return new_storage_path, new_filename
     match = _new_path_re.match(obj.storage_file_id)
     if match:
         # already in the current format
         assert obj.storage_file_id == new_storage_path.replace('-0-', '-{}-'.format(match.group(2)))
         return obj.storage_file_id, new_filename
     else:
         match = _new_path_re.match(new_storage_path)
         return '{}{}{}'.format(match.group(1), crc32(obj.storage_file_id), match.group(3)), new_filename
Example #38
0
 def _process(self):
     f = request.files["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=_css_file_data(self.event))
Example #39
0
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.reviewing, EventLogKind.positive, 'Abstracts', msg, session.user,
                           data={'Files': ', '.join(f.filename for f in abstract.files)})
 def _migrate_background(self, old_bg, tpl):
     storage_backend, storage_path, size = self.importer._get_local_file_info(
         old_bg)
     if storage_path is None:
         self.importer.print_error(
             '%[red!]File not found on disk; skipping it [{}]'.format(
                 convert_to_unicode(old_bg.fileName)),
             event_id=self.event_id)
         return
     content_type = mimetypes.guess_type(
         old_bg.fileName)[0] or 'application/octet-stream'
     filename = secure_filename(convert_to_unicode(old_bg.fileName),
                                'attachment')
     return DesignerImageFile(filename=filename,
                              content_type=content_type,
                              size=size,
                              storage_backend=storage_backend,
                              storage_file_id=storage_path)
Example #41
0
    def _process_icon(self, cat, icon):
        path = get_archived_file(icon, self.archive_dirs)[1]
        if path is None:
            self.print_error(
                cformat('%{red!}Icon not found on disk; skipping it'),
                event_id=cat.id)
            return

        try:
            icon_image = Image.open(path)
        except IOError as e:
            self.print_warning("Cannot open {}: {}".format(path, e),
                               event_id=cat.id)
            return

        if icon_image.mode == 'CMYK':
            self.print_warning("Icon is a CMYK {}; converting to RGB".format(
                icon_image.format),
                               always=False,
                               event_id=cat.id)
            # this may result in wrong colors, but there's not much we can do...
            icon_image = icon_image.convert('RGB')

        if icon_image.size != (16, 16):
            self.print_warning(
                "Icon is {}x{}; resizing to 16x16".format(*icon_image.size),
                always=False,
                event_id=cat.id)
            icon_image = icon_image.resize((16, 16), Image.ANTIALIAS)

        icon_bytes = BytesIO()
        icon_image.save(icon_bytes, 'PNG')
        icon_bytes.seek(0)
        icon_content = icon_bytes.read()
        icon_filename = secure_filename(convert_to_unicode(icon.fileName),
                                        'icon')
        icon_filename = os.path.splitext(icon_filename)[0] + '.png'
        cat.icon_metadata = {
            'size': len(icon_content),
            'hash': crc32(icon_content),
            'filename': icon_filename,
            'content_type': 'image/png'
        }
        cat.icon = icon_content
Example #42
0
def submit_attachment(task, attachment):
    """Sends an attachment's file to the conversion service"""
    from indico_conversion.plugin import ConversionPlugin
    if ConversionPlugin.settings.get('maintenance'):
        task.retry(countdown=900)
    url = ConversionPlugin.settings.get('server_url')
    payload = {
        'attachment_id': attachment.id
    }
    data = {
        'converter': 'pdf',
        'urlresponse': url_for_plugin('conversion.callback', _external=True),
        'dirresponse': secure_serializer.dumps(payload, salt='pdf-conversion')
    }
    file = attachment.file
    name, ext = os.path.splitext(file.filename)
    # we know ext is safe since it's based on a whitelist. the name part may be fully
    # non-ascii so we sanitize that to a generic name if necessary
    filename = secure_filename(name, 'attachment') + ext
    with file.open() as fd:
        try:
            response = requests.post(url, data=data, files={'uploadedfile': (filename, fd, file.content_type)})
            response.raise_for_status()
            if 'ok' not in response.text:
                raise requests.RequestException(f'Unexpected response from server: {response.text}')
        except requests.RequestException as exc:
            attempt = task.request.retries + 1
            try:
                delay = DELAYS[task.request.retries] if not config.DEBUG else 1
            except IndexError:
                # like this we can safely bump MAX_TRIES manually if necessary
                delay = DELAYS[-1]
            try:
                task.retry(countdown=delay, max_retries=(MAX_TRIES - 1))
            except MaxRetriesExceededError:
                ConversionPlugin.logger.error('Could not submit attachment %d (attempt %d/%d); giving up [%s]',
                                              attachment.id, attempt, MAX_TRIES, exc)
                pdf_state_cache.delete(str(attachment.id))
            except Retry:
                ConversionPlugin.logger.warning('Could not submit attachment %d (attempt %d/%d); retry in %ds [%s]',
                                                attachment.id, attempt, MAX_TRIES, delay, exc)
                raise
        else:
            ConversionPlugin.logger.info('Submitted %r', attachment)
Example #43
0
    def _process(self):
        defaults = FormDefaults(self.attachment, protected=self.attachment.is_protected, skip_attrs={'file'})
        if self.attachment.type == AttachmentType.file:
            file_ = self.attachment.file
            # file_attrs has to be manually "serialized", since it's going to be converted to JSON
            file_attrs = {
                'url': url_for('attachments.download', self.attachment, filename=self.attachment.file.filename,
                               from_preview='1'),
                'filename': file_.filename,
                'size': file_.size,
                'content_type': file_.content_type
            }
            form = EditAttachmentFileForm(linked_object=self.object, obj=defaults, file=file_attrs)
        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 {} edited by {}'.format(self.attachment, session.user))
            form.populate_obj(self.attachment, skip={'acl', 'file'})
            self.attachment.folder = folder
            if self.attachment.is_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 = request.files['file'] if request.files else None
                if file:
                    self.attachment.file = AttachmentFile(user=session.user, content_type=file.mimetype,
                                                          filename=secure_filename(file.filename, 'attachment'))
                    self.attachment.file.save(file.file)

            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 #44
0
 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 #45
0
 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 OSError:
         # 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 #46
0
    def _process_logo(self, logo, event):
        path = get_archived_file(logo, self.archive_dirs)[1]
        if path is None:
            self.print_error(
                cformat('%{red!}Logo not found on disk; skipping it'),
                event_id=event.id)
            return

        try:
            logo_image = Image.open(path)
        except IOError as e:
            self.print_warning("Cannot open {}: {}".format(path, e),
                               event_id=event.id)
            return

        if logo_image.mode == 'CMYK':
            self.print_warning("Logo is a CMYK {}; converting to RGB".format(
                logo_image.format),
                               event_id=event.id)
            # this may result in wrong colors, but there's not much we can do...
            logo_image = logo_image.convert('RGB')

        logo_bytes = BytesIO()
        logo_image.save(logo_bytes, 'PNG')
        logo_bytes.seek(0)
        logo_content = logo_bytes.read()
        logo_filename = secure_filename(convert_to_unicode(logo.fileName),
                                        'logo')
        logo_filename = os.path.splitext(logo_filename)[0] + '.png'
        event.logo_metadata = {
            'size': len(logo_content),
            'hash': crc32(logo_content),
            'filename': logo_filename,
            'content_type': 'image/png'
        }
        event.logo = logo_content
        if not self.quiet:
            self.print_success(cformat('- %{cyan}[Logo] {}').format(
                logo.fileName),
                               event_id=event.id)
Example #47
0
    def migrate_event_images(self):
        self.print_step('migrating event images')
        for event, picture in committing_iterator(self._iter_pictures()):
            local_file = picture._localFile
            content_type = mimetypes.guess_type(
                local_file.fileName)[0] or 'application/octet-stream'
            storage_backend, storage_path, size = self._get_local_file_info(
                local_file)

            if storage_path is None:
                self.print_warning(cformat(
                    '%{yellow}[{}]%{reset} -> %{red!}Not found in filesystem').
                                   format(local_file.id),
                                   event_id=event.id)
                continue

            filename = secure_filename(convert_to_unicode(local_file.fileName),
                                       'image')
            image = ImageFile(event_id=event.id,
                              filename=filename,
                              content_type=content_type,
                              created_dt=now_utc(),
                              size=size,
                              storage_backend=storage_backend,
                              storage_file_id=storage_path)

            db.session.add(image)
            db.session.flush()

            map_entry = LegacyImageMapping(event_id=event.id,
                                           legacy_image_id=local_file.id,
                                           image_id=image.id)

            db.session.add(map_entry)

            if not self.quiet:
                self.print_success(
                    cformat('%{cyan}[{}]%{reset} -> %{blue!}{}').format(
                        local_file.id, image),
                    event_id=event.id)
Example #48
0
 def _attachment_from_resource(self, folder, material, resource, base_object=None):
     modified_dt = (getattr(material, '_modificationDS', None) or getattr(base_object, 'startDate', None) or
                    getattr(base_object, '_modificationDS', None) or now_utc())
     data = {'id': self._get_id(Attachment),
             'folder_id': folder['id'],
             'user_id': self.janitor_user_id,
             'title': convert_to_unicode(resource.name).strip() or folder['title'],
             'description': convert_to_unicode(resource.description),
             'modified_dt': modified_dt}
     if resource.__class__.__name__ == 'Link':
         data['type'] = AttachmentType.link
         data['link_url'] = convert_to_unicode(resource.url).strip()
         if not data['link_url']:
             self.print_error(cformat('%{red!}[{}] Skipping link, missing URL').format(data['title']),
                              event_id=base_object.id)
             return None
     else:
         data['type'] = AttachmentType.file
         storage_backend, storage_path, size = self._get_local_file_info(resource)
         if storage_path is None:
             self.print_error(cformat('%{red!}File {} not found on disk').format(resource._LocalFile__archivedId),
                              event_id=base_object.id)
             return None
         filename = secure_filename(convert_to_unicode(resource.fileName), 'attachment')
         file_data = {'id': self._get_id(AttachmentFile),
                      'attachment_id': data['id'],
                      'user_id': self.janitor_user_id,
                      'created_dt': modified_dt,
                      'filename': filename,
                      'content_type': mimetypes.guess_type(filename)[0] or 'application/octet-stream',
                      'size': size,
                      'storage_backend': storage_backend,
                      'storage_file_id': storage_path}
         self.todo[AttachmentFile].append(file_data)
     tmp = ProtectionTarget()
     protection_from_ac(tmp, resource._Resource__ac)
     self.todo[AttachmentPrincipal] += tmp.make_principal_rows(attachment_id=data['id'])
     data['protection_mode'] = tmp.protection_mode
     self.todo[Attachment].append(data)
     return data
Example #49
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.file)
             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 #50
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 #51
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')
     if (self._dlg):
         return jsonify_data(image_list=_render_image_list_dlg(self.event))
     return jsonify_data(image_list=_render_image_list(self.event))
Example #52
0
    def _create_material(self, logs):
        folder = AttachmentFolder.find_first(object=self.event,
                                             is_default=False,
                                             title='Chat Logs',
                                             is_deleted=False)
        if folder is None:
            folder = AttachmentFolder(protection_mode=ProtectionMode.protected,
                                      linked_object=self.event,
                                      title='Chat Logs',
                                      description='Chat logs for this event')
            db.session.add(folder)

        filename = '{}.html'.format(secure_filename(self.material_name,
                                                    'logs'))
        attachment = Attachment(
            folder=folder,
            user=session.user,
            title=self.material_name,
            type=AttachmentType.file,
            description="Chat logs for the chat room '{}'".format(
                self.chatroom.name))
        attachment.file = AttachmentFile(user=session.user,
                                         filename=filename,
                                         content_type='text/html')
        attachment.file.save(logs.encode('utf-8'))
        db.session.flush()
        signals.attachments.attachment_created.send(attachment,
                                                    user=session.user)
        log_data = [
            ('Range',
             'Everything' if not self.date_filter else '{} - {}'.format(
                 format_date(self.start_date), format_date(self.end_date))),
        ]
        self.event.log(EventLogRealm.management,
                       EventLogKind.positive,
                       'Chat',
                       'Created material: {}'.format(filename),
                       session.user,
                       data=log_data)
 def build_storage_path(
     self,
     obj,
     _new_path_re=re.compile(
         r'^(event/\d+/registrations/\d+/\d+/\d+-)(\d+)(-.*)$')):
     old_filename = obj.filename
     new_filename = secure_filename(obj.filename, None)
     assert new_filename
     obj.filename = new_filename
     new_storage_path = obj._build_storage_path()[1]
     obj.filename = old_filename
     assert new_storage_path
     if not isinstance(obj, RegistrationData):
         return new_storage_path, new_filename
     match = _new_path_re.match(obj.storage_file_id)
     if match:
         # already in the current format
         assert obj.storage_file_id == new_storage_path.replace(
             '-0-', '-{}-'.format(match.group(2)))
         return obj.storage_file_id, new_filename
     else:
         match = _new_path_re.match(new_storage_path)
         return '{}{}{}'.format(match.group(1), crc32(obj.storage_file_id),
                                match.group(3)), new_filename
Example #54
0
    def _migrate_templates(self):
        for __, old_tpl in self.pr._templates.viewitems():
            old_filename = convert_to_unicode(old_tpl._Template__file.name)
            storage_backend, storage_path, size = self._get_local_file_info(
                old_tpl._Template__file)
            if storage_path is None:
                self.print_error(
                    '%[red!]File not found on disk; skipping it [{}]'.format(
                        old_filename))
                continue

            filename = secure_filename(old_filename, 'attachment')
            content_type = mimetypes.guess_type(
                old_filename)[0] or 'application/octet-stream'
            tpl = PaperTemplate(
                filename=filename,
                content_type=content_type,
                size=size,
                storage_backend=storage_backend,
                storage_file_id=storage_path,
                name=convert_to_unicode(old_tpl._Template__name)
                or old_filename,
                description=convert_to_unicode(old_tpl._Template__description))
            self.event.paper_templates.append(tpl)
Example #55
0
 def build_storage_path(self, obj, _new_path_re=re.compile(r'^(event/\d+/registrations/\d+/\d+/\d+-)(\d+)(-.*)$')):
     if isinstance(obj, File):
         # ``File``` was added in 2.3 and thus always has the correct paths
         # we cannot re-generate the storage path for it since it uses
         # a __context attribute which is only present during the initial
         # `save()` call and not stored anywhere.
         return obj.storage_file_id, obj.filename
     old_filename = obj.filename
     new_filename = secure_filename(obj.filename, None)
     assert new_filename
     obj.filename = new_filename
     new_storage_path = obj._build_storage_path()[1]
     obj.filename = old_filename
     assert new_storage_path
     if not isinstance(obj, RegistrationData):
         return new_storage_path, new_filename
     match = _new_path_re.match(obj.storage_file_id)
     if match:
         # already in the current format
         assert obj.storage_file_id == new_storage_path.replace('-0-', f'-{match.group(2)}-')
         return obj.storage_file_id, new_filename
     else:
         match = _new_path_re.match(new_storage_path)
         return f'{match.group(1)}{crc32(obj.storage_file_id)}{match.group(3)}', new_filename
Example #56
0
 def locator(self):
     return dict(self.revision.locator,
                 file_id=self.file_id,
                 filename=secure_filename(self.file.filename,
                                          f'file-{self.file_id}'))
Example #57
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]))
Example #58
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 #59
0
 def _process(self):
     filename = secure_filename('{}-Ticket.pdf'.format(self.event.title),
                                'ticket.pdf')
     return send_file(filename, generate_ticket(self.registration),
                      'application/pdf')
Example #60
0
 def _prepare_folder_structure(self, item):
     abstract_title = secure_filename('{}_{}'.format(unicode(item.abstract.friendly_id), item.abstract.title),
                                      '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]))