troggle-unchained/core/views/drawings.py

118 lines
4.6 KiB
Python

import os
import re
import stat
from pathlib import Path
from urllib.parse import unquote as urlunquote
from urllib.parse import urljoin
from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render
from troggle.core.models.survex import DrawingFile
from troggle.core.views.expo import getmimetype
# import parsers.surveys
"""Some of these views serve files as binary blobs, and simply set the mime type based on the file extension,
as does the urls.py dispatcher which sends them here. Here they should actually have the filetype checked
by looking inside the file before being served.
"""
todo = """- Need to check if invalid query string is invalid, or produces multiple replies
and render a user-friendly error page.
"""
def unescape(input):
"""These look like HTML entities, but they are not. They are tunnel-specific encodings"""
codes = {
"&space;": " ",
""": '"',
"&tab;": "\t",
"&backslash;": "\\",
"&newline;": "\n|\t",
"&apostrophe": "'",
}
for c in codes:
# print(c, codes[c])
input = input.replace(c, codes[c])
return input
def dwgallfiles(request):
"""Report on all the drawing files in the system. These were loaded by parsing the entire directory tree"""
dwgfiles = DrawingFile.objects.all()
return render(request, "dwgfiles.html", {"dwgfiles": dwgfiles, "settings": settings})
def dwgfilesingle(request, path):
"""sends a single binary file to the user. It could be an old PNG, PDF or SVG
not just Tunnel or Therion
The db records created on datbase reset import are not used when we look for an individual drawing, only
collections of them.
Note the infelicity that this will deliver files that exist, but are hidden on the previous
webpage /dwgupload/... if the user types the filename into the browser bar. Could be a problem?
Should we validate using uploads.py dwgvaliddisp() here too?
"""
tfile = Path(settings.DRAWINGS_DATA, path.replace(":", "#"))
if not tfile.is_file():
message = f"Drawing file not found in filesystem at '{path}' \n\t\tMaybe a new dataimport needs to be done to get up to date."
return render(request, "errors/generic.html", {"message": message})
if Path(tfile).suffix in [
".xml"
]: # tunnel files are usually 'us-ascii' (!). And may not close all XML tags properly either.
for encoding in ["us-ascii", "iso-8859-1", "utf-8"]:
try:
# print(f'attempting {encoding} for {tfile}')
with open(tfile, encoding=encoding, errors="strict") as f:
print(f"- before reading any {encoding}")
lines = f.readlines()
# print(f'- finished reading {encoding}')
clean = []
for l in lines:
clean.append(unescape(l)) # deals with strangely embedded survex file
# print(f'- Cleaned and stripped.')
try:
return HttpResponse(content=clean, content_type="text/xml")
except:
return HttpResponse(
content=f"Render fail for this file: {tfile} Please report to a nerd. Probably Julian's fault."
)
except:
print(f"! Exception when reading {encoding}")
continue
print(f"! None of those encodings worked for {tfile}")
try:
return HttpResponse(content=open(tfile, errors="ignore"), content_type=getmimetype(tfile))
except:
return HttpResponse(
content=f"Unable to understand the encoding for this file: {tfile} Please report to a nerd."
)
if Path(tfile).suffix in ["th2", ".th"]:
try:
return HttpResponse(content=open(tfile, errors="strict"), content_type="text/txt") # default utf-8
except:
return HttpResponse(
content=f"Unable to understand the encoding for this file: {tfile} Please report to a nerd."
)
else: # SVG, JPG etc
try:
return HttpResponse(content=open(tfile, mode="rb"), content_type=getmimetype(tfile)) # default utf-8
except:
try:
return HttpResponse(content=open(tfile, mode="rb"))
except:
return HttpResponse(
content=f"Unable to understand the encoding '{getmimetype(tfile)}' for this file: {tfile} Note that Apache will do its own thing here. Please report to a nerd."
)