CVE-2014-8114: Permissions, Privileges, and Access Controls (CWE-264)
value: The UberFire Framework 0.3.x does not properly restrict paths, which allows remote attackers to (1) execute arbitrary code by uploading crafted content to FileUploadServlet or (2) read arbitrary files via vectors involving FileDownloadServlet.
CWE description: Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.
Published: 2015-02-20T16:59Z
Repository: https://github.com/uberfire/uberfire
Language: Java
Files changed: uberfire-commons/src/main/java/org/uberfire/commons/regex/util/AntPathMatcher.java, uberfire-io/src/main/java/org/uberfire/io/regex/AntPathMatcher.java, uberfire-io/src/test/java/org/uberfire/io/regex/AntPathMatcherTest.java, uberfire-security/uberfire-security-server/src/main/java/org/uberfire/security/server/URLResourceManager.java, uberfire-server/src/main/java/org/uberfire/server/BaseFilteredServlet.java, uberfire-server/src/main/java/org/uberfire/server/FileDownloadServlet.java, uberfire-server/src/main/java/org/uberfire/server/FileUploadServlet.java
Commit date: 2014-12-24 10:26:06 -0300
Commit message: BZ(1169544,1169556, 1169557,1169559,1169560): improvements on security related to file access

Diff: diff --git a/uberfire-security/uberfire-security-server/src/main/java/org/uberfire/security/server/util/AntPathMatcher.java b/uberfire-commons/src/main/java/org/uberfire/commons/regex/util/AntPathMatcher.java
similarity index 59%
rename from uberfire-security/uberfire-security-server/src/main/java/org/uberfire/security/server/util/AntPathMatcher.java
rename to uberfire-commons/src/main/java/org/uberfire/commons/regex/util/AntPathMatcher.java
index b4bdcdc7..d8c7e051 100644
--- a/uberfire-security/uberfire-security-server/src/main/java/org/uberfire/security/server/util/AntPathMatcher.java
+++ b/uberfire-commons/src/main/java/org/uberfire/commons/regex/util/AntPathMatcher.java
@@ -1,22 +1,6 @@
-/*
- * Copyright 2012 JBoss Inc
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.uberfire.security.server.util;
+package org.uberfire.commons.regex.util;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.StringTokenizer;
 
@@ -37,120 +21,124 @@ public class AntPathMatcher {
 
     /**
      * Set the path separator to use for pattern parsing. Default is "/", as in
      * Ant.
      */
-    public void setPathSeparator(final String pathSeparator) {
+    public void setPathSeparator( final String pathSeparator ) {
         this.pathSeparator = pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR;
     }
 
-    public boolean isPattern(final String path) {
-        return path.indexOf('*') != -1 || path.indexOf('?') != -1;
+    public boolean isPattern( final String path ) {
+        return path.indexOf( '*' ) != -1 || path.indexOf( '?' ) != -1;
     }
 
-    public boolean match(final String pattern, final String path) {
-        return doMatch(pattern, path, true);
+    public boolean match( final String pattern,
+                          final String path ) {
+        return doMatch( pattern, path, true );
     }
 
-    public boolean matchStart(final String pattern, final String path) {
-        return doMatch(pattern, path, false);
+    public boolean matchStart( final String pattern,
+                               final String path ) {
+        return doMatch( pattern, path, false );
     }
 
     /**
      * Actually match the given <code>path</code> against the given
      * <code>pattern</code>.
      * @param pattern the pattern to match against
      * @param path the path String to test
      * @param fullMatch whether a full pattern match is required (else a pattern
      * match as far as the given base path goes is sufficient)
      * @return <code>true</code> if the supplied <code>path</code> matched,
-     *         <code>false</code> if it didn't
+     * <code>false</code> if it didn't
      */
-    protected boolean doMatch(String pattern, String path, boolean fullMatch) {
-        if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
+    protected boolean doMatch( String pattern,
+                               String path,
+                               boolean fullMatch ) {
+        if ( path.startsWith( this.pathSeparator ) != pattern.startsWith( this.pathSeparator ) ) {
             return false;
         }
 
-        String[] pattDirs = tokenizeToStringArray(pattern, this.pathSeparator);
-        String[] pathDirs = tokenizeToStringArray(path, this.pathSeparator);
+        String[] pattDirs = tokenizeToStringArray( pattern, this.pathSeparator );
+        String[] pathDirs = tokenizeToStringArray( path, this.pathSeparator );
 
         int pattIdxStart = 0;
         int pattIdxEnd = pattDirs.length - 1;
         int pathIdxStart = 0;
         int pathIdxEnd = pathDirs.length - 1;
 
         // Match all elements up to the first **
-        while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
-            String patDir = pattDirs[pattIdxStart];
-            if ("**".equals(patDir)) {
+        while ( pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd ) {
+            String patDir = pattDirs[ pattIdxStart ];
+            if ( "**".equals( patDir ) ) {
                 break;
             }
-            if (!matchStrings(patDir, pathDirs[pathIdxStart])) {
+            if ( !matchStrings( patDir, pathDirs[ pathIdxStart ] ) ) {
                 return false;
             }
             pattIdxStart++;
             pathIdxStart++;
         }
 
-        if (pathIdxStart > pathIdxEnd) {
+        if ( pathIdxStart > pathIdxEnd ) {
             // Path is exhausted, only match if rest of pattern is * or **'s
-            if (pattIdxStart > pattIdxEnd) {
-                return pattern.endsWith(this.pathSeparator) ? path.endsWith(this.pathSeparator) : !path
-                        .endsWith(this.pathSeparator);
+            if ( pattIdxStart > pattIdxEnd ) {
+                return pattern.endsWith( this.pathSeparator ) ? path.endsWith( this.pathSeparator ) : !path
+                        .endsWith( this.pathSeparator );
             }
-            if (!fullMatch) {
+            if ( !fullMatch ) {
                 return true;
             }
-            if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*")
-                    && path.endsWith(this.pathSeparator)) {
+            if ( pattIdxStart == pattIdxEnd && pattDirs[ pattIdxStart ].equals( "*" )
+                    && path.endsWith( this.pathSeparator ) ) {
                 return true;
             }
-            for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
-                if (!pattDirs[i].equals("**")) {
+            for ( int i = pattIdxStart; i <= pattIdxEnd; i++ ) {
+                if ( !pattDirs[ i ].equals( "**" ) ) {
                     return false;
                 }
             }
             return true;
-        } else if (pattIdxStart > pattIdxEnd) {
+        } else if ( pattIdxStart > pattIdxEnd ) {
             // String not exhausted, but pattern is. Failure.
             return false;
-        } else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) {
+        } else if ( !fullMatch && "**".equals( pattDirs[ pattIdxStart ] ) ) {
             // Path start definitely matches due to "**" part in pattern.
             return true;
         }
 
         // up to last '**'
-        while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
-            String patDir = pattDirs[pattIdxEnd];
-            if (patDir.equals("**")) {
+        while ( pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd ) {
+            String patDir = pattDirs[ pattIdxEnd ];
+            if ( patDir.equals( "**" ) ) {
                 break;
             }
-            if (!matchStrings(patDir, pathDirs[pathIdxEnd])) {
+            if ( !matchStrings( patDir, pathDirs[ pathIdxEnd ] ) ) {
                 return false;
             }
             pattIdxEnd--;
             pathIdxEnd--;
         }
-        if (pathIdxStart > pathIdxEnd) {
+        if ( pathIdxStart > pathIdxEnd ) {
             // String is exhausted
-            for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
-                if (!pattDirs[i].equals("**")) {
+            for ( int i = pattIdxStart; i <= pattIdxEnd; i++ ) {
+                if ( !pattDirs[ i ].equals( "**" ) ) {
                     return false;
                 }
             }
             return true;
         }
 
-        while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
+        while ( pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd ) {
             int patIdxTmp = -1;
-            for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
-                if (pattDirs[i].equals("**")) {
+            for ( int i = pattIdxStart + 1; i <= pattIdxEnd; i++ ) {
+                if ( pattDirs[ i ].equals( "**" ) ) {
                     patIdxTmp = i;
                     break;
                 }
             }
-            if (patIdxTmp == pattIdxStart + 1) {
+            if ( patIdxTmp == pattIdxStart + 1 ) {
                 // '**/**' situation, so skip one
                 pattIdxStart++;
                 continue;
             }
             // Find the pattern between padIdxStart & padIdxTmp in str between
@@ -158,32 +146,32 @@ public class AntPathMatcher {
             int patLength = patIdxTmp - pattIdxStart - 1;
             int strLength = pathIdxEnd - pathIdxStart + 1;
             int foundIdx = -1;
 
             strLoop:
-            for (int i = 0; i <= strLength - patLength; i++) {
-                for (int j = 0; j < patLength; j++) {
-                    String subPat = pattDirs[pattIdxStart + j + 1];
-                    String subStr = pathDirs[pathIdxStart + i + j];
-                    if (!matchStrings(subPat, subStr)) {
+            for ( int i = 0; i <= strLength - patLength; i++ ) {
+                for ( int j = 0; j < patLength; j++ ) {
+                    String subPat = pattDirs[ pattIdxStart + j + 1 ];
+                    String subStr = pathDirs[ pathIdxStart + i + j ];
+                    if ( !matchStrings( subPat, subStr ) ) {
                         continue strLoop;
                     }
                 }
                 foundIdx = pathIdxStart + i;
                 break;
             }
 
-            if (foundIdx == -1) {
+            if ( foundIdx == -1 ) {
                 return false;
             }
 
             pattIdxStart = patIdxTmp;
             pathIdxStart = foundIdx + patLength;
         }
 
-        for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
-            if (!pattDirs[i].equals("**")) {
+        for ( int i = pattIdxStart; i <= pattIdxEnd; i++ ) {
+            if ( !pattDirs[ i ].equals( "**" ) ) {
                 return false;
             }
         }
 
         return true;
@@ -196,141 +184,142 @@ public class AntPathMatcher {
      * '?' means one and only one character
      * @param pattern pattern to match against. Must not be <code>null</code>.
      * @param str string which must be matched against the pattern. Must not be
      * <code>null</code>.
      * @return <code>true</code> if the string matches against the pattern, or
-     *         <code>false</code> otherwise.
+     * <code>false</code> otherwise.
      */
-    private boolean matchStrings(String pattern, String str) {
+    private boolean matchStrings( String pattern,
+                                  String str ) {
         char[] patArr = pattern.toCharArray();
         char[] strArr = str.toCharArray();
         int patIdxStart = 0;
         int patIdxEnd = patArr.length - 1;
         int strIdxStart = 0;
         int strIdxEnd = strArr.length - 1;
         char ch;
 
         boolean containsStar = false;
-        for (char c : patArr) {
-            if (c == '*') {
+        for ( char c : patArr ) {
+            if ( c == '*' ) {
                 containsStar = true;
                 break;
             }
         }
 
-        if (!containsStar) {
+        if ( !containsStar ) {
             // No '*'s, so we make a shortcut
-            if (patIdxEnd != strIdxEnd) {
+            if ( patIdxEnd != strIdxEnd ) {
                 return false; // Pattern and string do not have the same size
             }
-            for (int i = 0; i <= patIdxEnd; i++) {
-                ch = patArr[i];
-                if (ch != '?') {
-                    if (ch != strArr[i]) {
+            for ( int i = 0; i <= patIdxEnd; i++ ) {
+                ch = patArr[ i ];
+                if ( ch != '?' ) {
+                    if ( ch != strArr[ i ] ) {
                         return false;
                         // Character mismatch
                     }
                 }
             }
             return true; // String matches against pattern
         }
 
-        if (patIdxEnd == 0) {
+        if ( patIdxEnd == 0 ) {
             return true; // Pattern contains only '*', which matches anything
         }
 
         // Process characters before first star
-        while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
-            if (ch != '?') {
-                if (ch != strArr[strIdxStart]) {
+        while ( ( ch = patArr[ patIdxStart ] ) != '*' && strIdxStart <= strIdxEnd ) {
+            if ( ch != '?' ) {
+                if ( ch != strArr[ strIdxStart ] ) {
                     return false;
                     // Character mismatch
                 }
             }
             patIdxStart++;
             strIdxStart++;
         }
-        if (strIdxStart > strIdxEnd) {
+        if ( strIdxStart > strIdxEnd ) {
             // All characters in the string are used. Check if only '*'s are
             // left in the pattern. If so, we succeeded. Otherwise failure.
-            for (int i = patIdxStart; i <= patIdxEnd; i++) {
-                if (patArr[i] != '*') {
+            for ( int i = patIdxStart; i <= patIdxEnd; i++ ) {
+                if ( patArr[ i ] != '*' ) {
                     return false;
                 }
             }
             return true;
         }
 
         // Process characters after last star
-        while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
-            if (ch != '?') {
-                if (ch != strArr[strIdxEnd]) {
+        while ( ( ch = patArr[ patIdxEnd ] ) != '*' && strIdxStart <= strIdxEnd ) {
+            if ( ch != '?' ) {
+                if ( ch != strArr[ strIdxEnd ] ) {
                     return false;
                     // Character mismatch
                 }
             }
             patIdxEnd--;
             strIdxEnd--;
         }
-        if (strIdxStart > strIdxEnd) {
+        if ( strIdxStart > strIdxEnd ) {
             // All characters in the string are used. Check if only '*'s are
             // left in the pattern. If so, we succeeded. Otherwise failure.
-            for (int i = patIdxStart; i <= patIdxEnd; i++) {
-                if (patArr[i] != '*') {
+            for ( int i = patIdxStart; i <= patIdxEnd; i++ ) {
+                if ( patArr[ i ] != '*' ) {
                     return false;
                 }
             }
             return true;
         }
 
         // process pattern between stars. padIdxStart and patIdxEnd point
         // always to a '*'.
-        while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
+        while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd ) {
             int patIdxTmp = -1;
-            for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
-                if (patArr[i] == '*') {
+            for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ ) {
+                if ( patArr[ i ] == '*' ) {
                     patIdxTmp = i;
                     break;
                 }
             }
-            if (patIdxTmp == patIdxStart + 1) {
+            if ( patIdxTmp == patIdxStart + 1 ) {
                 // Two stars next to each other, skip the first one.
                 patIdxStart++;
                 continue;
             }
             // Find the pattern between padIdxStart & padIdxTmp in str between
             // strIdxStart & strIdxEnd
             int patLength = patIdxTmp - patIdxStart - 1;
             int strLength = strIdxEnd - strIdxStart + 1;
             int foundIdx = -1;
             strLoop:
-            for (int i = 0; i <= strLength - patLength; i++) {
-                for (int j = 0; j < patLength; j++) {
-                    ch = patArr[patIdxStart + j + 1];
-                    if (ch != '?') {
-                        if (ch != strArr[strIdxStart + i + j]) {
+            for ( int i = 0; i <= strLength - patLength; i++ ) {
+                for ( int j = 0; j < patLength; j++ ) {
+                    ch = patArr[ patIdxStart + j + 1 ];
+                    if ( ch != '?' ) {
+                        if ( ch != strArr[ strIdxStart + i + j ] ) {
                             continue strLoop;
                         }
                     }
                 }
 
                 foundIdx = strIdxStart + i;
                 break;
             }
 
-            if (foundIdx == -1) {
+            if ( foundIdx == -1 ) {
                 return false;
             }
 
             patIdxStart = patIdxTmp;
             strIdxStart = foundIdx + patLength;
         }
 
         // All characters in the string are used. Check if only '*'s are left
         // in the pattern. If so, we succeeded. Otherwise failure.
-        for (int i = patIdxStart; i <= patIdxEnd; i++) {
-            if (patArr[i] != '*') {
+        for ( int i = patIdxStart; i <= patIdxEnd; i++ ) {
+            if ( patArr[ i ] != '*' ) {
                 return false;
             }
         }
 
         return true;
@@ -361,35 +350,36 @@ public class AntPathMatcher {
      * <p/>
      * Assumes that {@link #match} returns <code>true</code> for '
      * <code>pattern</code>' and '<code>path</code>', but does
      * <strong>not</strong> enforce this.
      */
-    public String extractPathWithinPattern(String pattern, String path) {
-        final String[] patternParts = tokenizeToStringArray(pattern, this.pathSeparator);
-        final String[] pathParts = tokenizeToStringArray(path, this.pathSeparator);
+    public String extractPathWithinPattern( String pattern,
+                                            String path ) {
+        final String[] patternParts = tokenizeToStringArray( pattern, this.pathSeparator );
+        final String[] pathParts = tokenizeToStringArray( path, this.pathSeparator );
 
         final StringBuilder buffer = new StringBuilder();
 
         // Add any path parts that have a wildcarded pattern part.
         int puts = 0;
-        for (int i = 0; i < patternParts.length; i++) {
-            final String patternPart = patternParts[i];
-            if ((patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) && pathParts.length >= i + 1) {
-                if (puts > 0 || (i == 0 && !pattern.startsWith(this.pathSeparator))) {
-                    buffer.append(this.pathSeparator);
+        for ( int i = 0; i < patternParts.length; i++ ) {
+            final String patternPart = patternParts[ i ];
+            if ( ( patternPart.indexOf( '*' ) > -1 || patternPart.indexOf( '?' ) > -1 ) && pathParts.length >= i + 1 ) {
+                if ( puts > 0 || ( i == 0 && !pattern.startsWith( this.pathSeparator ) ) ) {
+                    buffer.append( this.pathSeparator );
                 }
-                buffer.append(pathParts[i]);
+                buffer.append( pathParts[ i ] );
                 puts++;
             }
         }
 
         // Append any trailing path parts.
-        for (int i = patternParts.length; i < pathParts.length; i++) {
-            if (puts > 0 || i > 0) {
-                buffer.append(this.pathSeparator);
+        for ( int i = patternParts.length; i < pathParts.length; i++ ) {
+            if ( puts > 0 || i > 0 ) {
+                buffer.append( this.pathSeparator );
             }
-            buffer.append(pathParts[i]);
+            buffer.append( pathParts[ i ] );
         }
 
         return buffer.toString();
     }
 
@@ -406,21 +396,22 @@ public class AntPathMatcher {
      * those characters is individually considered as delimiter).
      * @return an array of the tokens
      * @see java.util.StringTokenizer
      * @see java.lang.String#trim()
      */
-    public static String[] tokenizeToStringArray(String str, String delimiters) {
-        if (str == null) {
+    public static String[] tokenizeToStringArray( String str,
+                                                  String delimiters ) {
+        if ( str == null ) {
             return null;
         }
-        final StringTokenizer st = new StringTokenizer(str, delimiters);
+        final StringTokenizer st = new StringTokenizer( str, delimiters );
         final List<String> tokens = new ArrayList<String>();
-        while (st.hasMoreTokens()) {
+        while ( st.hasMoreTokens() ) {
             final String token = st.nextToken().trim();
-            if (token.length() > 0) {
-                tokens.add(token);
+            if ( token.length() > 0 ) {
+                tokens.add( token );
             }
         }
-        return tokens.toArray(new String[tokens.size()]);
+        return tokens.toArray( new String[ tokens.size() ] );
     }
 
-}
+}
\ No newline at end of file
diff --git a/uberfire-io/src/main/java/org/uberfire/io/regex/AntPathMatcher.java b/uberfire-io/src/main/java/org/uberfire/io/regex/AntPathMatcher.java
new file mode 100644
index 00000000..25033269
--- /dev/null
+++ b/uberfire-io/src/main/java/org/uberfire/io/regex/AntPathMatcher.java
@@ -0,0 +1,89 @@
+package org.uberfire.io.regex;
+
+import java.net.URI;
+import java.util.Collection;
+
+import org.uberfire.java.nio.file.Path;
+
+import static org.uberfire.commons.validation.Preconditions.*;
+
+public final class AntPathMatcher {
+
+    private static org.uberfire.commons.regex.util.AntPathMatcher matcher = new org.uberfire.commons.regex.util.AntPathMatcher();
+
+    public static boolean filter( final Collection<String> includes,
+                                  final Collection<String> excludes,
+                                  final Path path ) {
+        checkNotNull( "includes", includes );
+        checkNotNull( "excludes", excludes );
+        checkNotNull( "path", path );
+        if ( includes.isEmpty() && excludes.isEmpty() ) {
+            return true;
+        } else if ( includes.isEmpty() ) {
+            return !( excludes( excludes, path ) );
+        } else if ( excludes.isEmpty() ) {
+            return includes( includes, path );
+        }
+        return includes( includes, path ) && !( excludes( excludes, path ) );
+    }
+
+    public static boolean filter( final Collection<String> includes,
+                                  final Collection<String> excludes,
+                                  final URI uri ) {
+        checkNotNull( "includes", includes );
+        checkNotNull( "excludes", excludes );
+        checkNotNull( "uri", uri );
+        if ( includes.isEmpty() && excludes.isEmpty() ) {
+            return true;
+        } else if ( includes.isEmpty() ) {
+            return !( excludes( excludes, uri ) );
+        } else if ( excludes.isEmpty() ) {
+            return includes( includes, uri );
+        }
+        return includes( includes, uri ) && !( excludes( excludes, uri ) );
+    }
+
+    public static boolean includes( final Collection<String> patterns,
+                                    final Path path ) {
+        checkNotNull( "patterns", patterns );
+        checkNotNull( "path", path );
+        return matches( patterns, path );
+    }
+
+    public static boolean includes( final Collection<String> patterns,
+                                    final URI uri ) {
+        checkNotNull( "patterns", patterns );
+        checkNotNull( "uri", uri );
+        return matches( patterns, uri );
+    }
+
+    public static boolean excludes( final Collection<String> patterns,
+                                    final URI uri ) {
+        checkNotNull( "patterns", patterns );
+        checkNotNull( "uri", uri );
+        return matches( patterns, uri );
+    }
+
+    public static boolean excludes( final Collection<String> patterns,
+                                    final Path path ) {
+        checkNotNull( "patterns", patterns );
+        checkNotNull( "path", path );
+        return matches( patterns, path );
+    }
+
+    private static boolean matches( final Collection<String> patterns,
+                                    final Path path ) {
+        return matches( patterns, path.toUri() );
+    }
+
+    private static boolean matches( final Collection<String> patterns,
+                                    final URI uri ) {
+        for ( final String pattern : patterns ) {
+            if ( matcher.match( pattern, uri.toString() ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/uberfire-io/src/test/java/org/uberfire/io/regex/AntPathMatcherTest.java b/uberfire-io/src/test/java/org/uberfire/io/regex/AntPathMatcherTest.java
new file mode 100644
index 00000000..d0b1318d
--- /dev/null
+++ b/uberfire-io/src/test/java/org/uberfire/io/regex/AntPathMatcherTest.java
@@ -0,0 +1,244 @@
+package org.uberfire.io.regex;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.uberfire.io.CommonIOServiceDotFileTest;
+import org.uberfire.io.IOService;
+import org.uberfire.io.impl.IOServiceDotFileImpl;
+import org.uberfire.java.nio.file.Path;
+import org.uberfire.java.nio.file.Paths;
+
+import static org.uberfire.io.regex.AntPathMatcher.*;
+
+public class AntPathMatcherTest {
+
+    final static IOService ioService = new IOServiceDotFileImpl();
+    private static File path = null;
+
+    @BeforeClass
+    public static void setup() throws IOException {
+        path = CommonIOServiceDotFileTest.createTempDirectory();
+        System.setProperty( "org.uberfire.nio.git.dir", path.getAbsolutePath() );
+        System.out.println( ".niogit: " + path.getAbsolutePath() );
+
+        final URI newRepo = URI.create( "git://antpathmatcher" );
+
+        ioService.newFileSystem( newRepo, new HashMap<String, Object>() );
+    }
+
+    @AfterClass
+    @BeforeClass
+    public static void cleanup() {
+        if ( path != null ) {
+            FileUtils.deleteQuietly( path );
+        }
+    }
+
+    @Test
+    public void testIncludes() {
+        final Collection<String> patterns = new ArrayList<String>() {{
+            add( "git://**" );
+            add( "**/repo/**" );
+        }};
+
+        {
+            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
+            Assert.assertFalse( includes( patterns, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
+            Assert.assertTrue( includes( patterns, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://master@antpathmatcher" ) );
+            Assert.assertTrue( includes( patterns, path ) );
+        }
+    }
+
+    @Test
+    public void testIncludesMid() {
+        final Collection<String> patterns = new ArrayList<String>() {{
+            add( "default://**" );
+            add( "**/repo/**" );
+        }};
+
+        {
+            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
+            Assert.assertTrue( includes( patterns, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
+            Assert.assertFalse( includes( patterns, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://master@antpathmatcher/repo/sss" ) );
+            Assert.assertTrue( includes( patterns, path ) );
+        }
+    }
+
+    @Test
+    public void testExcludes() {
+        final Collection<String> patterns = new ArrayList<String>() {{
+            add( "git://**" );
+            add( "**/repo/**" );
+        }};
+
+        {
+            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
+            Assert.assertFalse( excludes( patterns, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
+            Assert.assertTrue( excludes( patterns, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://master@antpathmatcher" ) );
+            Assert.assertTrue( excludes( patterns, path ) );
+        }
+    }
+
+    @Test
+    public void testExcludesMid() {
+        final Collection<String> patterns = new ArrayList<String>() {{
+            add( "default://**" );
+            add( "**/repo/**" );
+        }};
+
+        {
+            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
+            Assert.assertTrue( excludes( patterns, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
+            Assert.assertFalse( excludes( patterns, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://master@antpathmatcher/repo/sss" ) );
+            Assert.assertTrue( excludes( patterns, path ) );
+        }
+    }
+
+    @Test
+    public void testFilter() {
+        final Collection<String> includes = new ArrayList<String>() {{
+            add( "git://**" );
+        }};
+        final Collection<String> excludes = new ArrayList<String>() {{
+            add( "default://**" );
+        }};
+
+        {
+            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
+            Assert.assertFalse( filter( includes, excludes, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
+            Assert.assertTrue( filter( includes, excludes, path ) );
+        }
+
+        {
+            final Path path = Paths.get( URI.create( "git://master@antpathmatcher/repo/sss" ) );
+            Assert.assertTrue( filter( includes, excludes, path ) );
+        }
+
+        Assert.assertTrue( filter( Collections.<String>emptyList(), Collections.<String>emptyList(), Paths.get( URI.create( "git://master@antpathmatcher/repo/sss" ) ) ) );
+        Assert.assertTrue( filter( Collections.<String>emptyList(), Collections.<String>emptyList(), Paths.get( URI.create( "git://antpathmatcher" ) ) ) );
+    }
+
+    @Test
+    public void testIncludesUri() {
+        final Collection<String> patterns = new ArrayList<String>() {{
+            add( "git://**" );
+            add( "**/repo/**" );
+        }};
+
+        Assert.assertFalse( includes( patterns, URI.create( "file:///Users/home" ) ) );
+
+        Assert.assertTrue( includes( patterns, URI.create( "git://antpathmatcher" ) ) );
+
+        Assert.assertTrue( includes( patterns, URI.create( "git://master@antpathmatcher" ) ) );
+    }
+
+    @Test
+    public void testIncludesMidUri() {
+        final Collection<String> patterns = new ArrayList<String>() {{
+            add( "file://**" );
+            add( "**/repo/**" );
+        }};
+
+        Assert.assertTrue( includes( patterns, URI.create( "file:///Users/home" ) ) );
+
+        Assert.assertFalse( includes( patterns, URI.create( "git://antpathmatcher" ) ) );
+
+        Assert.assertTrue( includes( patterns, URI.create( "git://master@antpathmatcher/repo/sss" ) ) );
+    }
+
+    @Test
+    public void testExcludesUri() {
+        final Collection<String> patterns = new ArrayList<String>() {{
+            add( "git://**" );
+            add( "**/repo/**" );
+        }};
+
+        Assert.assertFalse( excludes( patterns, URI.create( "file:///Users/home" ) ) );
+
+        Assert.assertTrue( excludes( patterns, URI.create( "git://antpathmatcher" ) ) );
+
+        Assert.assertTrue( excludes( patterns, URI.create( "git://master@antpathmatcher" ) ) );
+    }
+
+    @Test
+    public void testExcludesMidUri() {
+        final Collection<String> patterns = new ArrayList<String>() {{
+            add( "file://**" );
+            add( "**/repo/**" );
+        }};
+
+        Assert.assertTrue( excludes( patterns, URI.create( "file:///Users/home" ) ) );
+
+        Assert.assertFalse( excludes( patterns, URI.create( "git://antpathmatcher" ) ) );
+
+        Assert.assertTrue( excludes( patterns, URI.create( "git://master@antpathmatcher/repo/sss" ) ) );
+    }
+
+    @Test
+    public void testFilterUri() {
+        final Collection<String> includes = new ArrayList<String>() {{
+            add( "git://**" );
+        }};
+        final Collection<String> excludes = new ArrayList<String>() {{
+            add( "file://**" );
+        }};
+
+        Assert.assertFalse( filter( includes, excludes, URI.create( "file:///Users/home" ) ) );
+
+        Assert.assertTrue( filter( includes, excludes, URI.create( "git://antpathmatcher" ) ) );
+
+        Assert.assertTrue( filter( includes, excludes, URI.create( "git://master@antpathmatcher/repo/sss" ) ) );
+
+        Assert.assertTrue( filter( Collections.<String>emptyList(), Collections.<String>emptyList(), URI.create( "file:///Users/home" ) ) );
+
+        Assert.assertTrue( filter( Collections.<String>emptyList(), Collections.<String>emptyList(), URI.create( "git://master@antpathmatcher/repo/sss" ) ) );
+
+    }
+}
diff --git a/uberfire-security/uberfire-security-server/src/main/java/org/uberfire/security/server/URLResourceManager.java b/uberfire-security/uberfire-security-server/src/main/java/org/uberfire/security/server/URLResourceManager.java
index 96e8fc16..0f6284b5 100644
--- a/uberfire-security/uberfire-security-server/src/main/java/org/uberfire/security/server/URLResourceManager.java
+++ b/uberfire-security/uberfire-security-server/src/main/java/org/uberfire/security/server/URLResourceManager.java
@@ -29,11 +29,11 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.uberfire.security.Resource;
 import org.uberfire.security.ResourceManager;
 import org.uberfire.security.Role;
 import org.uberfire.security.impl.RoleImpl;
-import org.uberfire.security.server.util.AntPathMatcher;
+import org.uberfire.commons.regex.util.AntPathMatcher;
 import org.yaml.snakeyaml.Yaml;
 
 import static java.util.Collections.*;
 import static org.uberfire.commons.validation.PortablePreconditions.checkNotNull;
 import static org.uberfire.commons.validation.Preconditions.*;
diff --git a/uberfire-server/src/main/java/org/uberfire/server/BaseFilteredServlet.java b/uberfire-server/src/main/java/org/uberfire/server/BaseFilteredServlet.java
new file mode 100644
index 00000000..684d3459
--- /dev/null
+++ b/uberfire-server/src/main/java/org/uberfire/server/BaseFilteredServlet.java
@@ -0,0 +1,66 @@
+package org.uberfire.server;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.uberfire.io.regex.AntPathMatcher;
+import org.uberfire.java.nio.file.Path;
+
+import static javax.servlet.http.HttpServletResponse.*;
+
+public abstract class BaseFilteredServlet extends HttpServlet {
+
+    private static final Logger logger = LoggerFactory.getLogger( BaseFilteredServlet.class );
+
+    protected Collection<String> includes = new ArrayList<String>();
+    protected Collection<String> excludes = new ArrayList<String>();
+
+    @Override
+    public void init( final ServletConfig config ) throws ServletException {
+        final String _includes = config.getInitParameter( "includes-path" );
+        if ( _includes != null && !_includes.trim().isEmpty() ) {
+            includes.addAll( Arrays.asList( _includes.split( "," ) ) );
+        }
+        final String _excludes = config.getInitParameter( "excludes-path" );
+        if ( _excludes != null && !_excludes.trim().isEmpty() ) {
+            excludes.addAll( Arrays.asList( _excludes.split( "," ) ) );
+        }
+    }
+
+    protected boolean validateAccess( final URI uri,
+                                      final HttpServletResponse response ) {
+        if ( !AntPathMatcher.filter( includes, excludes, uri ) ) {
+            logger.error( "Invalid credentials to path." );
+            try {
+                response.sendError( SC_FORBIDDEN );
+            } catch ( Exception ex ) {
+                logger.error( ex.getMessage() );
+            }
+            return false;
+        }
+        return true;
+    }
+
+    protected boolean validateAccess( final Path path,
+                                      final HttpServletResponse response ) {
+        if ( !AntPathMatcher.filter( includes, excludes, path ) ) {
+            logger.error( "Invalid credentials to path." );
+            try {
+                response.sendError( SC_FORBIDDEN );
+            } catch ( Exception ex ) {
+                logger.error( ex.getMessage() );
+            }
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/uberfire-server/src/main/java/org/uberfire/server/FileDownloadServlet.java b/uberfire-server/src/main/java/org/uberfire/server/FileDownloadServlet.java
index cfb476a5..7a7479f6 100644
--- a/uberfire-server/src/main/java/org/uberfire/server/FileDownloadServlet.java
+++ b/uberfire-server/src/main/java/org/uberfire/server/FileDownloadServlet.java
@@ -1,52 +1,59 @@
 package org.uberfire.server;
 
 import java.io.IOException;
 import java.net.URI;
-import java.net.URISyntaxException;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.uberfire.io.IOService;
 import org.uberfire.java.nio.file.Path;
 
+import static java.lang.String.*;
+
 public class FileDownloadServlet
-        extends HttpServlet {
+        extends BaseFilteredServlet {
 
-    private static final Logger logger = LoggerFactory.getLogger(FileDownloadServlet.class);
+    private static final Logger logger = LoggerFactory.getLogger( FileDownloadServlet.class );
 
     @Inject
     @Named("ioStrategy")
     private IOService ioService;
 
     @Override
-    protected void doGet(HttpServletRequest request, HttpServletResponse response)
+    protected void doGet( HttpServletRequest request,
+                          HttpServletResponse response )
             throws ServletException, IOException {
 
         try {
 
-            Path path = ioService.get(new URI(request.getParameter("path")));
+            final URI uri = new URI( request.getParameter( "path" ) );
+
+            if ( !validateAccess( uri, response ) ) {
+                return;
+            }
+
+            final Path path = ioService.get( uri );
 
-            byte[] bytes = ioService.readAllBytes(path);
+            byte[] bytes = ioService.readAllBytes( path );
 
-            response.setHeader("Content-Disposition",
-                    String.format("attachment; filename=%s;", path.getFileName().toString()));
+            response.setHeader( "Content-Disposition",
+                                format( "attachment; filename=%s;", path.getFileName().toString() ) );
 
-            response.setContentType("application/octet-stream");
+            response.setContentType( "application/octet-stream" );
 
             response.getOutputStream().write(
                     bytes,
                     0,
-                    bytes.length);
+                    bytes.length );
 
-        } catch (URISyntaxException e) {
-            logger.error("Failed to download a file.", e);
+        } catch ( final Exception e ) {
+            logger.error( "Failed to download a file.", e );
         }
 
     }
 }
diff --git a/uberfire-server/src/main/java/org/uberfire/server/FileUploadServlet.java b/uberfire-server/src/main/java/org/uberfire/server/FileUploadServlet.java
index 6b5fb71a..55c1ac1f 100644
--- a/uberfire-server/src/main/java/org/uberfire/server/FileUploadServlet.java
+++ b/uberfire-server/src/main/java/org/uberfire/server/FileUploadServlet.java
@@ -5,11 +5,10 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Iterator;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileItemFactory;
@@ -21,75 +20,92 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.uberfire.io.IOService;
 import org.uberfire.java.nio.file.Path;
 
 public class FileUploadServlet
-        extends HttpServlet {
+        extends BaseFilteredServlet {
 
-    private static final Logger logger = LoggerFactory.getLogger(FileUploadServlet.class);
+    private static final Logger logger = LoggerFactory.getLogger( FileUploadServlet.class );
 
     @Inject
     @Named("ioStrategy")
     private IOService ioService;
 
     @Override
-    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+    protected void doPost( HttpServletRequest request,
+                           HttpServletResponse response ) throws ServletException, IOException {
 
         try {
-            if (request.getParameter("path") != null) {
-                writeFile(ioService.get(new URI(request.getParameter("path"))), getFileItem(request));
+            if ( request.getParameter( "path" ) != null ) {
+
+                final URI uri = new URI( request.getParameter( "path" ) );
+
+                if ( !validateAccess( uri, response ) ) {
+                    return;
+                }
+
+                writeFile( ioService.get( uri ), getFileItem( request ) );
+
+                writeResponse( response, "OK" );
+            } else if ( request.getParameter( "folder" ) != null ) {
+
+                final URI uri = new URI( request.getParameter( "folder" ) + "/" + request.getParameter( "fileName" ) );
+
+                if ( !validateAccess( uri, response ) ) {
+                    return;
+                }
 
-                writeResponse(response, "OK");
-            } else if (request.getParameter("folder") != null) {
                 writeFile(
-                        ioService.get(new URI(request.getParameter("folder") + "/" + request.getParameter("fileName"))),
-                        getFileItem(request));
+                        ioService.get( uri ),
+                        getFileItem( request ) );
 
-                writeResponse(response, "OK");
+                writeResponse( response, "OK" );
             }
 
-        } catch (FileUploadException e) {
-            logError(e);
-            writeResponse(response, "FAIL");
-        } catch (URISyntaxException e) {
-            logError(e);
-            writeResponse(response, "FAIL");
+        } catch ( FileUploadException e ) {
+            logError( e );
+            writeResponse( response, "FAIL" );
+        } catch ( URISyntaxException e ) {
+            logError( e );
+            writeResponse( response, "FAIL" );
         }
     }
 
-    private FileItem getFileItem(HttpServletRequest request) throws FileUploadException {
-        Iterator iterator = getServletFileUpload().parseRequest(request).iterator();
-        while (iterator.hasNext()) {
+    private FileItem getFileItem( HttpServletRequest request ) throws FileUploadException {
+        Iterator iterator = getServletFileUpload().parseRequest( request ).iterator();
+        while ( iterator.hasNext() ) {
             FileItem item = (FileItem) iterator.next();
-            if (!item.isFormField()) {
+            if ( !item.isFormField() ) {
                 return item;
             }
         }
         return null;
     }
 
-    private void writeResponse(HttpServletResponse response, String ok) throws IOException {
-        response.setContentType("text/html");
-        response.getWriter().write(ok);
+    private void writeResponse( HttpServletResponse response,
+                                String ok ) throws IOException {
+        response.setContentType( "text/html" );
+        response.getWriter().write( ok );
     }
 
     private ServletFileUpload getServletFileUpload() {
         FileItemFactory factory = new DiskFileItemFactory();
-        ServletFileUpload upload = new ServletFileUpload(factory);
-        upload.setHeaderEncoding("UTF-8");
+        ServletFileUpload upload = new ServletFileUpload( factory );
+        upload.setHeaderEncoding( "UTF-8" );
         return upload;
     }
 
-    private void writeFile(Path path, FileItem uploadedItem) throws IOException {
-        if (!ioService.exists(path)) {
-            ioService.createFile(path);
+    private void writeFile( Path path,
+                            FileItem uploadedItem ) throws IOException {
+        if ( !ioService.exists( path ) ) {
+            ioService.createFile( path );
         }
 
-        ioService.write(path, IOUtils.toByteArray(uploadedItem.getInputStream()));
+        ioService.write( path, IOUtils.toByteArray( uploadedItem.getInputStream() ) );
 
         uploadedItem.getInputStream().close();
     }
 
-    private void logError(Throwable e) {
-        logger.error("Failed to upload a file.", e);
+    private void logError( Throwable e ) {
+        logger.error( "Failed to upload a file.", e );
     }
 }

Vulnerable code: /*
 * Copyright 2012 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.uberfire.security.server.util;
    public void setPathSeparator(final String pathSeparator) {
    public boolean isPattern(final String path) {
        return path.indexOf('*') != -1 || path.indexOf('?') != -1;
    public boolean match(final String pattern, final String path) {
        return doMatch(pattern, path, true);
    public boolean matchStart(final String pattern, final String path) {
        return doMatch(pattern, path, false);
     *         <code>false</code> if it didn't
    protected boolean doMatch(String pattern, String path, boolean fullMatch) {
        if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
        String[] pattDirs = tokenizeToStringArray(pattern, this.pathSeparator);
        String[] pathDirs = tokenizeToStringArray(path, this.pathSeparator);
        while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
            String patDir = pattDirs[pattIdxStart];
            if ("**".equals(patDir)) {
            if (!matchStrings(patDir, pathDirs[pathIdxStart])) {
        if (pathIdxStart > pathIdxEnd) {
            if (pattIdxStart > pattIdxEnd) {
                return pattern.endsWith(this.pathSeparator) ? path.endsWith(this.pathSeparator) : !path
                        .endsWith(this.pathSeparator);
            if (!fullMatch) {
            if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*")
                    && path.endsWith(this.pathSeparator)) {
            for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
                if (!pattDirs[i].equals("**")) {
        } else if (pattIdxStart > pattIdxEnd) {
        } else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) {
        while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
            String patDir = pattDirs[pattIdxEnd];
            if (patDir.equals("**")) {
            if (!matchStrings(patDir, pathDirs[pathIdxEnd])) {
        if (pathIdxStart > pathIdxEnd) {
            for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
                if (!pattDirs[i].equals("**")) {
        while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
            for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
                if (pattDirs[i].equals("**")) {
            if (patIdxTmp == pattIdxStart + 1) {
            for (int i = 0; i <= strLength - patLength; i++) {
                for (int j = 0; j < patLength; j++) {
                    String subPat = pattDirs[pattIdxStart + j + 1];
                    String subStr = pathDirs[pathIdxStart + i + j];
                    if (!matchStrings(subPat, subStr)) {
            if (foundIdx == -1) {
        for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
            if (!pattDirs[i].equals("**")) {
     *         <code>false</code> otherwise.
    private boolean matchStrings(String pattern, String str) {
        for (char c : patArr) {
            if (c == '*') {
        if (!containsStar) {
            if (patIdxEnd != strIdxEnd) {
            for (int i = 0; i <= patIdxEnd; i++) {
                ch = patArr[i];
                if (ch != '?') {
                    if (ch != strArr[i]) {
        if (patIdxEnd == 0) {
        while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
            if (ch != '?') {
                if (ch != strArr[strIdxStart]) {
        if (strIdxStart > strIdxEnd) {
            for (int i = patIdxStart; i <= patIdxEnd; i++) {
                if (patArr[i] != '*') {
        while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
            if (ch != '?') {
                if (ch != strArr[strIdxEnd]) {
        if (strIdxStart > strIdxEnd) {
            for (int i = patIdxStart; i <= patIdxEnd; i++) {
                if (patArr[i] != '*') {
        while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
            for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
                if (patArr[i] == '*') {
            if (patIdxTmp == patIdxStart + 1) {
            for (int i = 0; i <= strLength - patLength; i++) {
                for (int j = 0; j < patLength; j++) {
                    ch = patArr[patIdxStart + j + 1];
                    if (ch != '?') {
                        if (ch != strArr[strIdxStart + i + j]) {
            if (foundIdx == -1) {
        for (int i = patIdxStart; i <= patIdxEnd; i++) {
            if (patArr[i] != '*') {
    public String extractPathWithinPattern(String pattern, String path) {
        final String[] patternParts = tokenizeToStringArray(pattern, this.pathSeparator);
        final String[] pathParts = tokenizeToStringArray(path, this.pathSeparator);
        for (int i = 0; i < patternParts.length; i++) {
            final String patternPart = patternParts[i];
            if ((patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) && pathParts.length >= i + 1) {
                if (puts > 0 || (i == 0 && !pattern.startsWith(this.pathSeparator))) {
                    buffer.append(this.pathSeparator);
                buffer.append(pathParts[i]);
        for (int i = patternParts.length; i < pathParts.length; i++) {
            if (puts > 0 || i > 0) {
                buffer.append(this.pathSeparator);
            buffer.append(pathParts[i]);
    public static String[] tokenizeToStringArray(String str, String delimiters) {
        if (str == null) {
        final StringTokenizer st = new StringTokenizer(str, delimiters);
        while (st.hasMoreTokens()) {
            if (token.length() > 0) {
                tokens.add(token);
        return tokens.toArray(new String[tokens.size()]);
}
import org.uberfire.security.server.util.AntPathMatcher;
import java.net.URISyntaxException;
import javax.servlet.http.HttpServlet;
        extends HttpServlet {
    private static final Logger logger = LoggerFactory.getLogger(FileDownloadServlet.class);
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            Path path = ioService.get(new URI(request.getParameter("path")));
            byte[] bytes = ioService.readAllBytes(path);
            response.setHeader("Content-Disposition",
                    String.format("attachment; filename=%s;", path.getFileName().toString()));
            response.setContentType("application/octet-stream");
                    bytes.length);
        } catch (URISyntaxException e) {
            logger.error("Failed to download a file.", e);
import javax.servlet.http.HttpServlet;
        extends HttpServlet {
    private static final Logger logger = LoggerFactory.getLogger(FileUploadServlet.class);
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            if (request.getParameter("path") != null) {
                writeFile(ioService.get(new URI(request.getParameter("path"))), getFileItem(request));
                writeResponse(response, "OK");
            } else if (request.getParameter("folder") != null) {
                        ioService.get(new URI(request.getParameter("folder") + "/" + request.getParameter("fileName"))),
                        getFileItem(request));
                writeResponse(response, "OK");
        } catch (FileUploadException e) {
            logError(e);
            writeResponse(response, "FAIL");
        } catch (URISyntaxException e) {
            logError(e);
            writeResponse(response, "FAIL");
    private FileItem getFileItem(HttpServletRequest request) throws FileUploadException {
        Iterator iterator = getServletFileUpload().parseRequest(request).iterator();
        while (iterator.hasNext()) {
            if (!item.isFormField()) {
    private void writeResponse(HttpServletResponse response, String ok) throws IOException {
        response.setContentType("text/html");
        response.getWriter().write(ok);
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setHeaderEncoding("UTF-8");
    private void writeFile(Path path, FileItem uploadedItem) throws IOException {
        if (!ioService.exists(path)) {
            ioService.createFile(path);
        ioService.write(path, IOUtils.toByteArray(uploadedItem.getInputStream()));
    private void logError(Throwable e) {
        logger.error("Failed to upload a file.", e);
Fixed code: package org.uberfire.commons.regex.util;
    public void setPathSeparator( final String pathSeparator ) {
    public boolean isPattern( final String path ) {
        return path.indexOf( '*' ) != -1 || path.indexOf( '?' ) != -1;
    public boolean match( final String pattern,
                          final String path ) {
        return doMatch( pattern, path, true );
    public boolean matchStart( final String pattern,
                               final String path ) {
        return doMatch( pattern, path, false );
     * <code>false</code> if it didn't
    protected boolean doMatch( String pattern,
                               String path,
                               boolean fullMatch ) {
        if ( path.startsWith( this.pathSeparator ) != pattern.startsWith( this.pathSeparator ) ) {
        String[] pattDirs = tokenizeToStringArray( pattern, this.pathSeparator );
        String[] pathDirs = tokenizeToStringArray( path, this.pathSeparator );
        while ( pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd ) {
            String patDir = pattDirs[ pattIdxStart ];
            if ( "**".equals( patDir ) ) {
            if ( !matchStrings( patDir, pathDirs[ pathIdxStart ] ) ) {
        if ( pathIdxStart > pathIdxEnd ) {
            if ( pattIdxStart > pattIdxEnd ) {
                return pattern.endsWith( this.pathSeparator ) ? path.endsWith( this.pathSeparator ) : !path
                        .endsWith( this.pathSeparator );
            if ( !fullMatch ) {
            if ( pattIdxStart == pattIdxEnd && pattDirs[ pattIdxStart ].equals( "*" )
                    && path.endsWith( this.pathSeparator ) ) {
            for ( int i = pattIdxStart; i <= pattIdxEnd; i++ ) {
                if ( !pattDirs[ i ].equals( "**" ) ) {
        } else if ( pattIdxStart > pattIdxEnd ) {
        } else if ( !fullMatch && "**".equals( pattDirs[ pattIdxStart ] ) ) {
        while ( pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd ) {
            String patDir = pattDirs[ pattIdxEnd ];
            if ( patDir.equals( "**" ) ) {
            if ( !matchStrings( patDir, pathDirs[ pathIdxEnd ] ) ) {
        if ( pathIdxStart > pathIdxEnd ) {
            for ( int i = pattIdxStart; i <= pattIdxEnd; i++ ) {
                if ( !pattDirs[ i ].equals( "**" ) ) {
        while ( pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd ) {
            for ( int i = pattIdxStart + 1; i <= pattIdxEnd; i++ ) {
                if ( pattDirs[ i ].equals( "**" ) ) {
            if ( patIdxTmp == pattIdxStart + 1 ) {
            for ( int i = 0; i <= strLength - patLength; i++ ) {
                for ( int j = 0; j < patLength; j++ ) {
                    String subPat = pattDirs[ pattIdxStart + j + 1 ];
                    String subStr = pathDirs[ pathIdxStart + i + j ];
                    if ( !matchStrings( subPat, subStr ) ) {
            if ( foundIdx == -1 ) {
        for ( int i = pattIdxStart; i <= pattIdxEnd; i++ ) {
            if ( !pattDirs[ i ].equals( "**" ) ) {
     * <code>false</code> otherwise.
    private boolean matchStrings( String pattern,
                                  String str ) {
        for ( char c : patArr ) {
            if ( c == '*' ) {
        if ( !containsStar ) {
            if ( patIdxEnd != strIdxEnd ) {
            for ( int i = 0; i <= patIdxEnd; i++ ) {
                ch = patArr[ i ];
                if ( ch != '?' ) {
                    if ( ch != strArr[ i ] ) {
        if ( patIdxEnd == 0 ) {
        while ( ( ch = patArr[ patIdxStart ] ) != '*' && strIdxStart <= strIdxEnd ) {
            if ( ch != '?' ) {
                if ( ch != strArr[ strIdxStart ] ) {
        if ( strIdxStart > strIdxEnd ) {
            for ( int i = patIdxStart; i <= patIdxEnd; i++ ) {
                if ( patArr[ i ] != '*' ) {
        while ( ( ch = patArr[ patIdxEnd ] ) != '*' && strIdxStart <= strIdxEnd ) {
            if ( ch != '?' ) {
                if ( ch != strArr[ strIdxEnd ] ) {
        if ( strIdxStart > strIdxEnd ) {
            for ( int i = patIdxStart; i <= patIdxEnd; i++ ) {
                if ( patArr[ i ] != '*' ) {
        while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd ) {
            for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ ) {
                if ( patArr[ i ] == '*' ) {
            if ( patIdxTmp == patIdxStart + 1 ) {
            for ( int i = 0; i <= strLength - patLength; i++ ) {
                for ( int j = 0; j < patLength; j++ ) {
                    ch = patArr[ patIdxStart + j + 1 ];
                    if ( ch != '?' ) {
                        if ( ch != strArr[ strIdxStart + i + j ] ) {
            if ( foundIdx == -1 ) {
        for ( int i = patIdxStart; i <= patIdxEnd; i++ ) {
            if ( patArr[ i ] != '*' ) {
    public String extractPathWithinPattern( String pattern,
                                            String path ) {
        final String[] patternParts = tokenizeToStringArray( pattern, this.pathSeparator );
        final String[] pathParts = tokenizeToStringArray( path, this.pathSeparator );
        for ( int i = 0; i < patternParts.length; i++ ) {
            final String patternPart = patternParts[ i ];
            if ( ( patternPart.indexOf( '*' ) > -1 || patternPart.indexOf( '?' ) > -1 ) && pathParts.length >= i + 1 ) {
                if ( puts > 0 || ( i == 0 && !pattern.startsWith( this.pathSeparator ) ) ) {
                    buffer.append( this.pathSeparator );
                buffer.append( pathParts[ i ] );
        for ( int i = patternParts.length; i < pathParts.length; i++ ) {
            if ( puts > 0 || i > 0 ) {
                buffer.append( this.pathSeparator );
            buffer.append( pathParts[ i ] );
    public static String[] tokenizeToStringArray( String str,
                                                  String delimiters ) {
        if ( str == null ) {
        final StringTokenizer st = new StringTokenizer( str, delimiters );
        while ( st.hasMoreTokens() ) {
            if ( token.length() > 0 ) {
                tokens.add( token );
        return tokens.toArray( new String[ tokens.size() ] );
}
package org.uberfire.io.regex;

import java.net.URI;
import java.util.Collection;

import org.uberfire.java.nio.file.Path;

import static org.uberfire.commons.validation.Preconditions.*;

public final class AntPathMatcher {

    private static org.uberfire.commons.regex.util.AntPathMatcher matcher = new org.uberfire.commons.regex.util.AntPathMatcher();

    public static boolean filter( final Collection<String> includes,
                                  final Collection<String> excludes,
                                  final Path path ) {
        checkNotNull( "includes", includes );
        checkNotNull( "excludes", excludes );
        checkNotNull( "path", path );
        if ( includes.isEmpty() && excludes.isEmpty() ) {
            return true;
        } else if ( includes.isEmpty() ) {
            return !( excludes( excludes, path ) );
        } else if ( excludes.isEmpty() ) {
            return includes( includes, path );
        }
        return includes( includes, path ) && !( excludes( excludes, path ) );
    }

    public static boolean filter( final Collection<String> includes,
                                  final Collection<String> excludes,
                                  final URI uri ) {
        checkNotNull( "includes", includes );
        checkNotNull( "excludes", excludes );
        checkNotNull( "uri", uri );
        if ( includes.isEmpty() && excludes.isEmpty() ) {
            return true;
        } else if ( includes.isEmpty() ) {
            return !( excludes( excludes, uri ) );
        } else if ( excludes.isEmpty() ) {
            return includes( includes, uri );
        }
        return includes( includes, uri ) && !( excludes( excludes, uri ) );
    }

    public static boolean includes( final Collection<String> patterns,
                                    final Path path ) {
        checkNotNull( "patterns", patterns );
        checkNotNull( "path", path );
        return matches( patterns, path );
    }

    public static boolean includes( final Collection<String> patterns,
                                    final URI uri ) {
        checkNotNull( "patterns", patterns );
        checkNotNull( "uri", uri );
        return matches( patterns, uri );
    }

    public static boolean excludes( final Collection<String> patterns,
                                    final URI uri ) {
        checkNotNull( "patterns", patterns );
        checkNotNull( "uri", uri );
        return matches( patterns, uri );
    }

    public static boolean excludes( final Collection<String> patterns,
                                    final Path path ) {
        checkNotNull( "patterns", patterns );
        checkNotNull( "path", path );
        return matches( patterns, path );
    }

    private static boolean matches( final Collection<String> patterns,
                                    final Path path ) {
        return matches( patterns, path.toUri() );
    }

    private static boolean matches( final Collection<String> patterns,
                                    final URI uri ) {
        for ( final String pattern : patterns ) {
            if ( matcher.match( pattern, uri.toString() ) ) {
                return true;
            }
        }
        return false;
    }

}
package org.uberfire.io.regex;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;

import org.apache.commons.io.FileUtils;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.uberfire.io.CommonIOServiceDotFileTest;
import org.uberfire.io.IOService;
import org.uberfire.io.impl.IOServiceDotFileImpl;
import org.uberfire.java.nio.file.Path;
import org.uberfire.java.nio.file.Paths;

import static org.uberfire.io.regex.AntPathMatcher.*;

public class AntPathMatcherTest {

    final static IOService ioService = new IOServiceDotFileImpl();
    private static File path = null;

    @BeforeClass
    public static void setup() throws IOException {
        path = CommonIOServiceDotFileTest.createTempDirectory();
        System.setProperty( "org.uberfire.nio.git.dir", path.getAbsolutePath() );
        System.out.println( ".niogit: " + path.getAbsolutePath() );

        final URI newRepo = URI.create( "git://antpathmatcher" );

        ioService.newFileSystem( newRepo, new HashMap<String, Object>() );
    }

    @AfterClass
    @BeforeClass
    public static void cleanup() {
        if ( path != null ) {
            FileUtils.deleteQuietly( path );
        }
    }

    @Test
    public void testIncludes() {
        final Collection<String> patterns = new ArrayList<String>() {{
            add( "git://**" );
            add( "**/repo/**" );
        }};

        {
            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
            Assert.assertFalse( includes( patterns, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
            Assert.assertTrue( includes( patterns, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://master@antpathmatcher" ) );
            Assert.assertTrue( includes( patterns, path ) );
        }
    }

    @Test
    public void testIncludesMid() {
        final Collection<String> patterns = new ArrayList<String>() {{
            add( "default://**" );
            add( "**/repo/**" );
        }};

        {
            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
            Assert.assertTrue( includes( patterns, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
            Assert.assertFalse( includes( patterns, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://master@antpathmatcher/repo/sss" ) );
            Assert.assertTrue( includes( patterns, path ) );
        }
    }

    @Test
    public void testExcludes() {
        final Collection<String> patterns = new ArrayList<String>() {{
            add( "git://**" );
            add( "**/repo/**" );
        }};

        {
            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
            Assert.assertFalse( excludes( patterns, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
            Assert.assertTrue( excludes( patterns, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://master@antpathmatcher" ) );
            Assert.assertTrue( excludes( patterns, path ) );
        }
    }

    @Test
    public void testExcludesMid() {
        final Collection<String> patterns = new ArrayList<String>() {{
            add( "default://**" );
            add( "**/repo/**" );
        }};

        {
            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
            Assert.assertTrue( excludes( patterns, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
            Assert.assertFalse( excludes( patterns, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://master@antpathmatcher/repo/sss" ) );
            Assert.assertTrue( excludes( patterns, path ) );
        }
    }

    @Test
    public void testFilter() {
        final Collection<String> includes = new ArrayList<String>() {{
            add( "git://**" );
        }};
        final Collection<String> excludes = new ArrayList<String>() {{
            add( "default://**" );
        }};

        {
            final Path path = Paths.get( URI.create( "file:///Users/home" ) );
            Assert.assertFalse( filter( includes, excludes, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://antpathmatcher" ) );
            Assert.assertTrue( filter( includes, excludes, path ) );
        }

        {
            final Path path = Paths.get( URI.create( "git://master@antpathmatcher/repo/sss" ) );
            Assert.assertTrue( filter( includes, excludes, path ) );
        }

        Assert.assertTrue( filter( Collections.<String>emptyList(), Collections.<String>emptyList(), Paths.get( URI.create( "git://master@antpathmatcher/repo/sss" ) ) ) );
        Assert.assertTrue( filter( Collections.<String>emptyList(), Collections.<String>emptyList(), Paths.get( URI.create( "git://antpathmatcher" ) ) ) );
    }

    @Test
    public void testIncludesUri() {
        final Collection<String> patterns = new ArrayList<String>() {{
            add( "git://**" );
            add( "**/repo/**" );
        }};

        Assert.assertFalse( includes( patterns, URI.create( "file:///Users/home" ) ) );

        Assert.assertTrue( includes( patterns, URI.create( "git://antpathmatcher" ) ) );

        Assert.assertTrue( includes( patterns, URI.create( "git://master@antpathmatcher" ) ) );
    }

    @Test
    public void testIncludesMidUri() {
        final Collection<String> patterns = new ArrayList<String>() {{
            add( "file://**" );
            add( "**/repo/**" );
        }};

        Assert.assertTrue( includes( patterns, URI.create( "file:///Users/home" ) ) );

        Assert.assertFalse( includes( patterns, URI.create( "git://antpathmatcher" ) ) );

        Assert.assertTrue( includes( patterns, URI.create( "git://master@antpathmatcher/repo/sss" ) ) );
    }

    @Test
    public void testExcludesUri() {
        final Collection<String> patterns = new ArrayList<String>() {{
            add( "git://**" );
            add( "**/repo/**" );
        }};

        Assert.assertFalse( excludes( patterns, URI.create( "file:///Users/home" ) ) );

        Assert.assertTrue( excludes( patterns, URI.create( "git://antpathmatcher" ) ) );

        Assert.assertTrue( excludes( patterns, URI.create( "git://master@antpathmatcher" ) ) );
    }

    @Test
    public void testExcludesMidUri() {
        final Collection<String> patterns = new ArrayList<String>() {{
            add( "file://**" );
            add( "**/repo/**" );
        }};

        Assert.assertTrue( excludes( patterns, URI.create( "file:///Users/home" ) ) );

        Assert.assertFalse( excludes( patterns, URI.create( "git://antpathmatcher" ) ) );

        Assert.assertTrue( excludes( patterns, URI.create( "git://master@antpathmatcher/repo/sss" ) ) );
    }

    @Test
    public void testFilterUri() {
        final Collection<String> includes = new ArrayList<String>() {{
            add( "git://**" );
        }};
        final Collection<String> excludes = new ArrayList<String>() {{
            add( "file://**" );
        }};

        Assert.assertFalse( filter( includes, excludes, URI.create( "file:///Users/home" ) ) );

        Assert.assertTrue( filter( includes, excludes, URI.create( "git://antpathmatcher" ) ) );

        Assert.assertTrue( filter( includes, excludes, URI.create( "git://master@antpathmatcher/repo/sss" ) ) );

        Assert.assertTrue( filter( Collections.<String>emptyList(), Collections.<String>emptyList(), URI.create( "file:///Users/home" ) ) );

        Assert.assertTrue( filter( Collections.<String>emptyList(), Collections.<String>emptyList(), URI.create( "git://master@antpathmatcher/repo/sss" ) ) );

    }
}
import org.uberfire.commons.regex.util.AntPathMatcher;
package org.uberfire.server;

import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.uberfire.io.regex.AntPathMatcher;
import org.uberfire.java.nio.file.Path;

import static javax.servlet.http.HttpServletResponse.*;

public abstract class BaseFilteredServlet extends HttpServlet {

    private static final Logger logger = LoggerFactory.getLogger( BaseFilteredServlet.class );

    protected Collection<String> includes = new ArrayList<String>();
    protected Collection<String> excludes = new ArrayList<String>();

    @Override
    public void init( final ServletConfig config ) throws ServletException {
        final String _includes = config.getInitParameter( "includes-path" );
        if ( _includes != null && !_includes.trim().isEmpty() ) {
            includes.addAll( Arrays.asList( _includes.split( "," ) ) );
        }
        final String _excludes = config.getInitParameter( "excludes-path" );
        if ( _excludes != null && !_excludes.trim().isEmpty() ) {
            excludes.addAll( Arrays.asList( _excludes.split( "," ) ) );
        }
    }

    protected boolean validateAccess( final URI uri,
                                      final HttpServletResponse response ) {
        if ( !AntPathMatcher.filter( includes, excludes, uri ) ) {
            logger.error( "Invalid credentials to path." );
            try {
                response.sendError( SC_FORBIDDEN );
            } catch ( Exception ex ) {
                logger.error( ex.getMessage() );
            }
            return false;
        }
        return true;
    }

    protected boolean validateAccess( final Path path,
                                      final HttpServletResponse response ) {
        if ( !AntPathMatcher.filter( includes, excludes, path ) ) {
            logger.error( "Invalid credentials to path." );
            try {
                response.sendError( SC_FORBIDDEN );
            } catch ( Exception ex ) {
                logger.error( ex.getMessage() );
            }
            return false;
        }
        return true;
    }

}
import static java.lang.String.*;

        extends BaseFilteredServlet {
    private static final Logger logger = LoggerFactory.getLogger( FileDownloadServlet.class );
    protected void doGet( HttpServletRequest request,
                          HttpServletResponse response )
            final URI uri = new URI( request.getParameter( "path" ) );

            if ( !validateAccess( uri, response ) ) {
                return;
            }

            final Path path = ioService.get( uri );
            byte[] bytes = ioService.readAllBytes( path );
            response.setHeader( "Content-Disposition",
                                format( "attachment; filename=%s;", path.getFileName().toString() ) );
            response.setContentType( "application/octet-stream" );
                    bytes.length );
        } catch ( final Exception e ) {
            logger.error( "Failed to download a file.", e );
        extends BaseFilteredServlet {
    private static final Logger logger = LoggerFactory.getLogger( FileUploadServlet.class );
    protected void doPost( HttpServletRequest request,
                           HttpServletResponse response ) throws ServletException, IOException {
            if ( request.getParameter( "path" ) != null ) {

                final URI uri = new URI( request.getParameter( "path" ) );

                if ( !validateAccess( uri, response ) ) {
                    return;
                }

                writeFile( ioService.get( uri ), getFileItem( request ) );

                writeResponse( response, "OK" );
            } else if ( request.getParameter( "folder" ) != null ) {

                final URI uri = new URI( request.getParameter( "folder" ) + "/" + request.getParameter( "fileName" ) );

                if ( !validateAccess( uri, response ) ) {
                    return;
                }
                        ioService.get( uri ),
                        getFileItem( request ) );
                writeResponse( response, "OK" );
        } catch ( FileUploadException e ) {
            logError( e );
            writeResponse( response, "FAIL" );
        } catch ( URISyntaxException e ) {
            logError( e );
            writeResponse( response, "FAIL" );
    private FileItem getFileItem( HttpServletRequest request ) throws FileUploadException {
        Iterator iterator = getServletFileUpload().parseRequest( request ).iterator();
        while ( iterator.hasNext() ) {
            if ( !item.isFormField() ) {
    private void writeResponse( HttpServletResponse response,
                                String ok ) throws IOException {
        response.setContentType( "text/html" );
        response.getWriter().write( ok );
        ServletFileUpload upload = new ServletFileUpload( factory );
        upload.setHeaderEncoding( "UTF-8" );
    private void writeFile( Path path,
                            FileItem uploadedItem ) throws IOException {
        if ( !ioService.exists( path ) ) {
            ioService.createFile( path );
        ioService.write( path, IOUtils.toByteArray( uploadedItem.getInputStream() ) );
    private void logError( Throwable e ) {
        logger.error( "Failed to upload a file.", e );