Skip to content

Commit deaa53f

Browse files
committed
Fixed XSS Vulnerability.
1 parent 9d956fa commit deaa53f

22 files changed

+531
-41
lines changed

gwt-material/src/main/java/gwt/material/design/client/base/AbstractButton.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import com.google.gwt.event.logical.shared.ValueChangeEvent;
2525
import com.google.gwt.event.logical.shared.ValueChangeHandler;
2626
import com.google.gwt.event.shared.HandlerRegistration;
27+
import com.google.gwt.safehtml.shared.HtmlSanitizer;
28+
import com.google.gwt.safehtml.shared.SafeHtml;
2729
import com.google.gwt.user.client.History;
2830
import com.google.gwt.user.client.ui.HasValue;
2931
import gwt.material.design.client.base.mixin.ActivatesMixin;
@@ -36,7 +38,7 @@
3638
* @author Ben Dol
3739
*/
3840
public abstract class AbstractButton extends MaterialWidget implements HasHref, HasGrid, HasActivates,
39-
HasTargetHistoryToken, HasType<ButtonType>, HasValue<String> {
41+
HasTargetHistoryToken, HasType<ButtonType>, HasValue<String>, HasSafeText {
4042

4143
private String targetHistoryToken;
4244
private Span span = new Span();
@@ -169,6 +171,21 @@ public void setText(String text) {
169171
}
170172
}
171173

174+
@Override
175+
public void setHtml(SafeHtml html) {
176+
span.setHtml(html);
177+
}
178+
179+
@Override
180+
public void setSanitizer(HtmlSanitizer sanitizer) {
181+
span.setSanitizer(sanitizer);
182+
}
183+
184+
@Override
185+
public HtmlSanitizer getSanitizer() {
186+
return span.getSanitizer();
187+
}
188+
172189
/**
173190
* Set the target history token for the widget. Note, that you should use either
174191
* {@link #setTargetHistoryToken(String)} or {@link #setHref(String)}, but not both as

gwt-material/src/main/java/gwt/material/design/client/base/AbstractValueWidget.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,6 @@ public void setValue(V value, boolean fireEvents, boolean reload) {
8686
}
8787
}
8888

89-
//TODO:
90-
//setSanitizer();
91-
9289
@Override
9390
public void setErrorText(String errorText) {
9491
getStatusTextMixin().setErrorText(errorText);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* #%L
3+
* GwtMaterial
4+
* %%
5+
* Copyright (C) 2015 - 2020 GwtMaterialDesign
6+
* %%
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* #L%
19+
*/
20+
package gwt.material.design.client.base;
21+
22+
import com.google.gwt.safehtml.shared.HtmlSanitizer;
23+
import com.google.gwt.safehtml.shared.SafeHtml;
24+
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
25+
26+
/**
27+
* HTML-escapes its argument and returns the result wrapped as a SafeHtml.
28+
*/
29+
public class DefaultHtmlSanitizer implements HtmlSanitizer {
30+
31+
@Override
32+
public SafeHtml sanitize(String html) {
33+
return SafeHtmlUtils.fromString(html);
34+
}
35+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* #%L
3+
* GwtMaterial
4+
* %%
5+
* Copyright (C) 2015 - 2020 GwtMaterialDesign
6+
* %%
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* #L%
19+
*/
20+
package gwt.material.design.client.base;
21+
22+
import com.google.gwt.safehtml.shared.HtmlSanitizer;
23+
import com.google.gwt.safehtml.shared.SafeHtml;
24+
25+
public interface HasSafeText {
26+
27+
void setHtml(SafeHtml html);
28+
29+
void setSanitizer(HtmlSanitizer sanitizer);
30+
31+
HtmlSanitizer getSanitizer();
32+
}

gwt-material/src/main/java/gwt/material/design/client/base/TextWidget.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
package gwt.material.design.client.base;
2121

2222
import com.google.gwt.dom.client.Element;
23+
import com.google.gwt.safehtml.shared.HtmlSanitizer;
24+
import com.google.gwt.safehtml.shared.SafeHtml;
2325
import com.google.gwt.user.client.DOM;
2426
import com.google.gwt.user.client.ui.HasText;
2527
import gwt.material.design.client.base.mixin.TextMixin;
2628

27-
public class TextWidget extends MaterialWidget implements HasText {
29+
public class TextWidget extends MaterialWidget implements HasSafeText, HasText {
2830

29-
private final TextMixin<TextWidget> textMixin = new TextMixin<>(this);
31+
private TextMixin<TextWidget> textMixin;
3032

3133
public TextWidget() {
3234
super(DOM.createDiv());
@@ -42,11 +44,33 @@ public TextWidget(Element element, String... initialClass) {
4244

4345
@Override
4446
public String getText() {
45-
return textMixin.getText();
47+
return getTextMixin().getText();
4648
}
4749

4850
@Override
4951
public void setText(String text) {
50-
textMixin.setText(text);
52+
getTextMixin().setText(text);
5153
}
52-
}
54+
55+
@Override
56+
public void setHtml(SafeHtml html) {
57+
getTextMixin().setHtml(html);
58+
}
59+
60+
@Override
61+
public void setSanitizer(HtmlSanitizer sanitizer) {
62+
getTextMixin().setSanitizer(sanitizer);
63+
}
64+
65+
@Override
66+
public HtmlSanitizer getSanitizer() {
67+
return getTextMixin().getSanitizer();
68+
}
69+
70+
public TextMixin<TextWidget> getTextMixin() {
71+
if (textMixin == null) {
72+
textMixin = new TextMixin<>(this);
73+
}
74+
return textMixin;
75+
}
76+
}

gwt-material/src/main/java/gwt/material/design/client/base/mixin/AbstractMixin.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
/**
2727
* @author Sven Jacobs
2828
*/
29-
abstract class AbstractMixin<T extends UIObject> {
29+
public abstract class AbstractMixin<T extends UIObject> {
3030

3131
T uiObject;
3232

@@ -37,4 +37,8 @@ abstract class AbstractMixin<T extends UIObject> {
3737
public void setUiObject(T uiObject) {
3838
this.uiObject = uiObject;
3939
}
40+
41+
public T getUiObject() {
42+
return uiObject;
43+
}
4044
}

gwt-material/src/main/java/gwt/material/design/client/base/mixin/HTMLMixin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@
2323
import com.google.gwt.dom.client.Element;
2424
import com.google.gwt.user.client.ui.HasHTML;
2525
import com.google.gwt.user.client.ui.UIObject;
26+
import gwt.material.design.client.base.HasSafeText;
2627

2728
import static gwt.material.design.jquery.client.api.JQuery.$;
2829

2930
/**
3031
* @author Grant Slender
3132
*/
32-
public class HTMLMixin<T extends UIObject> extends TextMixin<T> implements HasHTML {
33+
public class HTMLMixin<T extends UIObject & HasSafeText> extends TextMixin<T> implements HasHTML {
3334

3435
public HTMLMixin(final T uiObject) {
3536
super(uiObject);

gwt-material/src/main/java/gwt/material/design/client/base/mixin/TextMixin.java

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,68 @@
2020
* #L%
2121
*/
2222

23+
import com.google.gwt.safehtml.shared.HtmlSanitizer;
24+
import com.google.gwt.safehtml.shared.SafeHtml;
2325
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
2426
import com.google.gwt.user.client.ui.UIObject;
27+
import gwt.material.design.client.base.DefaultHtmlSanitizer;
28+
import gwt.material.design.client.base.HasSafeText;
2529

2630
/**
31+
* @author Mark Kevin
2732
* @author Ben Dol
2833
*/
29-
public class TextMixin<T extends UIObject> extends AbstractMixin<T> {
34+
public class TextMixin<T extends UIObject & HasSafeText> extends AbstractMixin<T> implements HasSafeText {
35+
36+
protected static HtmlSanitizer DEFAULT_SANITIZER = new DefaultHtmlSanitizer();
37+
protected HtmlSanitizer _sanitizer;
38+
protected SafeHtml safeHtml;
3039

3140
public TextMixin(final T uiObject) {
3241
super(uiObject);
3342
}
3443

3544
public String getText() {
36-
return uiObject.getElement().getInnerText();
45+
return safeHtml != null ? uiObject.getElement().getInnerText() : null;
3746
}
3847

3948
public void setText(final String text) {
40-
uiObject.getElement().setInnerText(text);
49+
setHtml(toSafeHtml(text));
50+
}
51+
52+
protected SafeHtml toSafeHtml(String text) {
53+
SafeHtml safeHtml = null;
54+
if (text != null) {
55+
if (_sanitizer == null) {
56+
safeHtml = DEFAULT_SANITIZER.sanitize(text);
57+
} else {
58+
safeHtml = _sanitizer.sanitize(text);
59+
}
60+
}
61+
return safeHtml;
62+
}
63+
64+
@Override
65+
public void setHtml(SafeHtml safeHtml) {
66+
this.safeHtml = safeHtml;
67+
uiObject.getElement().setInnerSafeHtml(safeHtml != null ? safeHtml : SafeHtmlUtils.fromString(""));
68+
}
69+
70+
public static void setDefaultSanitizer(HtmlSanitizer defaultSanitizer) {
71+
DEFAULT_SANITIZER = defaultSanitizer;
72+
}
73+
74+
public static HtmlSanitizer getDefaultSanitizer() {
75+
return DEFAULT_SANITIZER;
76+
}
77+
78+
@Override
79+
public void setSanitizer(HtmlSanitizer sanitizer) {
80+
_sanitizer = sanitizer;
81+
}
82+
83+
@Override
84+
public HtmlSanitizer getSanitizer() {
85+
return _sanitizer;
4186
}
4287
}

gwt-material/src/main/java/gwt/material/design/client/ui/MaterialBadge.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package gwt.material.design.client.ui;
2121

2222
import com.google.gwt.dom.client.Document;
23-
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
2423
import gwt.material.design.client.constants.Color;
2524
import gwt.material.design.client.constants.CssName;
2625
import gwt.material.design.client.ui.html.Span;
@@ -81,14 +80,4 @@ public MaterialBadge(String text, Color textColor, Color bgColor) {
8180
setTextColor(textColor);
8281
setBackgroundColor(bgColor);
8382
}
84-
85-
@Override
86-
public String getText() {
87-
return SafeHtmlUtils.fromString(getElement().getInnerText()).asString();
88-
}
89-
90-
@Override
91-
public void setText(String text) {
92-
getElement().setInnerSafeHtml(SafeHtmlUtils.fromString(text));
93-
}
9483
}

gwt-material/src/main/java/gwt/material/design/client/ui/MaterialCardTitle.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121

2222
import com.google.gwt.dom.client.Document;
2323
import com.google.gwt.dom.client.Style;
24+
import com.google.gwt.safehtml.shared.HtmlSanitizer;
25+
import com.google.gwt.safehtml.shared.SafeHtml;
2426
import com.google.gwt.user.client.ui.HasText;
2527
import gwt.material.design.client.base.HasIcon;
28+
import gwt.material.design.client.base.HasSafeText;
2629
import gwt.material.design.client.base.MaterialWidget;
2730
import gwt.material.design.client.constants.*;
2831
import gwt.material.design.client.ui.html.Span;
@@ -38,7 +41,7 @@
3841
* @see <a href="https://material.io/guidelines/components/cards.html">Material Design Specification</a>
3942
*/
4043
//@formatter:on
41-
public class MaterialCardTitle extends MaterialWidget implements HasIcon, HasText {
44+
public class MaterialCardTitle extends MaterialWidget implements HasIcon, HasSafeText, HasText {
4245

4346
private MaterialIcon icon = new MaterialIcon();
4447
private Span titleLabel = new Span();
@@ -56,11 +59,26 @@ public String getText() {
5659
public void setText(String text) {
5760
titleLabel.setText(text);
5861

59-
if(!titleLabel.isAttached()) {
62+
if (!titleLabel.isAttached()) {
6063
add(titleLabel);
6164
}
6265
}
6366

67+
@Override
68+
public void setHtml(SafeHtml html) {
69+
titleLabel.setHtml(html);
70+
}
71+
72+
@Override
73+
public void setSanitizer(HtmlSanitizer sanitizer) {
74+
titleLabel.setSanitizer(sanitizer);
75+
}
76+
77+
@Override
78+
public HtmlSanitizer getSanitizer() {
79+
return titleLabel.getSanitizer();
80+
}
81+
6482
@Override
6583
public MaterialIcon getIcon() {
6684
return icon;

0 commit comments

Comments
 (0)