Skip to content

Commit 8565467

Browse files
committed
Merge branches '6_2' and 'master-cns' of https://github.com/cnsgithub/primefaces into master-cns
2 parents 72bdadf + ab3f127 commit 8565467

33 files changed

+1542
-1108
lines changed

pom.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@
126126
<dependency>
127127
<groupId>com.rometools</groupId>
128128
<artifactId>rome</artifactId>
129-
<version>1.7.3</version>
129+
<version>1.9.0</version>
130130
<scope>provided</scope>
131131
</dependency>
132132

@@ -191,7 +191,7 @@
191191
<dependency>
192192
<groupId>com.hazelcast</groupId>
193193
<artifactId>hazelcast</artifactId>
194-
<version>2.6.5</version>
194+
<version>3.9.2</version>
195195
<scope>provided</scope>
196196
</dependency>
197197
<dependency>
@@ -200,6 +200,13 @@
200200
<version>2.7.4</version>
201201
<scope>provided</scope>
202202
</dependency>
203+
204+
<!-- Text Editor -->
205+
<dependency>
206+
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
207+
<artifactId>owasp-java-html-sanitizer</artifactId>
208+
<version>20171016.1</version>
209+
</dependency>
203210
</dependencies>
204211

205212
<build>

src/main/java/org/primefaces/component/imagecompare/ImageCompareRenderer.java

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,35 +39,19 @@ protected void encodeScript(FacesContext context, ImageCompare compare) throws I
3939

4040
WidgetBuilder wb = getWidgetBuilder(context);
4141
wb.init("ImageCompare", compare.resolveWidgetVar(), clientId)
42-
.attr("handle", getResourceRequestPath(context, "imagecompare/handle.gif"))
43-
.attr("lt", getResourceRequestPath(context, "imagecompare/lt-small.png"))
44-
.attr("rt", getResourceRequestPath(context, "imagecompare/rt-small.png"));
45-
42+
.attr("leftimage", compare.getLeftImage())
43+
.attr("rightimage", compare.getRightImage());
4644
wb.finish();
4745
}
4846

4947
protected void encodeMarkup(FacesContext context, ImageCompare compare) throws IOException {
5048
ResponseWriter writer = context.getResponseWriter();
51-
5249
writer.startElement("div", compare);
50+
writer.writeAttribute("style", "width: " + compare.getWidth() + "px;" + "height: " + compare.getHeight() + "px;", null);
5351
writer.writeAttribute("id", compare.getClientId(context), "id");
54-
renderImage(context, compare, "before", compare.getLeftImage());
55-
renderImage(context, compare, "fter", compare.getRightImage());
52+
renderDynamicPassThruAttributes(context, compare);
5653
writer.endElement("div");
5754
}
5855

59-
private void renderImage(FacesContext context, ImageCompare compare, String type, String src) throws IOException {
60-
ResponseWriter writer = context.getResponseWriter();
61-
62-
writer.startElement("div", compare);
63-
64-
writer.startElement("img", null);
65-
writer.writeAttribute("alt", type, null);
66-
writer.writeAttribute("src", getResourceURL(context, src), null);
67-
writer.writeAttribute("width", compare.getWidth(), null);
68-
writer.writeAttribute("height", compare.getHeight(), null);
69-
writer.endElement("img");
7056

71-
writer.endElement("div");
72-
}
7357
}

src/main/java/org/primefaces/component/inputmask/InputMaskRenderer.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.io.IOException;
1919
import java.util.logging.Logger;
20+
import java.util.regex.Pattern;
2021

2122
import javax.faces.component.UIComponent;
2223
import javax.faces.context.FacesContext;
@@ -32,6 +33,9 @@ public class InputMaskRenderer extends InputRenderer {
3233

3334
private final static Logger logger = Logger.getLogger(InputMaskRenderer.class.getName());
3435

36+
private final static String REGEX_METACHARS = "<([{\\^-=$!|]})?*+.>".replaceAll(".", "\\\\$0");
37+
private final static Pattern REGEX_METACHARS_PATTERN = Pattern.compile("[" + REGEX_METACHARS + "]");
38+
3539
@Override
3640
public void decode(FacesContext context, UIComponent component) {
3741
InputMask inputMask = (InputMask) component;
@@ -46,10 +50,35 @@ public void decode(FacesContext context, UIComponent component) {
4650
String submittedValue = (String) context.getExternalContext().getRequestParameterMap().get(clientId);
4751

4852
if (submittedValue != null) {
53+
54+
if (!translateMaskIntoRegex(inputMask).matcher(submittedValue).matches()) {
55+
submittedValue = null;
56+
}
57+
4958
inputMask.setSubmittedValue(submittedValue);
5059
}
5160
}
5261

62+
// https://github.com/digitalBush/jquery.maskedinput
63+
// a - Represents an alpha character (A-Z,a-z)
64+
// 9 - Represents a numeric character (0-9)
65+
// * - Represents an alphanumeric character (A-Z,a-z,0-9)
66+
// ? - Makes the following input optional
67+
protected Pattern translateMaskIntoRegex(InputMask inputMask) {
68+
String mask = inputMask.getMask();
69+
70+
// Escape regex metacharacters first
71+
String regex = REGEX_METACHARS_PATTERN.matcher(mask).replaceAll("\\\\$0");
72+
73+
regex = regex.replace("a", "[A-Za-z]").replace("9", "[0-9]").replace("*", "[A-Za-z0-9]");
74+
int optionalPos = regex.indexOf("\\?");
75+
if (optionalPos != -1) {
76+
regex = regex.substring(0, optionalPos) + "(" + regex.substring(optionalPos + 2) + ")?";
77+
}
78+
79+
return Pattern.compile(regex);
80+
}
81+
5382
@Override
5483
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
5584
InputMask inputMask = (InputMask) component;

src/main/java/org/primefaces/component/signature/SignatureRenderer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ protected void encodeScript(FacesContext context, Signature signature) throws IO
7575
.attr("background", signature.getBackgroundColor(), null)
7676
.attr("color", signature.getColor(), null)
7777
.attr("thickness", signature.getThickness(), 2)
78-
.attr("disabled", signature.isReadonly(), false)
78+
.attr("readonly", signature.isReadonly(), false)
7979
.attr("guideline", signature.isGuideline(), false)
8080
.attr("guidelineColor", signature.getGuidelineColor(), null)
8181
.attr("guidelineOffset", signature.getGuidelineOffset(), 25)

src/main/java/org/primefaces/component/texteditor/TextEditorRenderer.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,70 @@
1717

1818
import java.io.IOException;
1919
import java.util.Map;
20+
import java.util.regex.Pattern;
2021

2122
import javax.faces.component.UIComponent;
2223
import javax.faces.context.FacesContext;
2324
import javax.faces.context.ResponseWriter;
2425
import javax.faces.convert.Converter;
2526
import javax.faces.convert.ConverterException;
2627

28+
import org.owasp.html.HtmlPolicyBuilder;
29+
import org.owasp.html.PolicyFactory;
30+
import org.owasp.html.Sanitizers;
2731
import org.primefaces.renderkit.CoreRenderer;
2832
import org.primefaces.util.ComponentUtils;
2933
import org.primefaces.util.WidgetBuilder;
3034

3135
public class TextEditorRenderer extends CoreRenderer {
3236

37+
private static final PolicyFactory HTML_IMAGES_SANITIZER = new HtmlPolicyBuilder()
38+
.allowUrlProtocols("data", "http", "https")
39+
.allowElements("img")
40+
.allowAttributes("src")
41+
.matching(Pattern.compile("^(data:image/(gif|png|jpeg)[,;]|http|https|mailto|//).+", Pattern.CASE_INSENSITIVE))
42+
.onElements("img")
43+
.toFactory();
44+
private static final PolicyFactory HTML_LINKS_SANITIZER = Sanitizers.LINKS
45+
.and(new HtmlPolicyBuilder()
46+
.allowElements("a")
47+
.allowAttributes("target")
48+
.onElements("a")
49+
.toFactory());
50+
private static final PolicyFactory HTML_STYLES_SANITIZER = Sanitizers.STYLES
51+
.and(new HtmlPolicyBuilder()
52+
.allowElements("span")
53+
.allowAttributes("class")
54+
.onElements("span")
55+
.toFactory());
56+
private static final PolicyFactory HTML_DENY_ALL_SANITIZER = new HtmlPolicyBuilder().toFactory();
57+
58+
protected String sanitizeHtml(String value, TextEditor editor) {
59+
PolicyFactory sanitizer = HTML_DENY_ALL_SANITIZER;
60+
if (editor.isAllowBlocks()) {
61+
sanitizer = sanitizer.and(Sanitizers.BLOCKS);
62+
}
63+
if (editor.isAllowFormatting()) {
64+
sanitizer = sanitizer.and(Sanitizers.FORMATTING);
65+
}
66+
if (editor.isAllowLinks()) {
67+
sanitizer = sanitizer.and(HTML_LINKS_SANITIZER);
68+
}
69+
if (editor.isAllowStyles()) {
70+
sanitizer = sanitizer.and(HTML_STYLES_SANITIZER);
71+
}
72+
if (editor.isAllowImages()) {
73+
sanitizer = sanitizer.and(HTML_IMAGES_SANITIZER);
74+
}
75+
return value == null ? null : sanitizer.sanitize(value);
76+
}
77+
3378
@Override
3479
public void decode(FacesContext context, UIComponent component) {
3580
TextEditor editor = (TextEditor) component;
3681
String inputParam = editor.getClientId(context) + "_input";
3782
Map<String, String> params = context.getExternalContext().getRequestParameterMap();
38-
String value = params.get(inputParam);
83+
String value = sanitizeHtml(params.get(inputParam), editor);
3984

4085
if (value != null && value.equals("<br/>")) {
4186
value = "";

src/main/java/org/primefaces/renderkit/SelectManyRenderer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ public void decode(FacesContext context, UIComponent component) {
3939
Map<String, String[]> params = context.getExternalContext().getRequestParameterValuesMap();
4040

4141
if (params.containsKey(submitParam)) {
42-
selectMany.setSubmittedValue(params.get(submitParam));
42+
String[] submittedValues = params.get(submitParam);
43+
checkDisabledSelectItemSubmitted(context, selectMany, (Object[]) getValues(selectMany), submittedValues);
44+
selectMany.setSubmittedValue(submittedValues);
4345
}
4446
else {
4547
selectMany.setSubmittedValue(new String[0]);

src/main/java/org/primefaces/renderkit/SelectOneRenderer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public void decode(FacesContext context, UIComponent component) {
3333
String clientId = getSubmitParam(context, selectOne);
3434
Map<String, String> params = context.getExternalContext().getRequestParameterMap();
3535
if (params.containsKey(clientId)) {
36+
String submittedValue = params.get(clientId);
37+
checkDisabledSelectItemSubmitted(context, selectOne, (Object[]) getValues(selectOne), submittedValue);
3638
selectOne.setSubmittedValue(params.get(clientId));
3739
}
3840
else {

src/main/java/org/primefaces/renderkit/SelectRenderer.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616
package org.primefaces.renderkit;
1717

1818
import java.lang.reflect.Array;
19+
import java.util.Arrays;
20+
import java.util.Collections;
1921
import java.util.List;
22+
import javax.faces.FacesException;
2023
import javax.faces.component.UIComponent;
24+
import javax.faces.component.UIInput;
2125
import javax.faces.context.FacesContext;
2226
import javax.faces.convert.Converter;
2327
import javax.faces.model.SelectItem;
@@ -95,4 +99,30 @@ protected int countSelectItems(SelectItem[] selectItems) {
9599
}
96100
return count;
97101
}
102+
103+
/**
104+
* Checks if at least one disabled select item has been submitted - this may occur with client side manipulation (#3264)
105+
* @throws javax.faces.FacesException if client side manipulation has been detected, in order to reject the submission
106+
*/
107+
protected void checkDisabledSelectItemSubmitted(FacesContext context, UIInput component, Object[] oldValues, String... newSubmittedValues)
108+
throws FacesException {
109+
String msg = "Disabled select item has been submitted";
110+
List<Object> oldVals = oldValues == null ? Collections.emptyList() : Arrays.asList(oldValues);
111+
List<String> newSubmittedValsStr = newSubmittedValues == null ? Collections.<String>emptyList() : Arrays.asList(newSubmittedValues);
112+
for (SelectItem selectItem : getSelectItems(context, component)) {
113+
if (selectItem.isDisabled()) {
114+
String selectItemValStr = getOptionAsString(context, component, component.getConverter(), selectItem.getValue());
115+
if (oldVals.contains(selectItemValStr) && !newSubmittedValsStr.contains(selectItemValStr)) {
116+
// disabled select item has been unselected
117+
throw new FacesException(msg);
118+
}
119+
if (newSubmittedValsStr.contains(selectItemValStr) && !oldVals.contains(selectItemValStr)) {
120+
// disabled select item has been selected
121+
throw new FacesException(msg);
122+
}
123+
}
124+
}
125+
}
126+
127+
98128
}

src/main/resources-maven-jsf/ui/imageCompare.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,8 @@
7474
<resource>
7575
<name>imagecompare/imagecompare.js</name>
7676
</resource>
77+
<resource>
78+
<name>imagecompare/imagecompare.css</name>
79+
</resource>
7780
</resources>
7881
</component>

src/main/resources-maven-jsf/ui/textEditor.xml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,41 @@
6666
<defaultValue>true</defaultValue>
6767
<description>Whether the toolbar of the editor is visible.</description>
6868
</attribute>
69+
<attribute>
70+
<name>allowFormatting</name>
71+
<required>false</required>
72+
<type>java.lang.Boolean</type>
73+
<defaultValue>true</defaultValue>
74+
<description>Whether to allow formatting to be included.</description>
75+
</attribute>
76+
<attribute>
77+
<name>allowBlocks</name>
78+
<required>false</required>
79+
<type>java.lang.Boolean</type>
80+
<defaultValue>true</defaultValue>
81+
<description>Whether to allow blocks to be included.</description>
82+
</attribute>
83+
<attribute>
84+
<name>allowStyles</name>
85+
<required>false</required>
86+
<type>java.lang.Boolean</type>
87+
<defaultValue>true</defaultValue>
88+
<description>Whether to allow styles to be included.</description>
89+
</attribute>
90+
<attribute>
91+
<name>allowLinks</name>
92+
<required>false</required>
93+
<type>java.lang.Boolean</type>
94+
<defaultValue>true</defaultValue>
95+
<description>Whether to allow links to be included.</description>
96+
</attribute>
97+
<attribute>
98+
<name>allowImages</name>
99+
<required>false</required>
100+
<type>java.lang.Boolean</type>
101+
<defaultValue>true</defaultValue>
102+
<description>Whether to allow images to be included.</description>
103+
</attribute>
69104
</attributes>
70105
<resources>
71106
<resource>

0 commit comments

Comments
 (0)