com.afis.jx.ckfinder.connector.utils.FileUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.afis.jx.ckfinder.connector.utils.FileUtils.java

Source

/*
 * CKFinder
 * ========
 * http://cksource.com/ckfinder
 * Copyright (C) 2007-2015, CKSource - Frederico Knabben. All rights reserved.
 *
 * The software, this file and its contents are subject to the CKFinder
 * License. Please read the license.txt file before using, installing, copying,
 * modifying or distribute this file or part of its contents. The contents of
 * this file is part of the Source Code of CKFinder.
 */
package com.afis.jx.ckfinder.connector.utils;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletContext;

import org.apache.commons.fileupload.FileItem;

import com.afis.jx.ckfinder.connector.ServletContextFactory;
import com.afis.jx.ckfinder.connector.configuration.Constants;
import com.afis.jx.ckfinder.connector.configuration.IConfiguration;
import com.afis.jx.ckfinder.connector.data.ResourceType;
import com.afis.jx.ckfinder.connector.errors.ConnectorException;

/**
 * Utils for files.
 *
 */
public class FileUtils {

    /**
     * max read file buffer size.
     */
    private static final int MAX_BUFFER_SIZE = 1024;
    private static final Map<String, String> UTF8_LOWER_ACCENTS = new HashMap<String, String>();
    private static final Map<String, String> UTF8_UPPER_ACCENTS = new HashMap<String, String>();
    private static final Map<String, String> encodingMap;
    private static final Pattern drivePatt = Pattern.compile("^[a-zA-Z]{1}:[/\\\\]");
    private static final Pattern invalidFileNamePatt = Pattern.compile(Constants.INVALID_FILE_NAME_REGEX);
    private static final Logger fileUtilsLogger = Logger.getLogger(FileUtils.class.getName());
    private static final String WEB_INF_FOLDER_NAME = "/WEB-INF/";
    private static final String ROOT_FOLDER_NAME = "/ROOT";
    private static final String DOMAINS_FOLDER_NAME = "/domains/";
    private static final String DOCROOT_FOLDER_NAME = "/docroot";
    private static final String CKFINDER_FOLDER_NAME = "/ckfinder";
    private static String fuClassPath;

    static {
        Map<String, String> mapHelper = new HashMap<String, String>();
        mapHelper.put("%21", "!");
        mapHelper.put("%27", "'");
        mapHelper.put("%28", "(");
        mapHelper.put("%29", ")");
        mapHelper.put("%7E", "~");
        mapHelper.put("[+]", "%20");
        encodingMap = Collections.unmodifiableMap(mapHelper);
    }

    /**
     * Gets list of children folder or files for dir, according to searchDirs param.
     *
     * @param dir folder to search.
     * @param searchDirs if true method return list of folders, otherwise list of files.
     * @return list of files or subdirectories in selected directory
     */
    public static List<String> findChildrensList(final File dir, final boolean searchDirs) {
        List<String> files = new ArrayList<String>();
        for (String subFiles : dir.list()) {
            File file = new File(dir + "/" + subFiles);
            if ((searchDirs && file.isDirectory()) || (!searchDirs && !file.isDirectory())) {
                files.add(file.getName());
            }
        }
        return files;
    }

    /**
     * Gets file extension.
     *
     * @param fileName name of file.
     * @param shortExtensionMode
     * @return file extension
     */
    public static String getFileExtension(final String fileName, final boolean shortExtensionMode) {
        if (shortExtensionMode) {
            return FileUtils.getFileExtension(fileName);
        }
        if (fileName == null || fileName.indexOf(".") == -1 || fileName.indexOf(".") == fileName.length() - 1) {
            return null;
        }
        return fileName.substring(fileName.indexOf(".") + 1);
    }

    /**
     * Gets file last extension.
     *
     * @param fileName name of file.
     * @return file extension
     */
    public static String getFileExtension(final String fileName) {
        if (fileName == null || fileName.lastIndexOf(".") == -1
                || fileName.lastIndexOf(".") == fileName.length() - 1) {
            return null;
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    /**
     * Gets file name without its extension.
     *
     * @param fileName name of file
     * @param shortExtensionMode
     * @return file extension
     */
    public static String getFileNameWithoutExtension(final String fileName, final boolean shortExtensionMode) {
        if (shortExtensionMode) {
            return FileUtils.getFileNameWithoutExtension(fileName);
        }

        if (fileName == null || fileName.indexOf(".") == -1) {
            return null;
        }
        return fileName.substring(0, fileName.indexOf("."));
    }

    /**
     * Gets file name without its last extension.
     *
     * @param fileName name of file
     * @return file extension
     */
    public static String getFileNameWithoutExtension(final String fileName) {
        if (fileName == null || fileName.lastIndexOf(".") == -1) {
            return null;
        }
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    /**
     * Print file content to outputstream.
     *
     * @param file file to be printed.
     * @param out outputstream.
     * @throws IOException when io error occurs.
     */
    public static void printFileContentToResponse(final File file, final OutputStream out) throws IOException {
        FileInputStream in = null;
        if (file.length() == 0) {
            return;
        }
        try {
            in = new FileInputStream(file);
            byte[] buf;
            if (file.length() < MAX_BUFFER_SIZE) {
                buf = new byte[(int) file.length()];
            } else {
                buf = new byte[MAX_BUFFER_SIZE];
            }

            int numRead;
            while ((numRead = in.read(buf)) != -1) {
                out.write(buf, 0, numRead);
            }
        } catch (IOException e) {
            throw e;
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                fileUtilsLogger.log(Level.SEVERE, "Error when closing stream.", e);
            }
        }
    }

    /**
     *
     * @param sourceFile source file
     * @param destFile destination file
     * @param move if source file should be deleted.
     * @param conf connector configuration
     * @return true if file moved/copied correctly
     * @throws IOException when IOerror occurs
     */
    public static boolean copyFromSourceToDestFile(final File sourceFile, final File destFile, final boolean move,
            final IConfiguration conf) throws IOException {
        createPath(destFile, true);
        InputStream in = new FileInputStream(sourceFile);
        OutputStream out = new FileOutputStream(destFile);
        byte[] buf = new byte[MAX_BUFFER_SIZE];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
        if (move) {
            sourceFile.delete();
        }
        return true;

    }

    /**
     * Gets an absolute path to CKFinder file or folder for which path was provided as parameter.
     *
     * @param path relative or absolute path to a CKFinder resource (file or folder).
     * @param isAbsolute flag indicating if path to resource is absolute e.g. /usr/john/userfiles or "C:\\userfiles". If this parameter is
     * set to true path will be returned as is.
     * @param shouldExist flag indicating if resource, represented by path parameter, should exist (e.g. configuration file) in file system
     * or not (e.g. userfiles folder).<br>
     * If this parameter is set to true, path to file will only be returned if such file exists. If file can't be found, method will return
     * null.
     * @return an absolute path to a resource in CKFinder
     * @throws ConnectorException when {@code ServletContext} is {@code null} or full path to resource cannot be obtained.
     */
    public static String getFullPath(String path, boolean isAbsolute, boolean shouldExist)
            throws ConnectorException {
        if (path != null && !path.equals("")) {
            if (isAbsolute) {
                if (path.startsWith("/")) {
                    //Check if this isn't Windows Path.
                    String temporary = PathUtils.removeSlashFromBeginning(path);
                    if (isStartsWithPattern(drivePatt, temporary)) {
                        path = temporary;
                    }
                }
                return checkAndReturnPath(shouldExist, path);
            } else {
                ServletContext sc = ServletContextFactory.getServletContext();
                String tempPath = PathUtils.addSlashToEnd(PathUtils.addSlashToBeginning(path));
                try {
                    java.net.URL url = sc.getResource(tempPath);
                    //For srevers like Tomcat 6-7 the getResource method returns JNDI URL.
                    if (url != null && url.getProtocol() != null && url.getProtocol().equalsIgnoreCase("jndi")) {
                        //Assume file is inside application context and try to get path.
                        //This method will fail if war is not exploaded.
                        String result = sc.getRealPath(tempPath.replace(sc.getContextPath(), ""));
                        if (result != null) {
                            return result;
                        } else {
                            //If application is packed, we have to try constructing the path manually.
                            result = getClassPath();
                            if (tempPath.indexOf(sc.getContextPath() + "/") >= 0
                                    && result.indexOf(sc.getContextPath() + "/") >= 0) {
                                result = result.substring(0, result.indexOf(sc.getContextPath()));
                                result = result + tempPath;
                            } else if (result.indexOf(sc.getContextPath() + "/") >= 0) {
                                result = result.substring(0,
                                        result.indexOf(sc.getContextPath()) + sc.getContextPath().length());
                                result = result + tempPath;
                            }

                            result = checkAndReturnPath(shouldExist, result);
                            if (result != null) {
                                return result;
                            }
                        }

                        //At this stage path is not in application context and is not absolute.
                        //We need to reset url as we cannot determine path from it.
                        if (result == null) {
                            url = null;
                        }
                    }

                    //For servers like Tomact 8 getResource method should return file:// url.
                    if (path.startsWith("/") || isStartsWithPattern(drivePatt, path)) {
                        //This is most likely absolute path.
                        String absolutePath = checkAndReturnPath(shouldExist, path);
                        if (absolutePath != null && !absolutePath.equals("")) {
                            return absolutePath;
                        } else {
                            //If absolute path has failed, give it one last try with relative path.
                            //Either path or null will be returned.
                            return sc.getRealPath(path.replace(sc.getContextPath(), ""));
                        }
                    }
                } catch (IOException ioex) {
                    throw new ConnectorException(ioex);
                }
            }
        }
        return null;
    }

    /**
     * Checks and returns path to resource. If shouldExist parameter is set to true, resource represented by path will be checked for
     * existence. If resource exists path will be returned, {@code null} otherwise. If shouldExist parameter is set to false path will be
     * returned as is.
     *
     * @param shouldExist flag indicating if file/folder represented by path parameter should exist in file system
     * @param path string representing path to file or folder
     *
     * @return string representing path to file or null if file should exist in file system but can't be read with a given path.
     */
    private static String checkAndReturnPath(boolean shouldExist, String path) {
        if (!shouldExist) {
            return path;
        } else {
            if (isFileExist(path)) {
                return path;
            }
            return null;
        }
    }

    /**
     * Checks if file/folder specified by the path exists in file system.
     *
     * @param path absolute path to file/folder used to check file existence
     * @return {@code true} if file/folder exists, {@code false} otherwise.
     */
    private static boolean isFileExist(String path) {
        File f = new File(path);
        return f.exists();
    }

    /**
     * Gets an absolute path to CKFinder resource folder for which path is calculated from baseURL configuration property.<br>
     * This method has limited capabilities. First it will check is folder should be created in application context. If not it will try to
     * create folder in Tomcat ROOT folder or GlassFish docroot folder. If this fails this method will fall back and try to create folder
     * inside application context (features like gallery may not work in this case as most likely baseURL and baseDir point to different
     * locations).<br>
     * Finally if nothing worked this method returns {@code null}.
     *
     * @param path relative or absolute path to a CKFinder folder.
     * @return an absolute path to a folder in CKFinder
     * @throws ConnectorException when {@code ServletContext} is {@code null} or path to resource cannot be obtained.
     */
    public static String calculatePathFromBaseUrl(String path) throws ConnectorException {
        if (path != null && !path.equals("")) {
            ServletContext sc = ServletContextFactory.getServletContext();
            String tempPath = PathUtils.addSlashToBeginning(path);
            String finalPath;
            if (tempPath.startsWith(sc.getContextPath() + "/")) {
                //Try creating path relative to application context.
                if ((finalPath = sc.getRealPath(tempPath.replace(sc.getContextPath(), ""))) != null) {
                    return finalPath;
                } else if ((finalPath = sc.getRealPath(CKFINDER_FOLDER_NAME)) != null) {
                    //If above is null, try getting path to direct subfolder in application context.
                    finalPath = PathUtils.escape(finalPath);
                    return finalPath.substring(0, finalPath.lastIndexOf(CKFINDER_FOLDER_NAME))
                            + tempPath.replace(sc.getContextPath(), "");
                } else {
                    finalPath = getClassPath();
                    if (finalPath.indexOf(sc.getContextPath()) >= 0) {
                        finalPath = finalPath.substring(0, finalPath.indexOf(sc.getContextPath()));
                        finalPath = finalPath + tempPath;
                        return finalPath;
                    } else {
                        finalPath = null;
                    }
                }
            } else {
                //Try creating path to ROOT on TC or docroot on GF
                finalPath = getClassPath();

                String tcPath = getTomcatRootPath(sc, finalPath);
                String gfPath = getGlassFishRootPath(sc, finalPath);
                if (!tcPath.equals("")) {
                    tempPath = filterRelativePathChars(tempPath);
                    finalPath = tcPath + tempPath;
                } else if (!gfPath.equals("")) {
                    tempPath = filterRelativePathChars(tempPath);
                    finalPath = gfPath + tempPath;
                } else {
                    //Fall back and try creating path relative application context
                    String realPath = sc.getRealPath(tempPath);
                    if (realPath != null) {
                        return realPath;
                    } else if (finalPath.indexOf(sc.getContextPath() + "/") >= 0) {
                        finalPath = finalPath.substring(0,
                                finalPath.indexOf(sc.getContextPath()) + sc.getContextPath().length());
                        tempPath = filterRelativePathChars(tempPath);
                        finalPath = finalPath + tempPath;
                    } else {
                        finalPath = null;
                    }
                }
            }
            return finalPath;
        }
        return null;
    }

    /**
     * Returns Path to Tomcat ROOT folder.
     *
     * @param sc current {@code ServletContext} object.
     * @param path String from which path to Tomcat ROOT folder will be calculated
     * @return path to Tomcat ROOT folder or empty String is path can't be found.
     */
    private static String getTomcatRootPath(ServletContext sc, String path) {
        String finalPath = "";
        int index = path.indexOf(sc.getContextPath() + WEB_INF_FOLDER_NAME);
        if (index >= 0) {
            path = path.substring(0, index);
            path = path + ROOT_FOLDER_NAME;
            if (isFileExist(path)) {
                finalPath = path;
            }
        }
        return finalPath;
    }

    /**
     * Returns Path to GlassFish docroot folder.
     *
     * @param sc current {@code ServletContext} object.
     * @param path String from which path to GlassFish docroot folder will be calculated
     * @return path to GlassFish docroot folder or empty String is path can't be found.
     */
    private static String getGlassFishRootPath(ServletContext sc, String path) {
        String finalPath = "";
        path = path.toLowerCase();
        int index = path.indexOf(DOMAINS_FOLDER_NAME);
        if (index >= 0) {
            path = PathUtils.addSlashToEnd(path);
            String key = path.substring(index + DOMAINS_FOLDER_NAME.length());
            if (!key.equals("")) {
                if (key.indexOf("/") > 0) {
                    key = key.substring(0, key.indexOf("/"));
                }
                path = path.substring(0, path.indexOf(key) + key.length()) + DOCROOT_FOLDER_NAME;
            }
            if (isFileExist(path)) {
                finalPath = path;
            }
        }
        return finalPath;
    }

    /**
     * This method removes any ".." characters from the path provided as parameter.
     *
     * @param path string representing path to remove unsafe characters from
     * @return filtered path without ".." characters.
     */
    private static String filterRelativePathChars(String path) {
        StringBuffer s = new StringBuffer(path);
        int index = s.indexOf("..");
        if (index >= 0) {
            s = s.delete(index, index + 2);
        }
        return s.toString();
    }

    /**
     * Checks if path starts with particular regular expression pattern.
     *
     * @param pattern the regular expression used to test the path
     * @param path the string representing path to test against regular expression
     * @return {@code true} if path starts with given pattern, {@code false} otherwise.
     */
    private static boolean isStartsWithPattern(Pattern pattern, String path) {
        Matcher m = pattern.matcher(path);
        if (m.find()) {
            return m.start() == 0;
        }
        return false;
    }

    /**
     * Gets absolute path to FileUtils.java file. This path is later used to calculate absolute path to other resources inside application.
     *
     * @return absolute path to FileUtils.java file.
     */
    private static String getClassPath() throws ConnectorException {
        if (fuClassPath == null || fuClassPath.equals("")) {
            java.net.URL url = FileUtils.class.getResource("FileUtils.class");
            String finalPath = null;
            String filePathPrefix = "file:/";

            if ("vfs".equalsIgnoreCase(url.getProtocol())) {
                try {
                    org.jboss.vfs.VirtualFile vFile = org.jboss.vfs.VFS.getChild(url.getPath());
                    finalPath = org.jboss.vfs.VFSUtils.getPhysicalURI(vFile).getPath();
                } catch (IOException ioex) {
                    throw new ConnectorException(ioex);
                }
            } else {
                try {
                    finalPath = url.toURI().getSchemeSpecificPart();
                } catch (URISyntaxException ueex) {
                    throw new ConnectorException(ueex);
                }
            }

            if (finalPath != null && finalPath.startsWith(filePathPrefix)) {
                finalPath = finalPath.substring(filePathPrefix.length());
            }

            if (finalPath != null && finalPath.startsWith("/")) {
                //Check if this isn't Windows Path.
                String temporary = PathUtils.removeSlashFromBeginning(finalPath);
                if (isStartsWithPattern(drivePatt, temporary)) {
                    finalPath = temporary;
                }
            }
            fuClassPath = finalPath;
        }
        return fuClassPath;
    }

    /**
     * Parse date with pattern yyyyMMddHHmm. Pattern is used in get file command response XML.
     *
     * @param file input file.
     * @return parsed file modification date.
     */
    public static String parseLastModifDate(final File file) {
        Date date = new Date(file.lastModified());
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");
        return dateFormat.format(date);
    }

    /**
     * check if dirname matches configuration hidden folder regex.
     *
     * @param dirName dir name
     * @param conf connector configuration
     * @return true if matches.
     */
    public static boolean checkIfDirIsHidden(final String dirName, final IConfiguration conf) {
        if (dirName == null || dirName.equals("")) {
            return false;
        }
        String dir = PathUtils.removeSlashFromEnd(PathUtils.escape(dirName));
        Scanner sc = new Scanner(dir).useDelimiter("/");
        while (sc.hasNext()) {
            boolean check = Pattern.compile(getHiddenFileOrFolderRegex(conf.getHiddenFolders())).matcher(sc.next())
                    .matches();
            if (check) {
                return true;
            }
        }
        return false;
    }

    /**
     * check if filename matches configuration hidden file regex.
     *
     * @param fileName file name
     * @param conf connector configuration
     * @return true if matches.
     */
    public static boolean checkIfFileIsHidden(final String fileName, final IConfiguration conf) {
        return Pattern.compile(getHiddenFileOrFolderRegex(conf.getHiddenFiles())).matcher(fileName).matches();
    }

    /**
     * get hidden folder regex pattern.
     *
     * @param hiddenList list of hidden file or files patterns.
     * @return full folder regex pattern
     */
    private static String getHiddenFileOrFolderRegex(final List<String> hiddenList) {
        StringBuilder sb = new StringBuilder("(");
        for (String item : hiddenList) {
            if (sb.length() > 3) {
                sb.append("|");
            }

            item = item.replaceAll("\\.", "\\\\.");
            item = item.replaceAll("\\*", ".+");
            item = item.replaceAll("\\?", ".");

            sb.append("(");
            sb.append(item);
            sb.append(")");

        }
        sb.append(")+");
        return sb.toString();
    }

    /**
     * deletes file or folder with all subfolders and subfiles.
     *
     * @param file file or directory to delete.
     * @return true if all files are deleted.
     */
    public static boolean delete(final File file) {

        if (file.isDirectory()) {
            for (String item : file.list()) {
                File subFile = new File(file.getAbsolutePath() + File.separator + item);
                if (!delete(subFile)) {
                    return false;
                }
            }
        }
        return file.delete();
    }

    /**
     * check if file or folder name doesn't match invalid name.
     *
     * @param fileName file name
     * @return true if file name is correct
     */
    public static boolean checkFileName(final String fileName) {
        return !(fileName == null || fileName.equals("") || fileName.charAt(fileName.length() - 1) == '.'
                || fileName.contains("..") || checkFolderNamePattern(fileName));
    }

    /**
     * check if new folder name contains disallowed chars.
     *
     * @param fileName file name
     * @return true if it does contain disallowed characters.
     */
    private static boolean checkFolderNamePattern(final String fileName) {
        return invalidFileNamePatt.matcher(fileName).find();
    }

    /**
     * checks if file extension is on denied list or isn't on allowed list.
     *
     * @param fileName filename
     * @param type resource type
     * @return 0 if ok, 1 if not ok, 2 if rename required
     */
    public static int checkFileExtension(final String fileName, final ResourceType type) {
        if (type == null || fileName == null) {
            return 1;
        }

        if (fileName.indexOf('.') == -1) {
            return 0;
        }

        return checkSingleExtension(getFileExtension(fileName), type) ? 0 : 1;
    }

    /**
     * Checks whether files extension is allowed.
     *
     * @param fileExt a string representing file extension to test
     * @param type a {@code ResourceType} object holding list of allowed and denied extensions against which parameter fileExt will be
     * tested
     * @return {@code true} is extension is on allowed extensions list or if allowed extensions is empty. The {@code false} is returned when
     * file is on denied extensions list or if none of the above conditions is met.
     */
    private static boolean checkSingleExtension(final String fileExt, final ResourceType type) {
        Scanner scanner = new Scanner(type.getDeniedExtensions()).useDelimiter(",");
        while (scanner.hasNext()) {
            if (scanner.next().equalsIgnoreCase(fileExt)) {
                return false;
            }
        }

        scanner = new Scanner(type.getAllowedExtensions()).useDelimiter(",");
        //The allowedExtensions is empty. Allow everything that isn't dissallowed.
        if (!scanner.hasNext()) {
            return true;
        }

        while (scanner.hasNext()) {
            if (scanner.next().equalsIgnoreCase(fileExt)) {
                return true;
            }
        }
        return false;
    }

    /**
     * converts filename to connector encoding.
     *
     * @param fileName file name
     * @param configuration connector configuration
     * @return encoded file name
     */
    public static String convertFromUriEncoding(final String fileName, final IConfiguration configuration) {
        try {
            return new String(fileName.getBytes(configuration.getUriEncoding()), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return fileName;
        }
    }

    /**
     * converts filename to ASCII.
     *
     * @param fileName file name
     * @return encoded file name
     */
    public static String convertToASCII(final String fileName) {
        String newFileName = fileName;
        fillLowerAccents();
        fillUpperAccents();
        for (String s : UTF8_LOWER_ACCENTS.keySet()) {
            newFileName = newFileName.replace(s, UTF8_LOWER_ACCENTS.get(s));
        }

        for (String s : UTF8_UPPER_ACCENTS.keySet()) {
            newFileName = newFileName.replace(s, UTF8_UPPER_ACCENTS.get(s));
        }
        return newFileName;
    }

    /**
     * creates file and all above folders that do not exist.
     *
     * @param file file to create.
     * @param asFile if it is path to folder.
     * @throws IOException when io error occurs.
     */
    public static void createPath(final File file, final boolean asFile) throws IOException {
        String path = file.getAbsolutePath();

        String dirPath;
        if (asFile) {
            dirPath = path.substring(0, path.lastIndexOf(File.separator));
        } else {
            dirPath = path;
        }

        File dir = new File(dirPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        if (asFile) {
            file.createNewFile();
        }
    }

    /**
     * check if file size isn't bigger then max size for type.
     *
     * @param type resource type
     * @param fileSize file size
     * @return true if file size isn't bigger then max size for type.
     */
    public static boolean checkFileSize(final ResourceType type, final long fileSize) {
        final Long maxSize = type.getMaxSize();
        return (maxSize == null || maxSize > fileSize);
    }

    /**
     * check if file has html file extension.
     *
     * @param file file name
     * @param configuration connector configuration
     * @return true if has
     */
    public static boolean checkIfFileIsHtmlFile(final String file, final IConfiguration configuration) {

        return configuration.getHTMLExtensions().contains(getFileExtension(file).toLowerCase());

    }

    /**
     * Detect HTML in the first KB to prevent against potential security issue with IE/Safari/Opera file type auto detection bug. Returns
     * true if file contain insecure HTML code at the beginning.
     *
     * @param item file upload item
     * @return true if detected.
     * @throws IOException when io error occurs.
     */
    public static boolean detectHtml(final FileItem item) throws IOException {
        byte[] buff = new byte[MAX_BUFFER_SIZE];
        InputStream is = null;
        try {
            is = item.getInputStream();
            is.read(buff, 0, MAX_BUFFER_SIZE);
            String content = new String(buff);
            content = content.toLowerCase().trim();

            if (Pattern
                    .compile("<!DOCTYPE\\W+X?HTML.+", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)
                    .matcher(content).matches()) {
                return true;
            }

            String[] tags = { "<body", "<head", "<html", "<img", "<pre", "<script", "<table", "<title" };

            for (String tag : tags) {
                if (content.indexOf(tag) != -1) {
                    return true;
                }
            }

            if (Pattern
                    .compile("type\\s*=\\s*[\'\"]?\\s*(?:\\w*/)?(?:ecma|java)",
                            Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)
                    .matcher(content).find()) {
                return true;
            }

            if (Pattern
                    .compile("(?:href|src|data)\\s*=\\s*[\'\"]?\\s*(?:ecma|java)script:",
                            Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)
                    .matcher(content).find()) {
                return true;
            }

            if (Pattern
                    .compile("url\\s*\\(\\s*[\'\"]?\\s*(?:ecma|java)script:",
                            Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE)
                    .matcher(content).find()) {
                return true;
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (is != null) {
                is.close();
            }
        }
        return false;
    }

    /**
     * Checks if folder has any subfolders but respects ACL and hideFolders setting from configuration.
     *
     * @param dirPath path to current folder.
     * @param dir current folder being checked. Represented by File object.
     * @param configuration configuration object.
     * @param resourceType name of resource type, folder is assigned to.
     * @param currentUserRole user role.
     * @return true if there are any allowed and non-hidden subfolders.
     */
    public static Boolean hasChildren(String dirPath, File dir, IConfiguration configuration, String resourceType,
            String currentUserRole) {
        FileFilter fileFilter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.isDirectory();
            }
        };
        File[] subDirsList = dir.listFiles(fileFilter);

        if (subDirsList != null) {
            for (File subDirsList1 : subDirsList) {
                String subDirName = subDirsList1.getName();
                if (!FileUtils.checkIfDirIsHidden(subDirName, configuration)
                        && AccessControlUtil.getInstance().checkFolderACL(resourceType, dirPath + subDirName,
                                currentUserRole, AccessControlUtil.CKFINDER_CONNECTOR_ACL_FOLDER_VIEW)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * rename file with double extension.
     *
     * @param type a {@code ResourceType} object holding list of allowed and denied extensions against which file extension will be tested.
     * @param fileName file name
     * @return new file name with . replaced with _ (but not last)
     */
    public static String renameFileWithBadExt(final ResourceType type, final String fileName) {
        if (type == null || fileName == null) {
            return null;
        }

        if (fileName.indexOf('.') == -1) {
            return fileName;
        }

        StringTokenizer tokens = new StringTokenizer(fileName, ".");
        String cfileName = tokens.nextToken();
        String currToken;
        while (tokens.hasMoreTokens()) {
            currToken = tokens.nextToken();
            if (tokens.hasMoreElements()) {
                cfileName = cfileName.concat(checkSingleExtension(currToken, type) ? "." : "_");
                cfileName = cfileName.concat(currToken);
            } else {
                cfileName = cfileName.concat(".".concat(currToken));
            }
        }
        return cfileName;
    }

    public static String encodeURIComponent(final String fileName) throws UnsupportedEncodingException {
        String fileNameHelper = URLEncoder.encode(fileName, "utf-8");
        for (Map.Entry<String, String> entry : encodingMap.entrySet()) {
            fileNameHelper = fileNameHelper.replaceAll(entry.getKey(), entry.getValue());
        }
        return fileNameHelper;
    }

    public static boolean checkFolderName(final String folderName, final IConfiguration configuration) {
        return !((configuration.isDisallowUnsafeCharacters()
                && (folderName.contains(".") || folderName.contains(";")))
                || FileUtils.checkFolderNamePattern(folderName));
    }

    public static boolean checkFileName(final String fileName, final IConfiguration configuration) {
        return !((configuration.isDisallowUnsafeCharacters() && fileName.contains(";"))
                || !FileUtils.checkFileName(fileName));
    }

    public static String backupWithBackSlash(final String fileName, final String toReplace) {
        return fileName.replaceAll(toReplace, "\\\\" + toReplace);
    }

    /**
     * fills data for upper accents map.
     */
    private static void fillUpperAccents() {
        if (UTF8_UPPER_ACCENTS.size() == 0) {
            UTF8_UPPER_ACCENTS.put("", "A");
            UTF8_UPPER_ACCENTS.put("", "O");
            UTF8_UPPER_ACCENTS.put("", "D");
            UTF8_UPPER_ACCENTS.put("", "F");
            UTF8_UPPER_ACCENTS.put("", "E");
            UTF8_UPPER_ACCENTS.put("", "S");
            UTF8_UPPER_ACCENTS.put("", "O");
            UTF8_UPPER_ACCENTS.put("", "A");
            UTF8_UPPER_ACCENTS.put("", "R");
            UTF8_UPPER_ACCENTS.put("", "T");
            UTF8_UPPER_ACCENTS.put("", "N");
            UTF8_UPPER_ACCENTS.put("", "A");
            UTF8_UPPER_ACCENTS.put("", "K");
            UTF8_UPPER_ACCENTS.put("", "S");
            UTF8_UPPER_ACCENTS.put("", "Y");
            UTF8_UPPER_ACCENTS.put("", "N");
            UTF8_UPPER_ACCENTS.put("", "L");
            UTF8_UPPER_ACCENTS.put("", "H");
            UTF8_UPPER_ACCENTS.put("", "P");
            UTF8_UPPER_ACCENTS.put("", "O");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "E");
            UTF8_UPPER_ACCENTS.put("", "E");
            UTF8_UPPER_ACCENTS.put("", "C");
            UTF8_UPPER_ACCENTS.put("", "W");
            UTF8_UPPER_ACCENTS.put("", "C");
            UTF8_UPPER_ACCENTS.put("", "O");
            UTF8_UPPER_ACCENTS.put("", "S");
            UTF8_UPPER_ACCENTS.put("", "O");
            UTF8_UPPER_ACCENTS.put("", "G");
            UTF8_UPPER_ACCENTS.put("", "T");
            UTF8_UPPER_ACCENTS.put("", "S");
            UTF8_UPPER_ACCENTS.put("", "E");
            UTF8_UPPER_ACCENTS.put("", "C");
            UTF8_UPPER_ACCENTS.put("", "S");
            UTF8_UPPER_ACCENTS.put("", "I");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "C");
            UTF8_UPPER_ACCENTS.put("", "E");
            UTF8_UPPER_ACCENTS.put("", "W");
            UTF8_UPPER_ACCENTS.put("", "T");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "C");
            UTF8_UPPER_ACCENTS.put("", "Oe");
            UTF8_UPPER_ACCENTS.put("", "E");
            UTF8_UPPER_ACCENTS.put("", "Y");
            UTF8_UPPER_ACCENTS.put("", "A");
            UTF8_UPPER_ACCENTS.put("?", "L");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "S");
            UTF8_UPPER_ACCENTS.put("", "G");
            UTF8_UPPER_ACCENTS.put("", "L");
            UTF8_UPPER_ACCENTS.put("", "F");
            UTF8_UPPER_ACCENTS.put("", "Z");
            UTF8_UPPER_ACCENTS.put("", "W");
            UTF8_UPPER_ACCENTS.put("", "B");
            UTF8_UPPER_ACCENTS.put("", "A");
            UTF8_UPPER_ACCENTS.put("", "I");
            UTF8_UPPER_ACCENTS.put("?", "I");
            UTF8_UPPER_ACCENTS.put("", "D");
            UTF8_UPPER_ACCENTS.put("", "T");
            UTF8_UPPER_ACCENTS.put("", "R");
            UTF8_UPPER_ACCENTS.put("", "Ae");
            UTF8_UPPER_ACCENTS.put("?", "I");
            UTF8_UPPER_ACCENTS.put("", "R");
            UTF8_UPPER_ACCENTS.put("", "E");
            UTF8_UPPER_ACCENTS.put("", "Ue");
            UTF8_UPPER_ACCENTS.put("", "O");
            UTF8_UPPER_ACCENTS.put("", "E");
            UTF8_UPPER_ACCENTS.put("", "N");
            UTF8_UPPER_ACCENTS.put("", "N");
            UTF8_UPPER_ACCENTS.put("", "H");
            UTF8_UPPER_ACCENTS.put("", "G");
            UTF8_UPPER_ACCENTS.put("?", "D");
            UTF8_UPPER_ACCENTS.put("", "J");
            UTF8_UPPER_ACCENTS.put("", "Y");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "T");
            UTF8_UPPER_ACCENTS.put("?", "Y");
            UTF8_UPPER_ACCENTS.put("?", "O");
            UTF8_UPPER_ACCENTS.put("", "Y");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "T");
            UTF8_UPPER_ACCENTS.put("?", "Y");
            UTF8_UPPER_ACCENTS.put("?", "O");
            UTF8_UPPER_ACCENTS.put("", "A");
            UTF8_UPPER_ACCENTS.put("", "L");
            UTF8_UPPER_ACCENTS.put("", "W");
            UTF8_UPPER_ACCENTS.put("", "Z");
            UTF8_UPPER_ACCENTS.put("", "I");
            UTF8_UPPER_ACCENTS.put("", "A");
            UTF8_UPPER_ACCENTS.put("", "G");
            UTF8_UPPER_ACCENTS.put("", "M");
            UTF8_UPPER_ACCENTS.put("", "O");
            UTF8_UPPER_ACCENTS.put("", "I");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "I");
            UTF8_UPPER_ACCENTS.put("", "Z");
            UTF8_UPPER_ACCENTS.put("?", "A");
            UTF8_UPPER_ACCENTS.put("", "U");
            UTF8_UPPER_ACCENTS.put("", "Th");
            UTF8_UPPER_ACCENTS.put("?", "Dh");
            UTF8_UPPER_ACCENTS.put("", "Ae");
            UTF8_UPPER_ACCENTS.put("", "E");
        }
    }

    /**
     * fills data for lower accents map.
     */
    private static void fillLowerAccents() {
        if (UTF8_LOWER_ACCENTS.size() == 0) {
            UTF8_LOWER_ACCENTS.put("", "a");
            UTF8_LOWER_ACCENTS.put("", "o");
            UTF8_LOWER_ACCENTS.put("?", "d");
            UTF8_LOWER_ACCENTS.put("", "f");
            UTF8_LOWER_ACCENTS.put("", "e");
            UTF8_LOWER_ACCENTS.put("", "s");
            UTF8_LOWER_ACCENTS.put("", "o");
            UTF8_LOWER_ACCENTS.put("", "ss");
            UTF8_LOWER_ACCENTS.put("", "a");
            UTF8_LOWER_ACCENTS.put("", "r");
            UTF8_LOWER_ACCENTS.put("", "t");
            UTF8_LOWER_ACCENTS.put("", "n");
            UTF8_LOWER_ACCENTS.put("?", "a");
            UTF8_LOWER_ACCENTS.put("", "k");
            UTF8_LOWER_ACCENTS.put("?", "s");
            UTF8_LOWER_ACCENTS.put("", "y");
            UTF8_LOWER_ACCENTS.put("", "n");
            UTF8_LOWER_ACCENTS.put("", "l");
            UTF8_LOWER_ACCENTS.put("", "h");
            UTF8_LOWER_ACCENTS.put("", "p");
            UTF8_LOWER_ACCENTS.put("", "o");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "e");
            UTF8_LOWER_ACCENTS.put("", "e");
            UTF8_LOWER_ACCENTS.put("", "c");
            UTF8_LOWER_ACCENTS.put("?", "w");
            UTF8_LOWER_ACCENTS.put("", "c");
            UTF8_LOWER_ACCENTS.put("", "o");
            UTF8_LOWER_ACCENTS.put("", "s");
            UTF8_LOWER_ACCENTS.put("", "o");
            UTF8_LOWER_ACCENTS.put("", "g");
            UTF8_LOWER_ACCENTS.put("", "t");
            UTF8_LOWER_ACCENTS.put("", "s");
            UTF8_LOWER_ACCENTS.put("", "e");
            UTF8_LOWER_ACCENTS.put("", "c");
            UTF8_LOWER_ACCENTS.put("", "s");
            UTF8_LOWER_ACCENTS.put("", "i");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "c");
            UTF8_LOWER_ACCENTS.put("", "e");
            UTF8_LOWER_ACCENTS.put("", "w");
            UTF8_LOWER_ACCENTS.put("", "t");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("?", "c");
            UTF8_LOWER_ACCENTS.put("", "oe");
            UTF8_LOWER_ACCENTS.put("", "e");
            UTF8_LOWER_ACCENTS.put("", "y");
            UTF8_LOWER_ACCENTS.put("", "a");
            UTF8_LOWER_ACCENTS.put("", "l");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "s");
            UTF8_LOWER_ACCENTS.put("", "g");
            UTF8_LOWER_ACCENTS.put("", "l");
            UTF8_LOWER_ACCENTS.put("", "f");
            UTF8_LOWER_ACCENTS.put("", "z");
            UTF8_LOWER_ACCENTS.put("", "w");
            UTF8_LOWER_ACCENTS.put("", "b");
            UTF8_LOWER_ACCENTS.put("", "a");
            UTF8_LOWER_ACCENTS.put("", "i");
            UTF8_LOWER_ACCENTS.put("", "i");
            UTF8_LOWER_ACCENTS.put("", "d");
            UTF8_LOWER_ACCENTS.put("", "t");
            UTF8_LOWER_ACCENTS.put("", "r");
            UTF8_LOWER_ACCENTS.put("", "ae");
            UTF8_LOWER_ACCENTS.put("", "i");
            UTF8_LOWER_ACCENTS.put("", "r");
            UTF8_LOWER_ACCENTS.put("", "e");
            UTF8_LOWER_ACCENTS.put("", "ue");
            UTF8_LOWER_ACCENTS.put("", "o");
            UTF8_LOWER_ACCENTS.put("", "e");
            UTF8_LOWER_ACCENTS.put("", "n");
            UTF8_LOWER_ACCENTS.put("", "n");
            UTF8_LOWER_ACCENTS.put("", "h");
            UTF8_LOWER_ACCENTS.put("?", "g");
            UTF8_LOWER_ACCENTS.put("", "d");
            UTF8_LOWER_ACCENTS.put("", "j");
            UTF8_LOWER_ACCENTS.put("", "y");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "t");
            UTF8_LOWER_ACCENTS.put("", "y");
            UTF8_LOWER_ACCENTS.put("", "o");
            UTF8_LOWER_ACCENTS.put("", "a");
            UTF8_LOWER_ACCENTS.put("", "l");
            UTF8_LOWER_ACCENTS.put("", "w");
            UTF8_LOWER_ACCENTS.put("", "z");
            UTF8_LOWER_ACCENTS.put("", "i");
            UTF8_LOWER_ACCENTS.put("", "a");
            UTF8_LOWER_ACCENTS.put("", "g");
            UTF8_LOWER_ACCENTS.put("?", "m");
            UTF8_LOWER_ACCENTS.put("?", "o");
            UTF8_LOWER_ACCENTS.put("", "i");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "i");
            UTF8_LOWER_ACCENTS.put("", "z");
            UTF8_LOWER_ACCENTS.put("", "a");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "th");
            UTF8_LOWER_ACCENTS.put("", "dh");
            UTF8_LOWER_ACCENTS.put("", "ae");
            UTF8_LOWER_ACCENTS.put("", "u");
            UTF8_LOWER_ACCENTS.put("", "e");

        }
    }
}