package org.limewire.ui.swing.util; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Random; import javax.swing.JOptionPane; import org.limewire.core.settings.SharingSettings; import org.limewire.io.IOUtils; import org.limewire.ui.swing.components.FocusJOptionPane; import org.limewire.ui.swing.settings.SwingUiSettings; import org.limewire.util.CommonUtils; import org.limewire.util.FileUtils; import org.limewire.util.OSUtils; /** Handles prompting the user to enter a valid save directory. */ public final class SaveDirectoryHandler { private SaveDirectoryHandler() {} /** * Ensures that the current save directory is valid, * prompting for a new one if it isn't. */ public static void validateSaveDirectoryAndPromptForNewOne() { File saveDir = SharingSettings.getSaveDirectory(); if(!isDirectoryValid(saveDir)) promptAndSetNewSaveDirectory(); } public static boolean isDirectoryValid(File dir){ return isSaveDirectoryValid(dir) && showVistaWarningIfNeeded(dir); } /** * Constructs a new window that prompts the user to enter a valid save * directory. * * This doesn't return until the user has chosen a valid directory. */ private static void promptAndSetNewSaveDirectory() { File dir = null; while(!isSaveDirectoryValid(dir) || !showVistaWarningIfNeeded(dir)) { FocusJOptionPane.showMessageDialog(GuiUtils.getMainFrame(), I18n.tr("Your save folder is not valid. It may have been deleted, you may not have permissions to write to it, or there may be another problem. Please choose a different folder."), I18n.tr("Invalid Folder"), JOptionPane.WARNING_MESSAGE); dir = showChooser(); if(dir == null) continue; FileUtils.setWriteable(dir); } } /** * Shows the chooser & sets the save directory setting, adding the save * directory as shared, also. * * @return the selected <tt>File</tt>, or <tt>null</tt> if there were * any problems */ private static File showChooser() { File dir = FileChooser.getInputDirectory(null); if(dir != null) { try { // updates Incomplete directory etc... SharingSettings.setSaveDirectory(dir); //SharingSettings.DIRECTORIES_TO_SHARE.add(dir); return dir; } catch(IOException ignored) {} } return null; } /** * Utility method for checking whether or not the save directory is valid. * * @param saveDir the save directory to check for validity * @return <tt>true</tt> if the save directory is valid, otherwise * <tt>false</tt> */ private static boolean isSaveDirectoryValid(File saveDir) { if(saveDir == null || saveDir.isFile()) return false; if(!saveDir.exists()) saveDir.mkdirs(); if(!saveDir.isDirectory()) return false; FileUtils.setWriteable(saveDir); Random generator = new Random(); File testFile = null; for(int i = 0; i < 10 && testFile == null; i++) { StringBuilder name = new StringBuilder(); for(int j = 0; j < 8; j++) { name.append((char)('a' + generator.nextInt('z'-'a'))); } name.append(".tmp"); testFile = new File(saveDir, name.toString()); if (testFile.exists()) { testFile = null; // try again! } } if (testFile == null) { return false; } RandomAccessFile testRAFile = null; try { testRAFile = new RandomAccessFile(testFile, "rw"); // Try to write something just to make extra sure we're OK. testRAFile.write(7); testRAFile.close(); } catch (FileNotFoundException e) { // If we could not open the file, then we can't write to that // directory. return false; } catch(IOException e) { // The directory is invalid if there was an error writing to it. return false; } finally { // Delete our test file. testFile.delete(); IOUtils.close(testRAFile); } return FileUtils.canWrite(saveDir); } private static boolean isGoodVistaDirectory(File f) { if (!OSUtils.isWindowsVista()) return true; try { return FileUtils.isReallyInParentPath(CommonUtils.getUserHomeDir(), f); } catch (IOException iox) { return true; // probably bad, but not vista-specific } } /** * @param f the directory the user wants to save to * @return true if its ok to use that directory */ private static boolean showVistaWarningIfNeeded(File f) { if (isGoodVistaDirectory(f)) return true; if(SwingUiSettings.VISTA_WARN_DIRECTORIES.contains(f)) { return true; } int ret = FocusJOptionPane .showOptionDialog( GuiUtils.getMainFrame(), I18n.tr("Saving downloads to {0} may not function correctly.\nTo be sure downloads are saved properly you should save them to a sub-folder of\n{1}.\nWould you like to choose another location?", f, CommonUtils.getUserHomeDir()), I18n.tr("Folder Warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, null, JOptionPane.YES_OPTION); if(ret == JOptionPane.NO_OPTION) { SwingUiSettings.VISTA_WARN_DIRECTORIES.add(f); } return ret == JOptionPane.NO_OPTION; } }