diff --git a/api/pom.xml b/api/pom.xml
index a43cd43e..a4eae2ae 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -15,7 +15,7 @@
org.openmrs.module
legacyui
- 1.19.0-SNAPSHOT
+ 1.21.0-SNAPSHOT
legacyui-api
diff --git a/omod/pom.xml b/omod/pom.xml
index cdcc11b3..c5133716 100644
--- a/omod/pom.xml
+++ b/omod/pom.xml
@@ -15,7 +15,7 @@
org.openmrs.module
legacyui
- 1.19.0-SNAPSHOT
+ 1.21.0-SNAPSHOT
legacyui-omod
diff --git a/omod/src/main/java/org/openmrs/web/xss/XSSFilter.java b/omod/src/main/java/org/openmrs/web/xss/XSSFilter.java
new file mode 100644
index 00000000..c3857ffa
--- /dev/null
+++ b/omod/src/main/java/org/openmrs/web/xss/XSSFilter.java
@@ -0,0 +1,51 @@
+/**
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
+ * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
+ *
+ * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
+ * graphic logo is a trademark of OpenMRS Inc.
+ */
+package org.openmrs.web.xss;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
+
+public class XSSFilter implements Filter {
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+ ServletException {
+
+ if (!"GET".equalsIgnoreCase(((HttpServletRequest) request).getMethod())) {
+ if (ServletFileUpload.isMultipartContent((HttpServletRequest) request)) {
+ request = new XSSMultipartRequestWrapper((DefaultMultipartHttpServletRequest) request);
+ } else {
+ request = new XSSRequestWrapper((HttpServletRequest) request);
+ }
+ }
+
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+}
diff --git a/omod/src/main/java/org/openmrs/web/xss/XSSMultipartRequestWrapper.java b/omod/src/main/java/org/openmrs/web/xss/XSSMultipartRequestWrapper.java
new file mode 100644
index 00000000..e6df7bb2
--- /dev/null
+++ b/omod/src/main/java/org/openmrs/web/xss/XSSMultipartRequestWrapper.java
@@ -0,0 +1,72 @@
+/**
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
+ * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
+ *
+ * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
+ * graphic logo is a trademark of OpenMRS Inc.
+ */
+package org.openmrs.web.xss;
+
+import java.util.Enumeration;
+
+import org.owasp.encoder.Encode;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
+
+public class XSSMultipartRequestWrapper extends DefaultMultipartHttpServletRequest {
+
+ public XSSMultipartRequestWrapper(DefaultMultipartHttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public String getParameter(String name) {
+
+ String value = getRequest().getParameter(name);
+ if (value == null) {
+ return null;
+ }
+
+ return Encode.forHtmlContent(value);
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+
+ String[] values = getRequest().getParameterValues(name);
+ if (values == null) {
+ return null;
+ }
+
+ int count = values.length;
+ String[] encodedValues = new String[count];
+ for (int i = 0; i < count; i++) {
+ encodedValues[i] = Encode.forHtmlContent(values[i]);
+ }
+
+ return encodedValues;
+ }
+
+ @Override
+ public DefaultMultipartHttpServletRequest getRequest() {
+ return (DefaultMultipartHttpServletRequest) super.getRequest();
+ }
+
+ @Override
+ public MultipartFile getFile(String name) {
+ return getRequest().getFile(name);
+ }
+
+ @Override
+ public MultiValueMap getMultiFileMap() {
+ return getRequest().getMultiFileMap();
+ }
+
+ @Override
+ public Enumeration getParameterNames() {
+ return getRequest().getParameterNames();
+ }
+}
diff --git a/omod/src/main/java/org/openmrs/web/xss/XSSRequestWrapper.java b/omod/src/main/java/org/openmrs/web/xss/XSSRequestWrapper.java
new file mode 100644
index 00000000..844bd55c
--- /dev/null
+++ b/omod/src/main/java/org/openmrs/web/xss/XSSRequestWrapper.java
@@ -0,0 +1,73 @@
+/**
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
+ * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
+ *
+ * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
+ * graphic logo is a trademark of OpenMRS Inc.
+ */
+package org.openmrs.web.xss;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.commons.io.IOUtils;
+import org.owasp.encoder.Encode;
+
+public class XSSRequestWrapper extends HttpServletRequestWrapper {
+
+ public XSSRequestWrapper(HttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public String[] getParameterValues(String parameter) {
+
+ String[] values = super.getParameterValues(parameter);
+ if (values == null) {
+ return null;
+ }
+
+ int count = values.length;
+ String[] encodedValues = new String[count];
+ for (int i = 0; i < count; i++) {
+ encodedValues[i] = Encode.forHtml(values[i]);
+ }
+
+ return encodedValues;
+ }
+
+ @Override
+ public String getParameter(String name) {
+
+ String value = super.getParameter(name);
+ if (value == null) {
+ return null;
+ }
+
+ return Encode.forHtml(value);
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+
+ String requestBody = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8.name());
+ String sanitizedBody = Encode.forHtmlContent(requestBody);
+
+ return new ServletInputStream() {
+
+ private final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(sanitizedBody.getBytes());
+
+ @Override
+ public int read() throws IOException {
+ return byteArrayInputStream.read();
+ }
+ };
+ }
+}
diff --git a/omod/src/main/resources/config.xml b/omod/src/main/resources/config.xml
index 4e78b785..b4009f68 100644
--- a/omod/src/main/resources/config.xml
+++ b/omod/src/main/resources/config.xml
@@ -351,6 +351,15 @@
dwrFilter
/ms/call/plaincall/*
+
+
+ XSSFilter
+ org.openmrs.web.xss.XSSFilter
+
+
+ XSSFilter
+ /*
+
diff --git a/pom.xml b/pom.xml
index a77d86b7..21be5424 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
org.openmrs.module
legacyui
- 1.19.0-SNAPSHOT
+ 1.21.0-SNAPSHOT
pom
Legacy UI Module
Provides the legacy UI which was removed from the platform since version 2.0