Skip to content

Commit de4b565

Browse files
committed
Preserve case for url() argument in css
DEVSIX-1452 Autoported commit. Original commit hash: [5c50c645]
1 parent 666e1bb commit de4b565

File tree

4 files changed

+94
-39
lines changed

4 files changed

+94
-39
lines changed

itext.tests/itext.html2pdf.tests/itext/html2pdf/css/util/CssUtilTest.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,18 @@ public virtual void NormalizeProperty() {
9595
NUnit.Framework.Assert.AreEqual("rgba(255,255,255,0.2)", CssUtils.NormalizeCssProperty("rgba( 255, 255 , 255 ,0.2 )"
9696
));
9797
}
98+
99+
[NUnit.Framework.Test]
100+
public virtual void NormalizeUrlTest() {
101+
NUnit.Framework.Assert.AreEqual("url(data:application/font-woff;base64,2CBPCRXmgywtV1t4oWwjBju0kqkvfhPs0cYdMgFtDSY5uL7MIGT5wiGs078HrvBHekp0Yf=)"
102+
, CssUtils.NormalizeCssProperty("url(data:application/font-woff;base64,2CBPCRXmgywtV1t4oWwjBju0kqkvfhPs0cYdMgFtDSY5uL7MIGT5wiGs078HrvBHekp0Yf=)"
103+
));
104+
NUnit.Framework.Assert.AreEqual("url(\"quoted Url\")", CssUtils.NormalizeCssProperty(" url( \"quoted Url\")"
105+
));
106+
NUnit.Framework.Assert.AreEqual("url('quoted Url')", CssUtils.NormalizeCssProperty(" url( 'quoted Url')"
107+
));
108+
NUnit.Framework.Assert.AreEqual("url(haveEscapedEndBracket\\))", CssUtils.NormalizeCssProperty("url( haveEscapedEndBracket\\) )"
109+
));
110+
}
98111
}
99112
}

itext/itext.html2pdf/itext/html2pdf/LogMessageConstant.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ public sealed class LogMessageConstant {
149149
/// <summary>The Constant UNKNOWN_MARGIN_BOX_CHILD.</summary>
150150
public const String UNKNOWN_MARGIN_BOX_CHILD = "Unknown margin box child";
151151

152+
public const String URL_IS_NOT_CLOSED_IN_CSS_EXPRESSION = "url function is not properly closed in expression:{0}";
153+
154+
public const String URL_IS_EMPTY_IN_CSS_EXPRESSION = "url function is empty in expression:{0}";
155+
152156
/// <summary>The Constant WAS_NOT_ABLE_TO_DEFINE_BACKGROUND_CSS_SHORTHAND_PROPERTIES.</summary>
153157
public const String WAS_NOT_ABLE_TO_DEFINE_BACKGROUND_CSS_SHORTHAND_PROPERTIES = "Was not able to define one of the background CSS shorthand properties: {0}";
154158

itext/itext.html2pdf/itext/html2pdf/css/util/CssPropertyNormalizer.cs

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -52,67 +52,105 @@ internal class CssPropertyNormalizer {
5252
/// <param name="str">the property</param>
5353
/// <returns>the normalized property</returns>
5454
public static String Normalize(String str) {
55-
StringBuilder buffer = new StringBuilder();
56-
int segmentStart = 0;
57-
for (int i = 0; i < str.Length; ++i) {
55+
StringBuilder sb = new StringBuilder();
56+
bool isWhitespace = false;
57+
int i = 0;
58+
while (i < str.Length) {
5859
if (str[i] == '\\') {
60+
sb.Append(str[i]);
5961
++i;
60-
}
61-
else {
62-
if (str[i] == '\'' || str[i] == '"') {
63-
AppendAndFormatSegment(buffer, str, segmentStart, i + 1);
64-
segmentStart = i = AppendQuoteContent(buffer, str, i + 1, str[i]);
62+
if (i < str.Length) {
63+
sb.Append(str[i]);
64+
++i;
6565
}
6666
}
67-
}
68-
if (segmentStart < str.Length) {
69-
AppendAndFormatSegment(buffer, str, segmentStart, str.Length);
70-
}
71-
return buffer.ToString();
72-
}
73-
74-
/// <summary>Appends and formats a segment.</summary>
75-
/// <param name="buffer">the current buffer</param>
76-
/// <param name="source">a source</param>
77-
/// <param name="start">where to start in the source</param>
78-
/// <param name="end">where to end in the source</param>
79-
private static void AppendAndFormatSegment(StringBuilder buffer, String source, int start, int end) {
80-
String[] parts = iText.IO.Util.StringUtil.Split(source.JSubstring(start, end), "\\s");
81-
StringBuilder sb = new StringBuilder();
82-
foreach (String part in parts) {
83-
if (part.Length > 0) {
84-
if (sb.Length > 0 && !TrimSpaceAfter(sb[sb.Length - 1]) && !TrimSpaceBefore(part[0])) {
85-
sb.Append(" ");
86-
}
87-
// Do not make base64 data lowercase, function name only
88-
if (part.Matches("^[uU][rR][lL]\\(.+\\)") && CssUtils.IsBase64Data(part.JSubstring(4, part.Length - 1))) {
89-
sb.Append(part.JSubstring(0, 3).ToLowerInvariant()).Append(part.Substring(3));
67+
else {
68+
if (iText.IO.Util.TextUtil.IsWhiteSpace(str[i])) {
69+
isWhitespace = true;
70+
++i;
9071
}
9172
else {
92-
sb.Append(part.ToLowerInvariant());
73+
if (isWhitespace) {
74+
if (sb.Length > 0 && !TrimSpaceAfter(sb[sb.Length - 1]) && !TrimSpaceBefore(str[i])) {
75+
sb.Append(" ");
76+
}
77+
isWhitespace = false;
78+
}
79+
if (str[i] == '\'' || str[i] == '"') {
80+
i = AppendQuotedString(sb, str, i);
81+
}
82+
else {
83+
if ((str[i] == 'u' || str[i] == 'U') && str.Substring(i).Matches("^[uU][rR][lL]\\(.*?")) {
84+
sb.Append(str.JSubstring(i, i + 4).ToLowerInvariant());
85+
i = AppendUrlContent(sb, str, i + 4);
86+
}
87+
else {
88+
sb.Append(char.ToLower(str[i]));
89+
++i;
90+
}
91+
}
9392
}
9493
}
9594
}
96-
buffer.Append(sb);
95+
return sb.ToString();
9796
}
9897

99-
/// <summary>Appends quoted content.</summary>
98+
/// <summary>Appends quoted string.</summary>
10099
/// <param name="buffer">the current buffer</param>
101100
/// <param name="source">a source</param>
102-
/// <param name="start">where to start in the source</param>
103-
/// <param name="endQuoteSymbol">the end quote symbol</param>
101+
/// <param name="start">where to start in the source. Should point at quote symbol.</param>
104102
/// <returns>the new position in the source</returns>
105-
private static int AppendQuoteContent(StringBuilder buffer, String source, int start, char endQuoteSymbol) {
106-
int end = CssUtils.FindNextUnescapedChar(source, endQuoteSymbol, start);
103+
private static int AppendQuotedString(StringBuilder buffer, String source, int start) {
104+
char endQuoteSymbol = source[start];
105+
int end = CssUtils.FindNextUnescapedChar(source, endQuoteSymbol, start + 1);
107106
if (end == -1) {
108107
end = source.Length;
109108
LoggerFactory.GetLogger(typeof(CssPropertyNormalizer)).Warn(MessageFormatUtil.Format(iText.Html2pdf.LogMessageConstant
110109
.QUOTE_IS_NOT_CLOSED_IN_CSS_EXPRESSION, source));
111110
}
111+
else {
112+
++end;
113+
}
112114
buffer.JAppend(source, start, end);
113115
return end;
114116
}
115117

118+
/// <summary>Appends url content and end parenthesis if url is correct.</summary>
119+
/// <param name="buffer">the current buffer</param>
120+
/// <param name="source">a source</param>
121+
/// <param name="start">where to start in the source. Should point at first symbol after "url(".</param>
122+
/// <returns>the new position in the source</returns>
123+
private static int AppendUrlContent(StringBuilder buffer, String source, int start) {
124+
while (iText.IO.Util.TextUtil.IsWhiteSpace(source[start]) && start < source.Length) {
125+
++start;
126+
}
127+
if (start < source.Length) {
128+
int curr = start;
129+
if (source[curr] == '"' || source[curr] == '\'') {
130+
curr = AppendQuotedString(buffer, source, curr);
131+
return curr;
132+
}
133+
else {
134+
curr = CssUtils.FindNextUnescapedChar(source, ')', curr);
135+
if (curr == -1) {
136+
LoggerFactory.GetLogger(typeof(CssPropertyNormalizer)).Warn(MessageFormatUtil.Format(iText.Html2pdf.LogMessageConstant
137+
.URL_IS_NOT_CLOSED_IN_CSS_EXPRESSION, source));
138+
return source.Length;
139+
}
140+
else {
141+
buffer.Append(source.JSubstring(start, curr).Trim());
142+
buffer.Append(')');
143+
return curr + 1;
144+
}
145+
}
146+
}
147+
else {
148+
LoggerFactory.GetLogger(typeof(CssPropertyNormalizer)).Warn(MessageFormatUtil.Format(iText.Html2pdf.LogMessageConstant
149+
.URL_IS_EMPTY_IN_CSS_EXPRESSION, source));
150+
return source.Length;
151+
}
152+
}
153+
116154
/// <summary>Checks if spaces can be trimmed after a specific character.</summary>
117155
/// <param name="ch">the character</param>
118156
/// <returns>true, if spaces can be trimmed after the character</returns>

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3013027a856ea0bfb21b894b5ae903ead5892f3f
1+
5c50c645b3e9ae22f1bfcf49effd04264a2b2a02

0 commit comments

Comments
 (0)