44
55import csv
66import datetime
7- import glob
87import io
98import itertools
109import json
2019from collections import OrderedDict , Counter , deque , defaultdict , namedtuple
2120from functools import partialmethod
2221import jsonschema
22+ from pathlib import Path
2323from urllib .parse import parse_qs , unquote , urlencode , urlsplit , urlunsplit
2424from tempfile import mkstemp
2525from wsgiref .handlers import format_date_time
@@ -250,40 +250,49 @@ def _get_materials_doc(meeting, name):
250250
251251@cache_page (1 * 60 )
252252def materials_document (request , document , num = None , ext = None ):
253- meeting = get_meeting (num ,type_in = ['ietf' ,'interim' ])
253+ """Materials document view
254+
255+ :param request: Django request
256+ :param document: Name of document without an extension
257+ :param num: meeting number
258+ :param ext: extension including preceding '.'
259+ """
260+ meeting = get_meeting (num , type_in = ["ietf" , "interim" ])
254261 num = meeting .number
255262 try :
256263 doc , rev = _get_materials_doc (meeting = meeting , name = document )
257264 except Document .DoesNotExist :
258265 raise Http404 ("No such document for meeting %s" % num )
259266
260267 if not rev :
261- filename = doc .get_file_name ()
268+ filename = Path ( doc .get_file_name () )
262269 else :
263- filename = os . path . join (doc .get_file_path (), document )
270+ filename = Path (doc .get_file_path ()) / document
264271 if ext :
265- if not filename .endswith (ext ):
266- name , _ = os .path .splitext (filename )
267- filename = name + ext
268- else :
269- filenames = glob .glob (filename + '.*' )
270- if filenames :
271- filename = filenames [0 ]
272- _ , basename = os .path .split (filename )
273- if not os .path .exists (filename ):
274- raise Http404 ("File not found: %s" % filename )
272+ filename = filename .with_suffix (ext )
273+ elif filename .suffix == "" :
274+ # If we don't already have an extension, try to add one
275+ ext_choices = {
276+ # Construct a map from suffix to full filename
277+ fn .suffix : fn
278+ for fn in sorted (filename .parent .glob (filename .stem + ".*" ))
279+ }
280+ if len (ext_choices ) > 0 :
281+ if ".pdf" in ext_choices :
282+ filename = ext_choices [".pdf" ]
283+ else :
284+ filename = list (ext_choices .values ())[0 ]
285+ if not filename .exists ():
286+ raise Http404 (f"File not found: { filename } " )
275287
276288 old_proceedings_format = meeting .number .isdigit () and int (meeting .number ) <= 96
277289 if settings .MEETING_MATERIALS_SERVE_LOCALLY or old_proceedings_format :
278- with io .open (filename , 'rb' ) as file :
279- bytes = file .read ()
280-
290+ bytes = filename .read_bytes ()
281291 mtype , chset = get_mime_type (bytes )
282292 content_type = "%s; charset=%s" % (mtype , chset )
283293
284- file_ext = os .path .splitext (filename )
285- if len (file_ext ) == 2 and file_ext [1 ] == '.md' and mtype == 'text/plain' :
286- sorted_accept = sort_accept_tuple (request .META .get ('HTTP_ACCEPT' ))
294+ if filename .suffix == ".md" and mtype == "text/plain" :
295+ sorted_accept = sort_accept_tuple (request .META .get ("HTTP_ACCEPT" ))
287296 for atype in sorted_accept :
288297 if atype [0 ] == "text/markdown" :
289298 content_type = content_type .replace ("plain" , "markdown" , 1 )
@@ -293,7 +302,7 @@ def materials_document(request, document, num=None, ext=None):
293302 "minimal.html" ,
294303 {
295304 "content" : markdown .markdown (bytes .decode (encoding = chset )),
296- "title" : basename ,
305+ "title" : filename . name ,
297306 },
298307 )
299308 content_type = content_type .replace ("plain" , "html" , 1 )
@@ -302,11 +311,12 @@ def materials_document(request, document, num=None, ext=None):
302311 break
303312
304313 response = HttpResponse (bytes , content_type = content_type )
305- response [' Content-Disposition' ] = 'inline; filename="%s"' % basename
314+ response [" Content-Disposition" ] = f 'inline; filename="{ filename . name } "'
306315 return response
307316 else :
308317 return HttpResponseRedirect (redirect_to = doc .get_href (meeting = meeting ))
309318
319+
310320@login_required
311321def materials_editable_groups (request , num = None ):
312322 meeting = get_meeting (num )
0 commit comments