From 5a9c36b43a0d47e8c4c8b1e365d9bf5bfffc552c Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Sun, 30 Jan 2005 18:01:57 +0000 Subject: [PATCH] Getting the selector text should properly escape and quote attribute value strings. Bug 142648, patch by Daniel Kraft , r=dbaron, sr=bzbarsky. --- layout/mathml/base/src/nsMathMLFrame.cpp | 11 +++---- layout/style/nsCSSStyleRule.cpp | 37 +++++++++++++----------- layout/style/nsStyleUtil.cpp | 35 ++++++++++++++++++++++ layout/style/nsStyleUtil.h | 3 ++ 4 files changed, 64 insertions(+), 22 deletions(-) diff --git a/layout/mathml/base/src/nsMathMLFrame.cpp b/layout/mathml/base/src/nsMathMLFrame.cpp index 7be0f906f6c..28e4d68e791 100644 --- a/layout/mathml/base/src/nsMathMLFrame.cpp +++ b/layout/mathml/base/src/nsMathMLFrame.cpp @@ -56,6 +56,7 @@ #include "nsContentCID.h" #include "nsAutoPtr.h" #include "nsStyleSet.h" +#include "nsStyleUtil.h" static NS_DEFINE_CID(kCSSStyleSheetCID, NS_CSS_STYLESHEET_CID); @@ -612,6 +613,8 @@ nsMathMLFrame::MapAttributesIntoCSS(nsPresContext* aPresContext, aContent->GetAttr(nameSpaceID, attrAtom, attrValue); if (attrValue.IsEmpty()) continue; + nsAutoString escapedAttrValue; + nsStyleUtil::EscapeCSSString(attrValue, escapedAttrValue); // don't add rules that are already in mathml.css // (this will also clean up whitespace before units - see bug 125303) @@ -633,7 +636,7 @@ nsMathMLFrame::MapAttributesIntoCSS(nsPresContext* aPresContext, // make a style rule that maps to the equivalent CSS property nsAutoString cssRule; cssRule.Assign(NS_LITERAL_STRING("[") + attrName + - NS_LITERAL_STRING("='") + attrValue + + NS_LITERAL_STRING("='") + escapedAttrValue + NS_LITERAL_STRING("']{") + cssProperty + NS_LITERAL_STRING("}")); if (!sheet) { @@ -657,12 +660,10 @@ nsMathMLFrame::MapAttributesIntoCSS(nsPresContext* aPresContext, } // check for duplicate, if a similar rule is already there, don't bother to add another one - // XXX bug 142648 - GetSourceSelectorText is in the format *[color=blue] (i.e., no quotes...) - // XXXrbs need to keep this in sync with the fix for bug 142648 nsAutoString selector; selector.Assign(NS_LITERAL_STRING("*[") + attrName + - NS_LITERAL_STRING("=") + attrValue + - NS_LITERAL_STRING("]")); + NS_LITERAL_STRING("=\"") + escapedAttrValue + + NS_LITERAL_STRING("\"]")); PRInt32 k, count; cssSheet->StyleRuleCount(count); for (k = 0; k < count; ++k) { diff --git a/layout/style/nsCSSStyleRule.cpp b/layout/style/nsCSSStyleRule.cpp index 5baf949f343..08e22ddcd5c 100644 --- a/layout/style/nsCSSStyleRule.cpp +++ b/layout/style/nsCSSStyleRule.cpp @@ -52,6 +52,7 @@ #include "nsCRT.h" #include "nsString.h" #include "nsStyleConsts.h" +#include "nsStyleUtil.h" #include "nsHTMLAtoms.h" #include "nsUnitConversion.h" #include "nsIFontMetrics.h" @@ -69,13 +70,15 @@ #include "nsContentUtils.h" #include "nsContentErrors.h" +/* ************************************************************************** */ + // -- nsCSSSelector ------------------------------- #define NS_IF_COPY(dest,source,type) \ - if (nsnull != source) dest = new type(*(source)) + if (source) dest = new type(*(source)) #define NS_IF_DELETE(ptr) \ - if (nsnull != ptr) { delete ptr; ptr = nsnull; } + if (ptr) { delete ptr; ptr = nsnull; } #define NS_IF_NEGATED_START(bool,str) \ if (bool) { str.AppendLiteral(":not("); } @@ -681,27 +684,27 @@ void nsCSSSelector::ToStringInternal(nsAString& aString, list->mAttr->ToString(temp); aString.Append(temp); // Append the function - if (list->mFunction == NS_ATTR_FUNC_EQUALS) { - aString.Append(PRUnichar('=')); - } else if (list->mFunction == NS_ATTR_FUNC_INCLUDES) { + if (list->mFunction == NS_ATTR_FUNC_INCLUDES) aString.Append(PRUnichar('~')); - aString.Append(PRUnichar('=')); - } else if (list->mFunction == NS_ATTR_FUNC_DASHMATCH) { + else if (list->mFunction == NS_ATTR_FUNC_DASHMATCH) aString.Append(PRUnichar('|')); - aString.Append(PRUnichar('=')); - } else if (list->mFunction == NS_ATTR_FUNC_BEGINSMATCH) { + else if (list->mFunction == NS_ATTR_FUNC_BEGINSMATCH) aString.Append(PRUnichar('^')); - aString.Append(PRUnichar('=')); - } else if (list->mFunction == NS_ATTR_FUNC_ENDSMATCH) { + else if (list->mFunction == NS_ATTR_FUNC_ENDSMATCH) aString.Append(PRUnichar('$')); - aString.Append(PRUnichar('=')); - } else if (list->mFunction == NS_ATTR_FUNC_CONTAINSMATCH) { + else if (list->mFunction == NS_ATTR_FUNC_CONTAINSMATCH) aString.Append(PRUnichar('*')); - aString.Append(PRUnichar('=')); - } + + aString.Append(PRUnichar('=')); + // Append the value - aString.Append(list->mValue); - aString.Append(PRUnichar(']')); + nsAutoString escaped; + nsStyleUtil::EscapeCSSString(list->mValue, escaped); + + aString.Append(PRUnichar('\"')); + aString.Append(escaped); + aString.AppendLiteral("\"]"); + NS_IF_NEGATED_END(aIsNegated, aString) list = list->mNext; } diff --git a/layout/style/nsStyleUtil.cpp b/layout/style/nsStyleUtil.cpp index e66f27335af..0a447bbe369 100644 --- a/layout/style/nsStyleUtil.cpp +++ b/layout/style/nsStyleUtil.cpp @@ -51,6 +51,7 @@ #include "nsNetUtil.h" #include "nsReadableUtils.h" #include "nsContentUtils.h" +#include "nsTextFormatter.h" // XXX This is here because nsCachedStyleData is accessed outside of // the content module; e.g., by nsCSSFrameConstructor. @@ -529,3 +530,37 @@ PRBool nsStyleUtil::DashMatchCompare(const nsAString& aAttributeValue, } return result; } + +void nsStyleUtil::EscapeCSSString(const nsString& aString, nsAString& aReturn) +{ + aReturn.Truncate(); + + const nsString::char_type* in = aString.get(); + const nsString::char_type* const end = in + aString.Length(); + for (; in != end; in++) + { + if (*in < 0x20) + { + // Escape all characters below 0x20 numerically. + + /* + This is the buffer into which snprintf should write. As the hex. value is, + for numbers below 0x20, max. 2 characters long, we don't need more than 5 + characters ("\XX "+NUL). + */ + PRUnichar buf[5]; + nsTextFormatter::snprintf(buf, NS_ARRAY_LENGTH(buf), NS_LITERAL_STRING("\\%hX ").get(), *in); + aReturn.Append(buf); + + } else switch (*in) { + // Special characters which should be escaped: Quotes and backslash + case '\\': + case '\"': + case '\'': + aReturn.Append(PRUnichar('\\')); + // And now, after the eventual escaping character, the actual one. + default: + aReturn.Append(PRUnichar(*in)); + } + } +} diff --git a/layout/style/nsStyleUtil.h b/layout/style/nsStyleUtil.h index 39f139de1ec..5653416ca26 100644 --- a/layout/style/nsStyleUtil.h +++ b/layout/style/nsStyleUtil.h @@ -75,6 +75,9 @@ public: static PRBool DashMatchCompare(const nsAString& aAttributeValue, const nsAString& aSelectorValue, const nsStringComparator& aComparator); + + static void EscapeCSSString(const nsString& aString, nsAString& aReturn); + };