Allow unescaped invalid URL chars in non-stringed CSS url() for IE7 and below.

With changes by: Jacek Caban <jacek@codeweavers.com>

IE7 and below parse unescaped chars (such as whitespace) of urls without
string as part of the url, unlike IE8+ which are spec compliant. So
url(file:///C:/a b/blah.jpg) and url(C:\\c d\\foo.png) both work but only
in IE7 and below modes, without having to escape the space with backslash
or enclosing the url in quotes. The launcher for Imperiums: Greek Wars
depends on this.

Note that on native it's not spaces that are special, but rather it looks
up until the closing parenthesis (unless it is escaped via backslash). For
example, even unescaped newline is processed as part of url:

background:url(
); background-color: black;

...sets it to black, but:

background:url(
; background-color: black;

...does not since it's invalid.

For some reason escaping a space via backslash `\ ` does not function as it
should, but others do (such as parentheses). The game's launcher actually
uses Regex.Escape(text).Replace("\ ", " "), so this is probably something
special there.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
Gabriel Ivăncescu 2023-02-22 18:13:25 +02:00
parent 8856e41e92
commit 335da24386
No known key found for this signature in database
GPG Key ID: 4CEE4FF41CC69382
4 changed files with 31 additions and 5 deletions

View File

@ -180,6 +180,7 @@ nsHTMLDocument::nsHTMLDocument()
mType = eHTML;
mDefaultElementType = kNameSpaceID_XHTML;
mCompatMode = eCompatibility_NavQuirks;
mIECompatMode = 11;
}
nsHTMLDocument::~nsHTMLDocument()

View File

@ -54,6 +54,7 @@
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h"
#include "mozilla/dom/URL.h"
#include "gfxFontFamilyList.h"
#include "nsIDOMHTMLDocument.h"
using namespace mozilla;
using namespace mozilla::css;
@ -553,7 +554,7 @@ protected:
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mParser(aParser),
mOriginalScanner(aParser->mScanner),
mStringScanner(aStringToScan, 0),
mStringScanner(aStringToScan, 0, aParser->mIECompatMode),
mParserStateRestorer(aParser),
mErrorSuppresser(aParser)
{
@ -1360,6 +1361,9 @@ protected:
// Used for @import rules
css::Loader* mChildLoader; // not ref counted, it owns us
// Wine Gecko: Internet Explorer compatibility mode
uint32_t mIECompatMode;
// Any sheets we may reuse when parsing an @import.
css::LoaderReusableStyleSheets* mReusableSheets;
@ -1518,6 +1522,7 @@ CSSParserImpl::CSSParserImpl()
mScanner(nullptr),
mReporter(nullptr),
mChildLoader(nullptr),
mIECompatMode(11),
mReusableSheets(nullptr),
mSection(eCSSSection_Charset),
mNameSpaceMap(nullptr),
@ -1584,6 +1589,15 @@ nsresult
CSSParserImpl::SetChildLoader(mozilla::css::Loader* aChildLoader)
{
mChildLoader = aChildLoader; // not ref counted, it owns us
if (mChildLoader) {
nsIDocument *doc = mChildLoader->GetDocument();
if (doc) {
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(doc);
if (htmlDoc)
htmlDoc->GetIECompatMode(&mIECompatMode);
}
}
return NS_OK;
}
@ -1609,6 +1623,7 @@ CSSParserImpl::InitScanner(nsCSSScanner& aScanner,
mScanner = &aScanner;
mReporter = &aReporter;
mScanner->SetErrorReporter(mReporter);
mScanner->SetIECompatMode(mIECompatMode);
mBaseURI = aBaseURI;
mSheetURI = aSheetURI;

View File

@ -338,7 +338,7 @@ nsCSSToken::AppendToString(nsString& aBuffer) const
/* nsCSSScanner methods. */
nsCSSScanner::nsCSSScanner(const nsAString& aBuffer, uint32_t aLineNumber)
nsCSSScanner::nsCSSScanner(const nsAString& aBuffer, uint32_t aLineNumber, uint32_t aIECompatMode)
: mBuffer(aBuffer.BeginReading())
, mOffset(0)
, mCount(aBuffer.Length())
@ -354,6 +354,7 @@ nsCSSScanner::nsCSSScanner(const nsAString& aBuffer, uint32_t aLineNumber)
, mRecording(false)
, mSeenBadToken(false)
, mSeenVariableReference(false)
, mIECompatMode(aIECompatMode)
{
MOZ_COUNT_CTOR(nsCSSScanner);
}
@ -693,8 +694,12 @@ nsCSSScanner::GatherText(uint8_t aClass, nsString& aText)
for (;;) {
// Consume runs of unescaped characters in one go.
uint32_t n = mOffset;
while (n < mCount && IsOpenCharClass(mBuffer[n], aClass)) {
n++;
if (mIECompatMode > 7 || aClass != IS_URL_CHAR) {
while (n < mCount && IsOpenCharClass(mBuffer[n], aClass))
n++;
} else {
while (n < mCount && mBuffer[n] != ')' && mBuffer[n] != '\\')
n++;
}
if (n > mOffset) {
aText.Append(&mBuffer[mOffset], n - mOffset);

View File

@ -202,7 +202,7 @@ class nsCSSScanner {
// when the line number is unknown. The scanner does not take
// ownership of |aBuffer|, so the caller must be sure to keep it
// alive for the lifetime of the scanner.
nsCSSScanner(const nsAString& aBuffer, uint32_t aLineNumber);
nsCSSScanner(const nsAString& aBuffer, uint32_t aLineNumber, uint32_t aIECompatMode = 11);
~nsCSSScanner();
void SetErrorReporter(mozilla::css::ErrorReporter* aReporter) {
@ -287,6 +287,8 @@ class nsCSSScanner {
// Resets the scanner offset to a position saved by SavePosition.
void RestoreSavedPosition(const nsCSSScannerPosition& aState);
void SetIECompatMode(uint32_t aMode) { mIECompatMode = aMode; }
enum EOFCharacters {
eEOFCharacters_None = 0x0000,
@ -370,6 +372,9 @@ protected:
bool mRecording;
bool mSeenBadToken;
bool mSeenVariableReference;
// Wine Gecko: Internet Explorer compatibility mode
uint32_t mIECompatMode;
};
// Token for the grid-template-areas micro-syntax