From 9cb88506a1fac16f4f095d2d8c7a20f235b5ecb6 Mon Sep 17 00:00:00 2001 From: Bob G Date: Tue, 27 Oct 2026 13:50:43 -0700 Subject: [PATCH] Handle any separator style when resolving pre-built model asset paths (#132) prebuilt() only split render_asset on an escaped double backslash and then on '/', so paths using single backslashes (mesh\ftcommunityitems\x.nif) kept their directories in the file name. The LXFML lookup then failed and get_model returned 500. Extract the base name by splitting on any run of backslashes or forward slashes and lowercasing it. Also return 404 instead of an unusable string when a LOT has no render asset. Co-authored-by: bob-g-code <346622190+bob-g-code@users.noreply.github.com> --- app/properties.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/app/properties.py b/app/properties.py index f661f59..9809b30 100644 --- a/app/properties.py +++ b/app/properties.py @@ -1,3 +1,4 @@ +import re from flask import ( render_template, Blueprint, @@ -422,6 +423,17 @@ def decompress(data): pos += length return out +def render_asset_basename(render_asset): + """Return the lowercase file name without extension of a client asset path. + + render_asset paths in the cdclient mix separators: single backslashes + (mesh\\ftcommunityitems\\x.nif), escaped double backslashes, forward + slashes, or combinations of those, and mixed case. + """ + name = re.split(r"[\\/]+", render_asset.strip())[-1] + return name.split(".")[0].lower() + + def prebuilt(content, file_format, lod): # translate LOT to component id # we need to get a type of 2 for the render component to find the filename @@ -438,12 +450,10 @@ def prebuilt(content, file_format, lod): ) # if we have a valie filename, coerce it - if filename: - filename = filename[0].split("\\\\")[-1].lower().split(".")[0] - if "/" in filename: - filename = filename.split("/")[-1].lower() - else: - return f"No filename for LOT {content.lot}" + if filename and filename[0]: + filename = render_asset_basename(filename[0]) + if not filename: + abort(404) # if we just want the lxfml, fine t and return it lxfml = pathlib.Path(f'{current_app.config["CLIENT_LOCATION"]}res/BrickModels/{filename.split(".")[0]}.lxfml')