Skip to content

Commit

Permalink
[BUG] alternative escape fix for pull/25
Browse files Browse the repository at this point in the history
[MNT] remove duplicate import
[MNT] version up to 0.13.0

Signed-off-by: mds-dwa <[email protected]>
  • Loading branch information
mds-dwa committed Dec 3, 2021
1 parent 77ebdb4 commit dfd0825
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 25 deletions.
19 changes: 11 additions & 8 deletions usdmanager/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

import logging
import re
from cgi import escape
from collections import defaultdict
from xml.sax.saxutils import escape, unescape

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

Expand Down Expand Up @@ -112,7 +112,7 @@ def compile(self):
self.regex = re.compile(
r'(?:[\'"@]+)' # 1 or more single quote, double quote, or at symbol.
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.
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.
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.
r'\.(?:'+'|'.join(exts)+r')' # followed by a period, then 1 of the acceptable file extensions
r'|\${[\w/${}:.-]+}' # One or more of these characters -- A-Za-z0-9_-/${}:. -- inside the variable curly brackets -- ${}
r')' # end group 1
Expand Down Expand Up @@ -182,15 +182,18 @@ def parse(self, nativeAbsPath, fileInfo, link):
# Search for multiple, non-overlapping links on each line.
offset = 0
for m in finditer(line):
linkPath = m.group(re_file_group)
# Since we had to escape all potential HTML-related characters before finding links, undo any replaced
# by escape if part of the linkPath itself. URIs may have & as part of the path for query parameters.
# We then have to re-escape the path before inserting it into HTML.
linkPath = unescape(m.group(re_file_group))
start = m.start(re_file_group)
end = m.end(re_file_group)
try:
href = parseMatch(m, linkPath, nativeAbsPath, fileInfo)
except ValueError:
# File doesn't exist or path cannot be resolved.
# Color it red.
href = '<span title="File not found" class="badLink">{}</span>'.format(linkPath)
href = '<span title="File not found" class="badLink">{}</span>'.format(escape(linkPath))
# Calculate difference in length between new link and original text so that we know where
# in the string to start the replacement when we have multiple matches in the same line.
line = line[:start + offset] + href + line[end + offset:]
Expand Down Expand Up @@ -254,13 +257,13 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):

# Make the HTML link.
if self.exists[fullPath]:
return '<a href="file://{}">{}</a>'.format(fullPath, linkPath)
elif '*' in linkPath or '&lt;UDIM&gt;' in linkPath or '.#.' in linkPath:
return '<a href="file://{}">{}</a>'.format(fullPath, escape(linkPath))
elif '*' in linkPath or '<UDIM>' in linkPath or '.#.' in linkPath:
# Create an orange link for files with wildcards in the path,
# designating zero or more files may exist.
return '<a title="Multiple files may exist" class="mayNotExist" href="file://{}">{}</a>'.format(
fullPath, linkPath)
return '<a title="File not found" class="badLink" href="file://{}">{}</a>'.format(fullPath, linkPath)
fullPath, escape(linkPath))
return '<a title="File not found" class="badLink" href="file://{}">{}</a>'.format(fullPath, escape(linkPath))

def parseLongLine(self, line):
""" Process a long line. Link parsing is skipped by default for lines over a certain length.
Expand Down
9 changes: 5 additions & 4 deletions usdmanager/parsers/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
Log file parser
"""
import re
from xml.sax.saxutils import escape

from Qt.QtCore import QFileInfo, Slot

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

# Make the HTML link.
if self.exists[fullPath]:
return '<a href="file://{}{}">{}</a>'.format(fullPath, queryStr, linkPath)
elif '*' in linkPath or '&lt;UDIM&gt;' in linkPath or '.#.' in linkPath:
return '<a href="file://{}{}">{}</a>'.format(fullPath, queryStr, escape(linkPath))
elif '*' in linkPath or '<UDIM>' in linkPath or '.#.' in linkPath:
# Create an orange link for files with wildcards in the path,
# designating zero or more files may exist.
return '<a title="Multiple files may exist" class="mayNotExist" href="file://{}{}">{}</a>'.format(
fullPath, queryStr, linkPath)
fullPath, queryStr, escape(linkPath))
return '<a title="File not found" class="badLink" href="file://{}{}">{}</a>'.format(
fullPath, queryStr, linkPath)
fullPath, queryStr, escape(linkPath))
27 changes: 17 additions & 10 deletions usdmanager/parsers/usd.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import logging
import re
from os.path import sep, splitext
from xml.sax.saxutils import escape, unescape

from Qt.QtCore import QFileInfo, Slot

Expand All @@ -45,9 +46,9 @@ def __init__(self, *args, **kwargs):
super(UsdAsciiParser, self).__init__(*args, **kwargs)
self.regex = None
self.usdArrayRegEx = re.compile(
"((?:\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.
"\s*(.*)\s*" # Everything inside the square brackets.
"(\].*)$" # Closing bracket to the end of the line.
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.
r"\s*(.*)\s*" # Everything inside the square brackets.
r"(\].*)$" # Closing bracket to the end of the line.
)

@Slot()
Expand Down Expand Up @@ -93,6 +94,10 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):
:Raises ValueError:
If path does not exist or cannot be resolved.
"""
# Since we had to escape all potential HTML-related characters before finding links, undo any replaced
# by escape if part of the linkPath itself. URIs may have & as part of the path for query parameters.
# We then have to re-escape the path before inserting it into HTML.
linkPath = unescape(linkPath)
expanded_path = utils.expandPath(
linkPath, nativeAbsPath,
self.sdf_format_args,
Expand All @@ -108,7 +113,7 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):
# Override any previously set sdf format args.
local_sdf_args = self.sdf_format_args.copy()
if match.group(3):
for kv in match.group(3).split("&amp;"):
for kv in match.group(3).split("&"):
k, v = kv.split("=", 1)
expanded_path = utils.expandPath(
v, nativeAbsPath, self.sdf_format_args,
Expand All @@ -131,22 +136,24 @@ def parseMatch(self, match, linkPath, nativeAbsPath, fileInfo):
# Make the HTML link.
if self.exists[fullPath]:
_, fullPathExt = splitext(fullPath)
if fullPathExt[1:] in USD_CRATE_EXTS or (fullPathExt[1:] in USD_AMBIGUOUS_EXTS and utils.isUsdCrate(fullPath)):
if fullPathExt[1:] in USD_CRATE_EXTS or (fullPathExt[1:] in USD_AMBIGUOUS_EXTS and
utils.isUsdCrate(fullPath)):
queryParams.insert(0, "binary=1")
return '<a class="binary" href="file://{}?{}">{}</a>'.format(fullPath, "&".join(queryParams), linkPath)
return '<a class="binary" href="file://{}?{}">{}</a>'.format(fullPath, "&".join(queryParams),
escape(linkPath))

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

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

def parseLongLine(self, line):
""" Process a long line. Link parsing is skipped, and long USD arrays are truncated in the middle.
Expand Down
3 changes: 1 addition & 2 deletions usdmanager/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,7 @@ def loadUiType(uiFile, sourceFile=None, className="DefaultWidgetClass"):
from io import StringIO
else:
from StringIO import StringIO
from Qt import QtWidgets


if not os.path.exists(uiFile) and not os.path.isabs(uiFile):
if sourceFile is None:
uiFile = resource_filename(__name__, uiFile)
Expand Down
2 changes: 1 addition & 1 deletion usdmanager/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
__version__ = '0.12.2'
__version__ = '0.13.0'

0 comments on commit dfd0825

Please sign in to comment.