You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2018/08/20 08:55:30 UTC

[camel] branch master updated: CAMEL-12597: camel-servlet now allows to specify accepted filename ext via a new whitelist option.

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 <cl...@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;
     }