Skip to content
This repository has been archived by the owner on Sep 5, 2019. It is now read-only.

Commit

Permalink
Adds a file upload syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Krienbühl committed May 29, 2015
1 parent 96270e5 commit 066cc22
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 13 deletions.
3 changes: 3 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Changelog
Unreleased
~~~~~~~~~~

- Adds a file upload syntax.
[href]

- Show the 'required' flag, even if the requirement is conditional.
[href]

Expand Down
35 changes: 27 additions & 8 deletions onegov/form/core.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import base64
import inspect
import magic
import weakref
Expand All @@ -7,6 +8,7 @@
from onegov.form.errors import InvalidMimeType
from operator import itemgetter
from mimetypes import types_map
from wtforms import FileField
from wtforms import Form as BaseForm


Expand Down Expand Up @@ -90,30 +92,47 @@ def __init__(self, *args, **kwargs):
fields=(self._fields[f[1]] for f in fields)
))

def submitted(self, request):
def submitted(self, request, whitelist=default_whitelist):
""" Returns true if the given request is a successful post request. """
return request.POST and self.validate()
valid = request.POST and self.validate()

def load_file(self, request, field_id, whitelist=default_whitelist):
if not valid:
return False

# load the files, making sure their mime type is on a whitelist and
# that their mimetype matches the extension they have
#
# access the files through self._files after that
for field in self._fields.values():
if isinstance(field, FileField):
field.data = self.load_file(request, field)

return True

def load_file(self, request, field, whitelist=default_whitelist):
""" Loads the given input field from the request, making sure it's
mimetype matches the extension and is found in the mimetype whitelist.
"""

field = getattr(self, field_id)
file_ext = '.' + field.data.split('.')[-1]
file_data = request.FILES[field.name].read()
file_ext = '.' + field.data.filename.split('.')[-1]
file_data = request.POST[field.id].file.read()

mimetype_by_extension = types_map.get(file_ext, '0xdeadbeef')
mimetype_by_introspection = magic.from_buffer(file_data)
mimetype_by_introspection = magic.from_buffer(file_data, mime=True)
mimetype_by_introspection = mimetype_by_introspection.decode('utf-8')

if mimetype_by_extension != mimetype_by_introspection:
raise InvalidMimeType()

if mimetype_by_introspection not in whitelist:
raise InvalidMimeType()

return file_data
return {
'filename': field.data.filename,
'base64': base64.b64encode(file_data).decode('ascii'),
'mimetype': mimetype_by_introspection
}


class Fieldset(object):
Expand Down
18 changes: 18 additions & 0 deletions onegov/form/parser/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,24 @@
One more time, this doesn't mean that the datetime format can be influenced.
Files
~~~~~
A file upload is defined like this::
I'm a file upload field = *.*
This particular example would allow any file. To allow only certain files
do something like this::
I'm a image filed = *.png|*.jpg|*.gif
I'm a document = *.doc
I'm any document = *.doc|*.pdf
The files are checked against their file extension. Onegov.form also checks
that uploaded files have the mimetype they claim to have and it won't accept
obviously dangerous uploads like binaries (unless you really want to).
Standard Numbers
~~~~~~~~~~~~~~~~
Expand Down
7 changes: 2 additions & 5 deletions onegov/form/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,8 @@ class ExpectedExtensions(object):
"""

def __init__(self, extensions):
self.extensions = ['.' + ext.lstrip('.') for ext in extensions]
self.extensions = tuple('.' + ext.lstrip('.') for ext in extensions)

def __call__(self, form, field):
if not field.data:
return

if not field.data.endswith(self.extension):
if not field.data.filename.endswith(self.extensions):
raise ValidationError(field.gettext(u'Invalid input.'))

0 comments on commit 066cc22

Please sign in to comment.