1 /* 2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net 3 * Copyright (C) 2004-2010 Frederico Caldeira Knabben 4 * 5 * == BEGIN LICENSE == 6 * 7 * Licensed under the terms of any of the following licenses at your 8 * choice: 9 * 10 * - GNU General Public License Version 2 or later (the "GPL") 11 * http://www.gnu.org/licenses/gpl.html 12 * 13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") 14 * http://www.gnu.org/licenses/lgpl.html 15 * 16 * - Mozilla Public License Version 1.1 or later (the "MPL") 17 * http://www.mozilla.org/MPL/MPL-1.1.html 18 * 19 * == END LICENSE == 20 */ 21 package net.fckeditor.tool; 22 23 import java.io.File; 24 import java.io.InputStream; 25 import java.util.regex.Pattern; 26 27 import net.fckeditor.handlers.PropertiesLoader; 28 29 import org.apache.commons.io.FilenameUtils; 30 import org.devlib.schmidt.imageinfo.ImageInfo; 31 32 /** 33 * Static helper methods for files. 34 * 35 * @version $Id: UtilsFile.java 4785 2009-12-21 20:10:28Z mosipov $ 36 */ 37 public class UtilsFile { 38 39 protected static final Pattern ILLEGAL_CURRENT_FOLDER_PATTERN = Pattern 40 .compile("^[^/]|[^/]$|/\\.{1,2}|\\\\|\\||:|\\?|\\*|\"|<|>|\\p{Cntrl}"); 41 42 /** 43 * Sanitizes a filename from certain chars.<br /> 44 * 45 * This method enforces the <code>forceSingleExtension</code> property and 46 * then replaces all occurrences of \, /, |, :, ?, *, ", <, >, 47 * control chars by _ (underscore). 48 * 49 * @param filename 50 * a potentially 'malicious' filename 51 * @return sanitized filename 52 */ 53 public static String sanitizeFileName(final String filename) { 54 55 if (Utils.isEmpty(filename)) 56 return filename; 57 58 String name = (PropertiesLoader.isForceSingleExtension()) ? UtilsFile 59 .forceSingleExtension(filename) : filename; 60 61 // Remove \ / | : ? * " < > 'Control Chars' with _ 62 return name.replaceAll("\\\\|/|\\||:|\\?|\\*|\"|<|>|\\p{Cntrl}", "_"); 63 } 64 65 /** 66 * Sanitizes a folder name from certain chars.<br /> 67 * 68 * This method replaces all occurrences of \, /, |, :, ?, *, ", <, 69 * >, control chars by _ (underscore). 70 * 71 * @param folderName 72 * a potentially 'malicious' folder name 73 * @return sanitized folder name 74 */ 75 public static String sanitizeFolderName(final String folderName) { 76 77 if (Utils.isEmpty(folderName)) 78 return folderName; 79 80 // Remove . \ / | : ? * " < > 'Control Chars' with _ 81 return folderName.replaceAll( 82 "\\.|\\\\|/|\\||:|\\?|\\*|\"|<|>|\\p{Cntrl}", "_"); 83 } 84 85 /** 86 * Checks if the underlying input stream contains an image. 87 * 88 * @param in 89 * input stream of an image 90 * @return <code>true</code> if the underlying input stream contains an 91 * image, else <code>false</code> 92 */ 93 public static boolean isImage(final InputStream in) { 94 ImageInfo ii = new ImageInfo(); 95 ii.setInput(in); 96 return ii.check(); 97 } 98 99 /** 100 * Checks whether a path complies with the FCKeditor File Browser <a href="http://docs.fckeditor.net/FCKeditor_2.x/Developers_Guide/Server_Side_Integration#File_Browser_Requests" 101 * target="_blank">rules</a>. 102 * 103 * @param path 104 * a potentially 'malicious' path 105 * @return <code>true</code> if path complies with the rules, else 106 * <code>false</code> 107 */ 108 public static boolean isValidPath(final String path) { 109 if (Utils.isEmpty(path)) 110 return false; 111 112 if (ILLEGAL_CURRENT_FOLDER_PATTERN.matcher(path).find()) 113 return false; 114 115 return true; 116 } 117 118 /** 119 * Replaces all dots in a filename with underscores except the last one. 120 * 121 * @param filename 122 * filename to sanitize 123 * @return string with a single dot only 124 */ 125 public static String forceSingleExtension(final String filename) { 126 return filename.replaceAll("\\.(?![^.]+$)", "_"); 127 } 128 129 /** 130 * Checks if a filename contains more than one dot. 131 * 132 * @param filename 133 * filename to check 134 * @return <code>true</code> if filename contains severals dots, else 135 * <code>false</code> 136 */ 137 public static boolean isSingleExtension(final String filename) { 138 return filename.matches("[^\\.]+\\.[^\\.]+"); 139 } 140 141 /** 142 * Checks a directory for existence and creates it if non-existent. 143 * 144 * @param dir 145 * directory to check/create 146 */ 147 public static void checkDirAndCreate(File dir) { 148 if (!dir.exists()) 149 dir.mkdirs(); 150 } 151 152 /** 153 * Iterates over a base name and returns the first non-existent file.<br /> 154 * This method extracts a file's base name, iterates over it until the first 155 * non-existent appearance with <code>basename(n).ext</code>. Where n is a 156 * positive integer starting from one. 157 * 158 * @param file 159 * base file 160 * @return first non-existent file 161 */ 162 public static File getUniqueFile(final File file) { 163 if (!file.exists()) 164 return file; 165 166 File tmpFile = new File(file.getAbsolutePath()); 167 File parentDir = tmpFile.getParentFile(); 168 int count = 1; 169 String extension = FilenameUtils.getExtension(tmpFile.getName()); 170 String baseName = FilenameUtils.getBaseName(tmpFile.getName()); 171 do { 172 tmpFile = new File(parentDir, baseName + "(" + count++ + ")." 173 + extension); 174 } while (tmpFile.exists()); 175 return tmpFile; 176 } 177 }