Sanitize the URL further by removing leading slashes and any duplicated ones

This commit is contained in:
Dale Glass 2020-09-23 23:33:22 +02:00
parent b243d382fc
commit 1d58ac4d79
2 changed files with 22 additions and 4 deletions

View file

@ -49,13 +49,32 @@ QUrl ExternalResource::getQUrl(Bucket bucket, const QUrl& path) {
base = _bucketBases[bucket];
}
QUrl merged = base.resolved(path).adjusted(QUrl::NormalizePathSegments);
QUrl filteredPath = path;
QString pathQString = filteredPath.path();
// De-duplicate URL separators, since S3 doesn't actually have subdirectories, and treats a '/' as a part
// of the filename. This means that "/dir/file.txt" and "/dir//file.txt" are not equivalent on S3.
while(pathQString.contains("//")) {
pathQString = pathQString.replace("//", "/");
}
// If a path starts with a / it would have the effect of overriding any path specified in the bucket.
// We remove it, ensuring that getQUrl(Bucket.Assets, "/file.txt") and getQUrl(Bucket.Assets, "file.txt")
// are equivalent.
if (pathQString.startsWith("/")) {
pathQString.remove(0,1);
}
filteredPath.setPath(pathQString);
QUrl merged = base.resolved(filteredPath).adjusted(QUrl::NormalizePathSegments);
if ( merged.isValid() ) {
qCDebug(external_resource) << "External resource resolved to " << merged;
} else {
qCCritical(external_resource) << "External resource resolved to invalid URL " << merged << "; Error "
<< merged.errorString() << "; base = " << base << "; path = " << path;
<< merged.errorString() << "; base = " << base << "; path = " << path
<< "; filtered path = " << filteredPath;
}
return merged;

View file

@ -693,8 +693,7 @@ public:
* @param {string} path - The path within the external resource bucket where the asset is located.
* <p>Normally, this should start with a path or filename to be appended to the bucket URL.
* Alternatively, it can be a relative path starting with <code>./</code> or <code>../</code>, to navigate within the
* resource bucket's URL. Or it can be an absolute path starting with <code>/</code>, in which case the bucket's path
* is discarded when calculating the asset's URL.</p>
* resource bucket's URL.</p>
* @Returns {string} The URL of an external asset.
* @example <caption>Report the URL of a default particle.</caption>
* print(Script.getExternalPath(Script.ExternalPaths.Assets, "Bazaar/Assets/Textures/Defaults/Interface/default_particle.png"));