Files
django-dav-events/dav_submission/views.py

248 lines
9.3 KiB
Python

# -*- coding: utf-8 -*-
import codecs
import datetime
import logging
import os
import pytz
import re
import urllib
from django.apps import apps
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.http import FileResponse, Http404
from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.translation import ugettext as _
from django.views import generic
from .forms import UploadForm
app_config = apps.get_containing_app_config(__package__)
logger = logging.getLogger(__name__)
class ListView(generic.ListView):
template_name = 'dav_submission/list.html'
def get_queryset(self):
base_path = app_config.settings.upload_path
metadata_file_name = app_config.settings.metadata_file_name
subdirs = os.listdir(base_path)
all_metadata = {}
for subdir in subdirs:
metadata_file_path = os.path.join(base_path, subdir, metadata_file_name)
if hasattr(urllib, 'quote_plus'):
pk = urllib.quote_plus(subdir)
else:
pk = urllib.parse.quote_plus(subdir)
metadata = {
'pk': pk,
'name': None,
'email_address': None,
'title': None,
'timestamp': None,
}
with open(metadata_file_path) as f:
for line in f:
mo = re.match(r'^Absender: (.*) <(.*)>$', line)
if mo is not None:
metadata['name'] = mo.group(1)
metadata['email_address'] = mo.group(2)
continue
mo = re.match(r'^Titel: (.*)$', line)
if mo is not None:
metadata['title'] = mo.group(1)
continue
mo = re.match(r'^Datum: ([0-9]{2}.[0-9]{2}.[0-9]{4}) ([0-9]{2}:[0-9]{2}:[0-9]{2}) (.*)$', line)
if mo is not None:
date_str = mo.group(1)
time_str = mo.group(2)
zone_str = mo.group(3)
datetime_str = '{} {}'.format(date_str, time_str)
timestamp = datetime.datetime.strptime(datetime_str, '%d.%m.%Y %H:%M:%S')
tz = pytz.timezone(zone_str)
metadata['timestamp'] = tz.localize(timestamp)
continue
all_metadata[subdir] = metadata
sorted(subdirs)
qs = [all_metadata[subdir] for subdir in subdirs]
return qs
class DownloadView(generic.DetailView):
def get(self, request, *args, **kwargs):
base_path = app_config.settings.upload_path
pk = kwargs.get('pk')
if hasattr(urllib, 'unquote_plus'):
subdir = urllib.unquote_plus(pk)
else:
subdir = urllib.parse.unquote_plus(pk)
path = os.path.join(base_path, subdir)
if not os.path.isdir(path):
raise Http404()
file_name = subdir
file_ext = '.zip'
mime_type = 'application/zip'
disposition_file_name = '{file_name}{file_ext}'.format(
file_name=file_name,
file_ext=file_ext,
)
raise Exception('Not Implemented yet')
file_obj = open(path, 'rb')
response = FileResponse(streaming_content=file_obj, content_type=mime_type)
disposition_header = 'attachment; filename="{}"'.format(disposition_file_name)
response['Content-Disposition'] = disposition_header
return response
class UploadView(generic.edit.FormView):
initial = {
# 'name': u'heinzel',
# 'email_address': 'heinzel@heinzelwelt.de',
# 'group': 'Alte Maschinen',
# 'title': u'Mein Beitrag',
# 'description': 'Foobar',
# 'accepted': True,
}
template_name = 'dav_submission/upload_form.html'
form_class = UploadForm
success_url = reverse_lazy('dav_submission:success')
def _sanitize_filename(self, input):
max_length = None
discard_chars = u''
allowed_chars = (u'abcdefghijklmnopqrstuvwxyz'
u'äöüß'
u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
u'ÄÖÜ'
u'0123456789'
u'._-')
non_allowed_substitute = u'_'
space_substitute = u'_'
if space_substitute is None:
space_substitute = non_allowed_substitute
r = ''
for c in input:
if c in discard_chars:
continue
elif allowed_chars is not None and c in allowed_chars:
r += c
elif allowed_chars is None and c.isalnum():
r += c
elif c.isspace():
r += space_substitute
else:
r += non_allowed_substitute
return r[:max_length]
def get_context_data(self, **kwargs):
c = super(UploadView, self).get_context_data(**kwargs)
c['show_upload_form'] = app_config.settings.enable_upload
return c
def form_valid(self, form):
base_path = app_config.settings.upload_path
subdir_format_str = u'{datetime}--{title}'
now = timezone.now()
subdir_format_kwargs = {'datetime': now.strftime('%Y-%m-%d--%H%M%S'),
'date': now.strftime('%Y-%m-%d'),
'time': now.strftime('%H-%M-%S'),
'title': form.cleaned_data['title']}
subdir_name = self._sanitize_filename(
subdir_format_str.format(**subdir_format_kwargs)
)
subdir_path = os.path.join(base_path, subdir_name)
if os.path.isdir(subdir_path):
message = _(u'Es gibt bereits einen Beitrag mit dem Titel "%(title)s".') % subdir_format_kwargs
messages.error(self.request, message)
form.add_error('title', message)
return self.render_to_response(self.get_context_data(form=form))
os.makedirs(subdir_path)
try:
metadata_format_str = u"""Absender: {name} <{email_address}>
Gruppe: {group}
Datum: {date} {time}
Titel: {title}
Beschreibung:
{description}
"""
metadata_format_kwargs = {
'date': timezone.localtime(now).strftime('%d.%m.%Y'),
'time': timezone.localtime(now).strftime('%H:%M:%S %Z'),
'name': form.cleaned_data['name'],
'email_address': form.cleaned_data['email_address'],
'group': form.cleaned_data['group'],
'title': form.cleaned_data['title'],
'description': form.cleaned_data['description'],
}
metadata = metadata_format_str.format(**metadata_format_kwargs)
metadata_file_name = app_config.settings.metadata_file_name
metadata_file_path = os.path.join(subdir_path, metadata_file_name)
with codecs.open(metadata_file_path, 'w', encoding='utf-8') as metadata_file:
metadata_file.write(metadata)
except Exception as e:
message = _(u'Jetzt ist irgendwas schief gelaufen.')
messages.error(self.request, message)
logger.error('dav_submission.views.UploadView.form_valid(): Catched Exception #2: %s', str(e))
return super(UploadView, self).form_valid(form)
try:
for input_file in form.files.getlist('files'):
file_name = self._sanitize_filename(input_file.name)
file_path = os.path.join(subdir_path, file_name)
if os.path.exists(file_path):
message = _(u'Die Datei %(name)s haben wir bereits.') % {'name': input_file.name}
messages.error(self.request, message)
continue
with open(file_path, 'wb+') as local_file:
for chunk in input_file.chunks():
local_file.write(chunk)
size = os.path.getsize(file_path)
if size > (1024 * 1024):
size_str = u'%s MiB' % ('%.3f' % (size / 1024.0 / 1024.0)).rstrip('0').rstrip('.')
elif size > 1024:
size_str = u'%s KiB' % ('%.3f' % (size / 1024.0)).rstrip('0').rstrip('.')
else:
size_str = u'%d Byte' % size
message = _(u'Datei erfolgreich hochgeladen: %(name)s (%(size)s)') % {'name': input_file.name,
'size': size_str}
messages.success(self.request, message)
except Exception as e:
message = _(u'Jetzt ist irgendwas schief gelaufen.')
messages.error(self.request, message)
logger.error('dav_submission.views.UploadView.form_valid(): Catched Exception #3: %s', str(e))
return super(UploadView, self).form_valid(form)
return super(UploadView, self).form_valid(form)
def post(self, request, *args, **kwargs):
if not app_config.settings.enable_upload:
raise PermissionDenied(_(u'Der Upload ist noch nicht freigeschaltet.'))
return super(UploadView, self).post(request, *args, **kwargs)
class SuccessView(generic.TemplateView):
template_name = 'dav_submission/success.html'