package com.limegroup.gnutella.library; import static com.limegroup.gnutella.Constants.MAX_FILE_SIZE; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import org.limewire.core.settings.LibrarySettings; import org.limewire.util.CommonUtils; import org.limewire.util.FileUtils; import org.limewire.util.MediaType; import org.limewire.util.OSUtils; public class LibraryUtils { // TODO: refactor back into filemanger for test mocking... use instances. /** Subdirectory that is always shared. */ public static final File PROGRAM_SHARE; /** Subdirectory that also is always shared. */ public static final File PREFERENCE_SHARE; /** Subdirectory used to share special application files. */ public static final File APPLICATION_SPECIAL_SHARE; private static final List<File> userDirectories; private static final List<String> sensitiveDirectories; static { File forceShare = new File(".", ".NetworkShare").getAbsoluteFile(); try { forceShare = FileUtils.getCanonicalFile(forceShare); } catch(IOException ignored) {} PROGRAM_SHARE = forceShare; forceShare = new File(CommonUtils.getUserSettingsDir(), ".NetworkShare").getAbsoluteFile(); try { forceShare = FileUtils.getCanonicalFile(forceShare); } catch(IOException ignored) {} PREFERENCE_SHARE = forceShare; forceShare = new File(CommonUtils.getUserSettingsDir(), ".AppSpecialShare").getAbsoluteFile(); forceShare.mkdir(); try { forceShare = FileUtils.getCanonicalFile(forceShare); } catch(IOException ignored) {} APPLICATION_SPECIAL_SHARE = forceShare; userDirectories = getUserDirectories(); sensitiveDirectories = getSensitiveDirectories(); } /** * Builds list of directories with a given name for each user, starting from thier home directory. */ private static List<String> getUserDirectories(String directoryName) { List<String> userSubDirectories = new ArrayList<String>(); for(File userHome : userDirectories) { File folder = new File(userHome, directoryName); userSubDirectories.add(folder.getAbsolutePath()); } return userSubDirectories; } /** * Returns list of sensitive directories. */ private static List<String> getSensitiveDirectories() { List<String> sensitiveDirectories = new ArrayList<String>(); if (OSUtils.isWindows()) { sensitiveDirectories.addAll(getUserDirectories("Documents")); sensitiveDirectories.addAll(getUserDirectories("My Documents")); sensitiveDirectories.addAll(getUserDirectories("Desktop")); sensitiveDirectories.add(File.separator + "Documents and Settings"); sensitiveDirectories.add(File.separator + "Program Files"); sensitiveDirectories.add(File.separator + "Windows"); sensitiveDirectories.add(File.separator + "WINDOWS"); sensitiveDirectories.add(File.separator + "WINNT"); sensitiveDirectories.add(File.separator + "Users"); sensitiveDirectories.add(File.separator + "Local Settings"); sensitiveDirectories.add(File.separator + "Application Data"); sensitiveDirectories.add(File.separator + "Temp"); sensitiveDirectories.add(File.separator + "Temporary Internet Files"); } if (OSUtils.isMacOSX()) { sensitiveDirectories.addAll(getUserDirectories("Documents")); sensitiveDirectories.addAll(getUserDirectories("Desktop")); sensitiveDirectories.addAll(getUserDirectories("Library")); sensitiveDirectories.add(File.separator + "Users"); sensitiveDirectories.add(File.separator + "System"); sensitiveDirectories.add(File.separator + "System Folder"); sensitiveDirectories.add(File.separator + "Previous Systems"); sensitiveDirectories.add(File.separator + "private"); sensitiveDirectories.add(File.separator + "Volumes"); sensitiveDirectories.add(File.separator + "Desktop"); sensitiveDirectories.add(File.separator + "Applications"); sensitiveDirectories.add(File.separator + "Applications (Mac OS 9)"); sensitiveDirectories.add(File.separator + "Network"); } if (OSUtils.isPOSIX()) { sensitiveDirectories.addAll(getUserDirectories("Desktop")); sensitiveDirectories.addAll(getUserDirectories("Documents")); sensitiveDirectories.add(File.separator + "bin"); sensitiveDirectories.add(File.separator + "boot"); sensitiveDirectories.add(File.separator + "dev"); sensitiveDirectories.add(File.separator + "etc"); sensitiveDirectories.add(File.separator + "home"); sensitiveDirectories.add(File.separator + "mnt"); sensitiveDirectories.add(File.separator + "opt"); sensitiveDirectories.add(File.separator + "proc"); sensitiveDirectories.add(File.separator + "root"); sensitiveDirectories.add(File.separator + "sbin"); sensitiveDirectories.add(File.separator + "usr"); sensitiveDirectories.add(File.separator + "var"); } return sensitiveDirectories; } /** * Returns list of possible user home directories. */ private static List<File> getUserDirectories() { File userHome = new File(System.getProperty("user.home")); List<File> userDirectories = new ArrayList<File>(); userDirectories.add(userHome.getAbsoluteFile()); File commonHome = null; if(OSUtils.isWindowsVista() || OSUtils.isWindows7()) { commonHome = new File("C:/Users"); } else if(OSUtils.isWindows()) { commonHome = new File("C:/Documents and Settings"); } else if( OSUtils.isMacOSX()) { commonHome = new File("/Users"); } else if (OSUtils.isLinux()) { commonHome = new File("/home"); } //not all users will have their home directory under the commonHome, some might have custom locations. if(commonHome != null) { File[] directories = commonHome.listFiles(new FileFilter() { @Override public boolean accept(File file) { return file.isDirectory(); } }); if(directories != null) { userDirectories.addAll(Arrays.asList(directories)); } } return userDirectories; } /** * @return <code>isFilePhysicallyManagable(file) && isFileAllowedToBeManaged(file))</code> */ public static boolean isFileManagable(File file) { return isFilePhysicallyManagable(file) && isFileAllowedToBeManaged(file); } /** * Returns true if this file is not too large, not too small, * not null, not a directory, not unreadable, not hidden. * <p> * Returns false otherwise. */ public static boolean isFilePhysicallyManagable(File file) { if (file == null || !file.exists() || file.isDirectory() || !file.canRead() || file.isHidden() ) { return false; } long fileLength = file.length(); if (fileLength <= 0 || fileLength > MAX_FILE_SIZE) { return false; } return true; } /** * If managing programs is disabled and the specified file is not a forced * share, returns false if the file is a program. Otherwise returns false * if the file's extension is banned. Otherwise returns true. */ public static boolean isFileAllowedToBeManaged(File file) { String ext = FileUtils.getFileExtension(file).toLowerCase(Locale.US); if(!LibrarySettings.ALLOW_PROGRAMS.getValue() && !LibraryUtils.isForcedShare(file)) { MediaType type = MediaType.getMediaTypeForExtension(ext); if(type == MediaType.getProgramMediaType()) return false; } // TODO: This generated a small # of complaints (and broke some tests, but not hard to fix those) // Before re-adding, should confirm that we definitely want this behavior, and maybe // turn it into an option? The UI right now exposes these extensions as // "banned search result extensions", which is a little different than what this code is doing. // String dotExt = "." + ext; // for(String banned : FilterSettings.BANNED_EXTENSIONS.get()) { // if(banned.equals(dotExt)) // return false; // } return true; } /** * Returns true iff <tt>file</tt> is a sensitive directory. */ public static boolean isSensitiveDirectory(File folder) { if (folder == null) { return false; } if(userDirectories.contains(folder)) { return true; } String folderPath = folder.getPath(); for (String name : sensitiveDirectories) { if (folderPath.endsWith(name)) { return true; } } return false; } /** * Determines if this FileDesc is a network share. */ public static boolean isForcedShare(FileDesc desc) { return isForcedShare(desc.getFile()); } /** * Determines if this File is a network share. */ public static boolean isForcedShare(File file) { File parent = file.getParentFile(); return parent != null && isForcedShareDirectory(parent); } /** * Determines if this File is an application special share. */ public static boolean isApplicationSpecialShare(File file) { File parent = file.getParentFile(); return parent != null && isApplicationSpecialShareDirectory(parent); } /** * Determines if this File is a network shared directory. */ public static boolean isForcedShareDirectory(File f) { return f != null && (f.equals(LibraryUtils.PROGRAM_SHARE) || f.equals(LibraryUtils.PREFERENCE_SHARE)); } public static boolean isApplicationSpecialShareDirectory(File directory) { return directory.equals(LibraryUtils.APPLICATION_SPECIAL_SHARE); } /** * Returns true if this folder should never be a managed. */ public static boolean isFolderBanned(File folder) { // check for system roots File[] faRoots = File.listRoots(); if (faRoots != null && faRoots.length > 0) { for (int i = 0; i < faRoots.length; i++) { if (folder.equals(faRoots[i])) return true; } } // Check for the folder name being 'Cookies', or 'Cookies\Low' [vista] // TODO: Make sure this is i18n-safe String name = folder.getName().toLowerCase(Locale.US); if(name.equals("cookies")) return true; else if(name.equals("low")) { String parent = folder.getParent(); if(parent != null && parent.toLowerCase(Locale.US).equals("cookies")) return true; } return false; } }