This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new 6f449df  CAMEL-12597: camel-servlet now allows to specify accepted 
filename ext via a new whitelist option.
6f449df is described below

commit 6f449dfb0ca7e3668ebdaa91cb602198c6a93b25
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Mon Aug 20 10:55:10 2018 +0200

    CAMEL-12597: camel-servlet now allows to specify accepted filename ext via 
a new whitelist option.
---
 .../camel/http/common/DefaultHttpBinding.java      | 28 ++++++++++++++++-
 .../org/apache/camel/http/common/HttpBinding.java  | 14 +++++++++
 .../src/main/docs/servlet-component.adoc           |  6 ++--
 .../component/servlet/AttachmentHttpBinding.java   | 36 ++++++++++++++++++----
 .../camel/component/servlet/ServletComponent.java  | 15 +++++++++
 .../camel/component/servlet/ServletEndpoint.java   | 16 ++++++++++
 .../springboot/ServletComponentConfiguration.java  | 13 ++++++++
 7 files changed, 119 insertions(+), 9 deletions(-)

diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
index 4bf1b76..f8c5343 100644
--- 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
@@ -46,6 +46,7 @@ import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.StreamCache;
 import org.apache.camel.converter.stream.CachedOutputStream;
 import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.GZIPHelper;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.MessageHelper;
@@ -81,6 +82,7 @@ public class DefaultHttpBinding implements HttpBinding {
     private boolean mapHttpMessageHeaders = true;
     private boolean mapHttpMessageFormUrlEncodedBody = true;
     private HeaderFilterStrategy headerFilterStrategy = new 
HttpHeaderFilterStrategy();
+    private String fileNameExtWhitelist;
 
     public DefaultHttpBinding() {
     }
@@ -300,7 +302,23 @@ public class DefaultHttpBinding implements HttpBinding {
             LOG.trace("HTTP attachment {} = {}", name, object);
             if (object instanceof File) {
                 String fileName = request.getParameter(name);
-                message.addAttachment(fileName, new DataHandler(new 
CamelFileDataSource((File)object, fileName)));
+                // is the file name accepted
+                boolean accepted = true;
+                if (fileNameExtWhitelist != null) {
+                    String ext = FileUtil.onlyExt(fileName);
+                    if (ext != null) {
+                        ext = ext.toLowerCase(Locale.US);
+                        fileNameExtWhitelist = 
fileNameExtWhitelist.toLowerCase(Locale.US);
+                        if (!fileNameExtWhitelist.equals("*") && 
!fileNameExtWhitelist.contains(ext)) {
+                            accepted = false;
+                        }
+                    }
+                }
+                if (accepted) {
+                    message.addAttachment(fileName, new DataHandler(new 
CamelFileDataSource((File) object, fileName)));
+                } else {
+                    LOG.debug("Cannot add file as attachment: {} because the 
file is not accepted according to fileNameExtWhitelist: {}", fileName, 
fileNameExtWhitelist);
+                }
             }
         }
     }
@@ -642,6 +660,14 @@ public class DefaultHttpBinding implements HttpBinding {
         this.mapHttpMessageFormUrlEncodedBody = 
mapHttpMessageFormUrlEncodedBody;
     }
 
+    public String getFileNameExtWhitelist() {
+        return fileNameExtWhitelist;
+    }
+
+    public void setFileNameExtWhitelist(String fileNameExtWhitelist) {
+        this.fileNameExtWhitelist = fileNameExtWhitelist;
+    }
+
     protected static SimpleDateFormat getHttpDateFormat() {
         SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, 
Locale.US);
         dateFormat.setTimeZone(TIME_ZONE_GMT);
diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpBinding.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpBinding.java
index 0826a27..d3bd834 100644
--- 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpBinding.java
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpBinding.java
@@ -217,4 +217,18 @@ public interface HttpBinding {
      */
     void setMapHttpMessageFormUrlEncodedBody(boolean 
mapHttpMessageFormUrlEncodedBody);
 
+    /**
+     * Whitelist of accepted filename extensions for accepting uploaded files.
+     * <p/>
+     * Multiple extensions can be separated by comma, such as txt,xml.
+     */
+    String getFileNameExtWhitelist();
+
+    /**
+     * Whitelist of accepted filename extensions for accepting uploaded files.
+     * <p/>
+     * Multiple extensions can be separated by comma, such as txt,xml.
+     */
+    void setFileNameExtWhitelist(String fileNameExtWhitelist);
+
 }
diff --git a/components/camel-servlet/src/main/docs/servlet-component.adoc 
b/components/camel-servlet/src/main/docs/servlet-component.adoc
index 86ce21c..cd80de3 100644
--- a/components/camel-servlet/src/main/docs/servlet-component.adoc
+++ b/components/camel-servlet/src/main/docs/servlet-component.adoc
@@ -43,7 +43,7 @@ You can append query options to the URI in the following 
format,
 ### Options
 
 // component options: START
-The Servlet component supports 8 options, which are listed below.
+The Servlet component supports 9 options, which are listed below.
 
 
 
@@ -53,6 +53,7 @@ The Servlet component supports 8 options, which are listed 
below.
 | *servletName* (consumer) | Default name of servlet to use. The default name 
is CamelServlet. |  | String
 | *httpRegistry* (consumer) | To use a custom 
org.apache.camel.component.servlet.HttpRegistry. |  | HttpRegistry
 | *attachmentMultipart Binding* (consumer) | Whether to automatic bind 
multipart/form-data as attachments on the Camel Exchange. The options 
attachmentMultipartBinding=true and disableStreamCache=false cannot work 
together. Remove disableStreamCache to use AttachmentMultipartBinding. This is 
turn off by default as this may require servlet specific configuration to 
enable this when using Servlet's. | false | boolean
+| *fileNameExtWhitelist* (consumer) | Whitelist of accepted filename 
extensions for accepting uploaded files. Multiple extensions can be separated 
by comma, such as txt,xml. |  | String
 | *httpBinding* (advanced) | To use a custom HttpBinding to control the 
mapping between Camel message and HttpClient. |  | HttpBinding
 | *httpConfiguration* (advanced) | To use the shared HttpConfiguration as base 
configuration. |  | HttpConfiguration
 | *allowJavaSerialized Object* (advanced) | Whether to allow java 
serialization when a request uses 
context-type=application/x-java-serialized-object. This is by default turned 
off. If you enable this then be aware that Java will deserialize the incoming 
data from the request to Java and that can be a potential security risk. | 
false | boolean
@@ -80,7 +81,7 @@ with the following path and query parameters:
 |===
 
 
-==== Query Parameters (21 parameters):
+==== Query Parameters (22 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -101,6 +102,7 @@ with the following path and query parameters:
 | *eagerCheckContentAvailable* (consumer) | Whether to eager check whether the 
HTTP requests has content if the content-length header is 0 or not present. 
This can be turned on in case HTTP clients do not send streamed data. | false | 
boolean
 | *exceptionHandler* (consumer) | To let the consumer use a custom 
ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this 
options is not in use. By default the consumer will deal with exceptions, that 
will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
 | *exchangePattern* (consumer) | Sets the exchange pattern when the consumer 
creates an exchange. |  | ExchangePattern
+| *fileNameExtWhitelist* (consumer) | Whitelist of accepted filename 
extensions for accepting uploaded files. Multiple extensions can be separated 
by comma, such as txt,xml. |  | String
 | *optionsEnabled* (consumer) | Specifies whether to enable HTTP OPTIONS for 
this Servlet consumer. By default OPTIONS is turned off. | false | boolean
 | *traceEnabled* (consumer) | Specifies whether to enable HTTP TRACE for this 
Servlet consumer. By default TRACE is turned off. | false | boolean
 | *mapHttpMessageBody* (advanced) | If this option is true then IN exchange 
Body of the exchange will be mapped to HTTP body. Setting this to false will 
avoid the HTTP mapping. | true | boolean
diff --git 
a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java
 
b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java
index dd2ba36..b295bbc 100644
--- 
a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java
+++ 
b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Collection;
+import java.util.Locale;
 import javax.activation.DataSource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.Part;
@@ -29,6 +30,9 @@ import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.http.common.DefaultHttpBinding;
 import org.apache.camel.http.common.HttpMessage;
 import org.apache.camel.impl.DefaultAttachment;
+import org.apache.camel.util.FileUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * To handle attachments with Servlet.
@@ -37,6 +41,8 @@ import org.apache.camel.impl.DefaultAttachment;
  */
 public final class AttachmentHttpBinding extends DefaultHttpBinding {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(AttachmentHttpBinding.class);
+
     AttachmentHttpBinding() {
     }
 
@@ -45,14 +51,32 @@ public final class AttachmentHttpBinding extends 
DefaultHttpBinding {
         try {
             Collection<Part> parts = request.getParts();
             for (Part part : parts) {
-                DataSource ds = new PartDataSource(part);
-                Attachment attachment = new DefaultAttachment(ds);
-                for (String headerName : part.getHeaderNames()) {
-                    for (String headerValue : part.getHeaders(headerName)) {
-                        attachment.addHeader(headerName, headerValue);
+                String fileName = part.getName();
+                // is the file name accepted
+                boolean accepted = true;
+                if (getFileNameExtWhitelist() != null) {
+                    String ext = FileUtil.onlyExt(fileName);
+                    if (ext != null) {
+                        ext = ext.toLowerCase(Locale.US);
+                        String whiteList = 
getFileNameExtWhitelist().toLowerCase(Locale.US);
+                        if (!whiteList.equals("*") && 
!whiteList.contains(ext)) {
+                            accepted = false;
+                        }
+                    }
+                }
+
+                if (accepted) {
+                    DataSource ds = new PartDataSource(part);
+                    Attachment attachment = new DefaultAttachment(ds);
+                    for (String headerName : part.getHeaderNames()) {
+                        for (String headerValue : part.getHeaders(headerName)) 
{
+                            attachment.addHeader(headerName, headerValue);
+                        }
                     }
+                    message.addAttachmentObject(part.getName(), attachment);
+                } else {
+                    LOG.debug("Cannot add file as attachment: {} because the 
file is not accepted according to fileNameExtWhitelist: {}", fileName, 
getFileNameExtWhitelist());
                 }
-                message.addAttachmentObject(part.getName(), attachment);
             }
         } catch (Exception e) {
             throw new RuntimeCamelException("Cannot populate attachments", e);
diff --git 
a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/ServletComponent.java
 
b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/ServletComponent.java
index 6c3613e..3683be6 100644
--- 
a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/ServletComponent.java
+++ 
b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/ServletComponent.java
@@ -47,6 +47,7 @@ public class ServletComponent extends HttpCommonComponent 
implements RestConsume
     private String servletName = "CamelServlet";
     private HttpRegistry httpRegistry;
     private boolean attachmentMultipartBinding;
+    private String fileNameExtWhitelist;
 
     public ServletComponent() {
         super(ServletEndpoint.class);
@@ -89,6 +90,7 @@ public class ServletComponent extends HttpCommonComponent 
implements RestConsume
 
         ServletEndpoint endpoint = createServletEndpoint(uri, this, httpUri);
         endpoint.setServletName(servletName);
+        endpoint.setFileNameExtWhitelist(fileNameExtWhitelist);
         if (async != null) {
             endpoint.setAsync(async);
         }
@@ -222,6 +224,19 @@ public class ServletComponent extends HttpCommonComponent 
implements RestConsume
         this.attachmentMultipartBinding = attachmentMultipartBinding;
     }
 
+    public String getFileNameExtWhitelist() {
+        return fileNameExtWhitelist;
+    }
+
+    /**
+     * Whitelist of accepted filename extensions for accepting uploaded files.
+     * <p/>
+     * Multiple extensions can be separated by comma, such as txt,xml.
+     */
+    public void setFileNameExtWhitelist(String fileNameExtWhitelist) {
+        this.fileNameExtWhitelist = fileNameExtWhitelist;
+    }
+
     @Override
     public Consumer createConsumer(CamelContext camelContext, Processor 
processor, String verb, String basePath, String uriTemplate,
                                    String consumes, String produces, 
RestConfiguration configuration, Map<String, Object> parameters) throws 
Exception {
diff --git 
a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/ServletEndpoint.java
 
b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/ServletEndpoint.java
index 0425b4b..0c48efb 100644
--- 
a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/ServletEndpoint.java
+++ 
b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/ServletEndpoint.java
@@ -46,6 +46,8 @@ public class ServletEndpoint extends HttpCommonEndpoint {
     private String servletName;
     @UriParam(label = "consumer,advanced")
     private boolean attachmentMultipartBinding;
+    @UriParam(label = "consumer,advanced")
+    private String fileNameExtWhitelist;
 
     public ServletEndpoint() {
     }
@@ -70,6 +72,7 @@ public class ServletEndpoint extends HttpCommonEndpoint {
             } else {
                 this.binding = new DefaultHttpBinding();
             }
+            this.binding.setFileNameExtWhitelist(getFileNameExtWhitelist());
             this.binding.setTransferException(isTransferException());
             if (getComponent() != null) {
                 
this.binding.setAllowJavaSerializedObject(getComponent().isAllowJavaSerializedObject());
@@ -127,6 +130,19 @@ public class ServletEndpoint extends HttpCommonEndpoint {
         this.attachmentMultipartBinding = attachmentMultipartBinding;
     }
 
+    public String getFileNameExtWhitelist() {
+        return fileNameExtWhitelist;
+    }
+
+    /**
+     * Whitelist of accepted filename extensions for accepting uploaded files.
+     * <p/>
+     * Multiple extensions can be separated by comma, such as txt,xml.
+     */
+    public void setFileNameExtWhitelist(String fileNameExtWhitelist) {
+        this.fileNameExtWhitelist = fileNameExtWhitelist;
+    }
+
     @Override
     public Producer createProducer() throws Exception {
         throw new UnsupportedOperationException("You cannot create producer 
with servlet endpoint, please consider to use http or http4 endpoint.");
diff --git 
a/platforms/spring-boot/components-starter/camel-servlet-starter/src/main/java/org/apache/camel/component/servlet/springboot/ServletComponentConfiguration.java
 
b/platforms/spring-boot/components-starter/camel-servlet-starter/src/main/java/org/apache/camel/component/servlet/springboot/ServletComponentConfiguration.java
index 97ecab5..3599ad6 100644
--- 
a/platforms/spring-boot/components-starter/camel-servlet-starter/src/main/java/org/apache/camel/component/servlet/springboot/ServletComponentConfiguration.java
+++ 
b/platforms/spring-boot/components-starter/camel-servlet-starter/src/main/java/org/apache/camel/component/servlet/springboot/ServletComponentConfiguration.java
@@ -56,6 +56,11 @@ public class ServletComponentConfiguration
      */
     private Boolean attachmentMultipartBinding = false;
     /**
+     * Whitelist of accepted filename extensions for accepting uploaded files.
+     * Multiple extensions can be separated by comma, such as txt,xml.
+     */
+    private String fileNameExtWhitelist;
+    /**
      * To use a custom HttpBinding to control the mapping between Camel message
      * and HttpClient. The option is a org.apache.camel.http.common.HttpBinding
      * type.
@@ -111,6 +116,14 @@ public class ServletComponentConfiguration
         this.attachmentMultipartBinding = attachmentMultipartBinding;
     }
 
+    public String getFileNameExtWhitelist() {
+        return fileNameExtWhitelist;
+    }
+
+    public void setFileNameExtWhitelist(String fileNameExtWhitelist) {
+        this.fileNameExtWhitelist = fileNameExtWhitelist;
+    }
+
     public String getHttpBinding() {
         return httpBinding;
     }

Reply via email to