Skip to content

Commit dfd0825

Browse files
committed
[BUG] alternative escape fix for pull/25
[MNT] remove duplicate import [MNT] version up to 0.13.0 Signed-off-by: mds-dwa <[email protected]>
1 parent 77ebdb4 commit dfd0825

File tree

5 files changed

+35
-25
lines changed

5 files changed

+35
-25
lines changed

usdmanager/parser.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
import logging
2121
import re
22-
from cgi import escape
2322
from collections import defaultdict
23+
from xml.sax.saxutils import escape, unescape
2424

2525
from Qt.QtCore import QFile, QFileInfo, QObject, Signal, Slot
2626

@@ -112,7 +112,7 @@ def compile(self):
112112
self.regex = re.compile(
113113
r'(?:[\'"@]+)' # 1 or more single quote, double quote, or at symbol.
114114
r'(' # Group 1: Path. This is the main group we are looking for. Matches based on extension before the pipe, or variable after the pipe.
115-
r'[^\t\n\r\f\v\'"]*?' # 0 or more (greedy) non-whitespace characters (regular spaces are ok) and no quotes followed by a period, then 1 of the acceptable file extensions. NOTE: Backslash exclusion removed for Windows support; make sure this doesn't negatively affect other systems.
115+
r'[^\t\n\r\f\v\'"]*?' # 0 or more (greedy) non-whitespace characters (regular spaces are ok) and no quotes followed by a period, then 1 of the acceptable file extensions.
116116
r'\.(?:'+'|'.join(exts)+r')' # followed by a period, then 1 of the acceptable file extensions
117117
r'|\${[\w/${}:.-]+}' # One or more of these characters -- A-Za-z0-9_-/${}:. -- inside the variable curly brackets -- ${}
118118
r')' # end group 1
@@ -182,15 +182,18 @@ def parse(self, nativeAbsPath, fileInfo, link):
182182
# Search for multiple, non-overlapping links on each line.
183183
offset = 0
184184
for m in finditer(line):
185-
linkPath = m.group(re_file_group)
185+
# Since we had to escape all potential HTML-related characters before finding links, undo any replaced
186+
# by escape if part of the linkPath itself. URIs may have & as part of the path for query parameters.
187+
# We then have to re-escape the path before inserting it into HTML.
188+
linkPath = unescape(m.group(re_file_group))
186189
start = m.start(re_file_group)
187190
end = m.end(re_file_group)
188191
try:
189192
href = parseMatch(m, linkPath, nativeAbsPath, fileInfo)
190193
except ValueError:
191194
# File doesn't exist or path cannot be resolved.
192195
# Color it red.
193-
href = '<span title="File not found" class="badLink">{}</span>'.format(linkPath)
196+
href = '<span title="File not found" class="badLink">{}</span>'.format(escape(linkPath))
194197
# Calculate difference in length between new link and original text so that we know where
195198
# in the string to start the replacement when we have multiple matches in the same line.
196199
line = line[:start + offset] + href + line[end + offset:]
@@ -254,13 +257,13 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):
254257

255258
# Make the HTML link.
256259
if self.exists[fullPath]:
257-
return '<a href="file://{}">{}</a>'.format(fullPath, linkPath)
258-
elif '*' in linkPath or '&lt;UDIM&gt;' in linkPath or '.#.' in linkPath:
260+
return '<a href="file://{}">{}</a>'.format(fullPath, escape(linkPath))
261+
elif '*' in linkPath or '<UDIM>' in linkPath or '.#.' in linkPath:
259262
# Create an orange link for files with wildcards in the path,
260263
# designating zero or more files may exist.
261264
return '<a title="Multiple files may exist" class="mayNotExist" href="file://{}">{}</a>'.format(
262-
fullPath, linkPath)
263-
return '<a title="File not found" class="badLink" href="file://{}">{}</a>'.format(fullPath, linkPath)
265+
fullPath, escape(linkPath))
266+
return '<a title="File not found" class="badLink" href="file://{}">{}</a>'.format(fullPath, escape(linkPath))
264267

265268
def parseLongLine(self, line):
266269
""" Process a long line. Link parsing is skipped by default for lines over a certain length.

usdmanager/parsers/log.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
Log file parser
1818
"""
1919
import re
20+
from xml.sax.saxutils import escape
2021

2122
from Qt.QtCore import QFileInfo, Slot
2223

@@ -91,11 +92,11 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):
9192

9293
# Make the HTML link.
9394
if self.exists[fullPath]:
94-
return '<a href="file://{}{}">{}</a>'.format(fullPath, queryStr, linkPath)
95-
elif '*' in linkPath or '&lt;UDIM&gt;' in linkPath or '.#.' in linkPath:
95+
return '<a href="file://{}{}">{}</a>'.format(fullPath, queryStr, escape(linkPath))
96+
elif '*' in linkPath or '<UDIM>' in linkPath or '.#.' in linkPath:
9697
# Create an orange link for files with wildcards in the path,
9798
# designating zero or more files may exist.
9899
return '<a title="Multiple files may exist" class="mayNotExist" href="file://{}{}">{}</a>'.format(
99-
fullPath, queryStr, linkPath)
100+
fullPath, queryStr, escape(linkPath))
100101
return '<a title="File not found" class="badLink" href="file://{}{}">{}</a>'.format(
101-
fullPath, queryStr, linkPath)
102+
fullPath, queryStr, escape(linkPath))

usdmanager/parsers/usd.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import logging
2020
import re
2121
from os.path import sep, splitext
22+
from xml.sax.saxutils import escape, unescape
2223

2324
from Qt.QtCore import QFileInfo, Slot
2425

@@ -45,9 +46,9 @@ def __init__(self, *args, **kwargs):
4546
super(UsdAsciiParser, self).__init__(*args, **kwargs)
4647
self.regex = None
4748
self.usdArrayRegEx = re.compile(
48-
"((?:\s*(?:\w+\s+)?\w+\[\]\s+[\w:]+\s*=|\s*\d+:)\s*\[)" # Array attribute definition and equal sign, or a frame number and colon, plus the opening bracket.
49-
"\s*(.*)\s*" # Everything inside the square brackets.
50-
"(\].*)$" # Closing bracket to the end of the line.
49+
r"((?:\s*(?:\w+\s+)?\w+\[\]\s+[\w:]+\s*=|\s*\d+:)\s*\[)" # Array attribute definition and equal sign, or a frame number and colon, plus the opening bracket.
50+
r"\s*(.*)\s*" # Everything inside the square brackets.
51+
r"(\].*)$" # Closing bracket to the end of the line.
5152
)
5253

5354
@Slot()
@@ -93,6 +94,10 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):
9394
:Raises ValueError:
9495
If path does not exist or cannot be resolved.
9596
"""
97+
# Since we had to escape all potential HTML-related characters before finding links, undo any replaced
98+
# by escape if part of the linkPath itself. URIs may have & as part of the path for query parameters.
99+
# We then have to re-escape the path before inserting it into HTML.
100+
linkPath = unescape(linkPath)
96101
expanded_path = utils.expandPath(
97102
linkPath, nativeAbsPath,
98103
self.sdf_format_args,
@@ -108,7 +113,7 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):
108113
# Override any previously set sdf format args.
109114
local_sdf_args = self.sdf_format_args.copy()
110115
if match.group(3):
111-
for kv in match.group(3).split("&amp;"):
116+
for kv in match.group(3).split("&"):
112117
k, v = kv.split("=", 1)
113118
expanded_path = utils.expandPath(
114119
v, nativeAbsPath, self.sdf_format_args,
@@ -131,22 +136,24 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):
131136
# Make the HTML link.
132137
if self.exists[fullPath]:
133138
_, fullPathExt = splitext(fullPath)
134-
if fullPathExt[1:] in USD_CRATE_EXTS or (fullPathExt[1:] in USD_AMBIGUOUS_EXTS and utils.isUsdCrate(fullPath)):
139+
if fullPathExt[1:] in USD_CRATE_EXTS or (fullPathExt[1:] in USD_AMBIGUOUS_EXTS and
140+
utils.isUsdCrate(fullPath)):
135141
queryParams.insert(0, "binary=1")
136-
return '<a class="binary" href="file://{}?{}">{}</a>'.format(fullPath, "&".join(queryParams), linkPath)
142+
return '<a class="binary" href="file://{}?{}">{}</a>'.format(fullPath, "&".join(queryParams),
143+
escape(linkPath))
137144

138145
queryStr = "?" + "&".join(queryParams) if queryParams else ""
139-
return '<a href="file://{}{}">{}</a>'.format(fullPath, queryStr, linkPath)
140-
elif '*' in linkPath or '&lt;UDIM&gt;' in linkPath or '.#.' in linkPath:
146+
return '<a href="file://{}{}">{}</a>'.format(fullPath, queryStr, escape(linkPath))
147+
elif '*' in linkPath or '<UDIM>' in linkPath or '.#.' in linkPath:
141148
# Create an orange link for files with wildcards in the path,
142149
# designating zero or more files may exist.
143150
queryStr = "?" + "&".join(queryParams) if queryParams else ""
144151
return '<a title="Multiple files may exist" class="mayNotExist" href="file://{}{}">{}</a>'.format(
145-
fullPath, queryStr, linkPath)
152+
fullPath, queryStr, escape(linkPath))
146153

147154
queryStr = "?" + "&".join(queryParams) if queryParams else ""
148155
return '<a title="File not found" class="badLink" href="file://{}{}">{}</a>'.format(
149-
fullPath, queryStr, linkPath)
156+
fullPath, queryStr, escape(linkPath))
150157

151158
def parseLongLine(self, line):
152159
""" Process a long line. Link parsing is skipped, and long USD arrays are truncated in the middle.

usdmanager/utils.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,7 @@ def loadUiType(uiFile, sourceFile=None, className="DefaultWidgetClass"):
476476
from io import StringIO
477477
else:
478478
from StringIO import StringIO
479-
from Qt import QtWidgets
480-
479+
481480
if not os.path.exists(uiFile) and not os.path.isabs(uiFile):
482481
if sourceFile is None:
483482
uiFile = resource_filename(__name__, uiFile)

usdmanager/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
#
16-
__version__ = '0.12.2'
16+
__version__ = '0.13.0'

0 commit comments

Comments
 (0)