CVE-2014-8114 (Java, published 2015-02-20T16:59Z)
Description: 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.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-264 \u2014 Permissions, Privileges, and Access Controls
Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.
Repository: https://github.com/uberfire/uberfire
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 message: BZ(1169544,1169556, 1169557,1169559,1169560): improvements on security related to file access


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 );