//***************************************************************************** //* //* (c) Copyright 2002. Glub Tech, Incorporated. All Rights Reserved. //* //* $Id: CLIUtil.java 37 2009-05-11 22:46:15Z gary $ //* //***************************************************************************** package com.glub.secureftp.client.cli; import com.glub.util.*; import com.glub.secureftp.bean.*; import java.io.*; import java.text.*; import java.util.*; import org.apache.regexp.*; public class CLIUtil { /** * This method builds and returns the first valid path substituting globs * for files when needed. */ public static File globLocalPathForDir( String absDirPath ) throws FileNotFoundException { boolean directoryOnly = true; absDirPath = Util.searchAndReplace( absDirPath, "*", ".*", true ); absDirPath = Util.searchAndReplace( absDirPath, "?", ".*", true ); File result = new File( absDirPath ); if ( !result.exists() ) { StringTokenizer tok = new StringTokenizer( absDirPath, System.getProperty("file.separator") ); result = null; // for each token, find matching files/folders while( tok.hasMoreTokens() ) { String token = tok.nextToken(); File parentDir = null; if ( null == result ) { // if we're on windows, handle slightly differently if ( token.length() > 1 && token.charAt(1) == ':' ) { result = new File( token + File.separator ); if ( tok.hasMoreTokens() ) { token = tok.nextToken(); } parentDir = result; } else { result = new File( File.separator + token ); parentDir = new File(File.separator); } } else { parentDir = (new File(result, token)).getParentFile(); } if ( token.equals(".*") && !tok.hasMoreTokens() ) { return parentDir; } else if ( token.equals("..") ) { result = result.getParentFile(); if ( null != result.getParentFile() ) { parentDir = result.getParentFile(); token = result.getName(); } else { parentDir = result; if ( tok.hasMoreTokens() ) { token = tok.nextToken(); } } } else if ( token.equals(".") ) { if ( tok.hasMoreTokens() ) { token = tok.nextToken(); } } File[] filesInCurrentDir = parentDir.listFiles(); try { RECompiler compiler = new RECompiler(); RE fileRegex = new RE(); fileRegex.setMatchFlags(RE.MATCH_CASEINDEPENDENT); REProgram pattern = compiler.compile("^" + token + "$"); fileRegex.setProgram(pattern); File[] filesFound = globLocalFiles( token, filesInCurrentDir, fileRegex ); if ( filesFound.length < 1 ) { throw new FileNotFoundException(); } result = filesFound[0]; if ( directoryOnly && !result.isDirectory() ) { boolean foundDir = false; for ( int i = 1; i < filesFound.length; i++ ) { if ( filesFound[i].isDirectory() ) { result = filesFound[i]; foundDir = true; break; } } if ( !foundDir ) { throw new FileNotFoundException(); } } } catch ( FileNotFoundException fnfe ) { throw new FileNotFoundException(absDirPath); } catch ( RESyntaxException rese ) { throw new FileNotFoundException(absDirPath); } if ( null == result ) result = new File( result, token ); //System.out.println(result.getAbsolutePath()); } } return result; } public static short GLOB_ONLY_FILES = 0; public static short GLOB_ONLY_DIRS = 1; public static short GLOB_ALL_FILES = 2; /** * This method builds and returns all the files that match the fileGlob * parameter. */ public static File[] globLocalPathForFiles( String fileGlob, short fileSelectionMode ) throws FileNotFoundException { File[] filesFound = null; fileGlob = Util.searchAndReplace( fileGlob, "*", ".*", true ); fileGlob = Util.searchAndReplace( fileGlob, "?", ".*", true ); File simpleGuess = new File( fileGlob ); if ( !simpleGuess.exists() ) { StringTokenizer tok = new StringTokenizer( fileGlob, File.separator ); simpleGuess = null; // for each token, find matching files/folders while( tok.hasMoreTokens() ) { filesFound = null; String token = tok.nextToken(); File parentDir = null; if ( null == simpleGuess ) { // if we're on windows, handle slightly differently if ( token.length() > 1 && token.charAt(1) == ':' ) { simpleGuess = new File( token + File.separator ); if ( tok.hasMoreTokens() ) { token = tok.nextToken(); } parentDir = simpleGuess; } else { simpleGuess = new File( File.separator + token ); parentDir = new File(File.separator); } } else { parentDir = (new File(simpleGuess, token)).getParentFile(); } if ( token.equals(".*") && !tok.hasMoreTokens() ) { filesFound = parentDir.listFiles(); } else if ( token.equals("..") ) { simpleGuess = simpleGuess.getParentFile(); if ( null != simpleGuess.getParentFile() ) { parentDir = simpleGuess.getParentFile(); token = simpleGuess.getName(); } else { parentDir = simpleGuess; if ( tok.hasMoreTokens() ) { token = tok.nextToken(); } } } else if ( token.equals(".") ) { if ( tok.hasMoreTokens() ) { token = tok.nextToken(); } } if ( filesFound == null ) { File[] filesInCurrentDir = parentDir.listFiles(); try { RECompiler compiler = new RECompiler(); RE fileRegex = new RE(); fileRegex.setMatchFlags(RE.MATCH_CASEINDEPENDENT); REProgram pattern = compiler.compile("^" + token + "$"); fileRegex.setProgram(pattern); filesFound = globLocalFiles( token, filesInCurrentDir, fileRegex ); if ( filesFound.length < 1 ) { throw new FileNotFoundException(); } simpleGuess = filesFound[0]; } catch ( FileNotFoundException fnfe ) { throw new FileNotFoundException(fileGlob); } catch ( RESyntaxException rese ) { throw new FileNotFoundException(fileGlob); } } } } if ( fileSelectionMode == GLOB_ONLY_FILES || fileSelectionMode == GLOB_ONLY_DIRS ) { ArrayList updatedFilesFoundArray = new ArrayList( filesFound.length ); for ( int i = 0; i < filesFound.length; i++ ) { if ( fileSelectionMode == GLOB_ONLY_FILES && filesFound[i].isFile() ) { updatedFilesFoundArray.add( filesFound[i] ); } else if ( fileSelectionMode == GLOB_ONLY_DIRS && filesFound[i].isDirectory() ) { updatedFilesFoundArray.add( filesFound[i] ); } } if ( updatedFilesFoundArray.size() < 1 ) { throw new FileNotFoundException(fileGlob); } filesFound = (File[])updatedFilesFoundArray.toArray( new File[1] ); } return filesFound; } public static File[] globLocalFiles( String data, File[] filesToGlob, RE regExp ) throws FileNotFoundException { ArrayList results = new ArrayList(); Arrays.sort( filesToGlob ); boolean foundMatch = false; for ( int i = 0; i < filesToGlob.length; i++ ) { //System.out.println(data + " " + filesToGlob[i].getName()); if ( data.equals(filesToGlob[i].getName()) ) { results.add( filesToGlob[i] ); foundMatch = true; } else if ( regExp.match( filesToGlob[i].getName() ) ) { results.add( filesToGlob[i] ); //System.out.println("found! " + filesToGlob[i].getName()); foundMatch = true; } } if ( !foundMatch ) { throw new FileNotFoundException("no files matching criteria"); } return (File[])results.toArray( new File[1] ); } public static String getPassword( String prompt, boolean pwMask ) throws IOException { StringBuffer password = new StringBuffer(); PrintStream out = SecureFTP.getFTPSession().getPrintStream(); MaskingThread maskingThread = null; if ( pwMask ) { maskingThread = new MaskingThread(prompt); maskingThread.setPriority(Thread.MAX_PRIORITY); maskingThread.start(); } else { out.print( prompt ); } while (true) { char c = (char)SecureFTP.getInputStream().read(); if ( pwMask ) { maskingThread.stopMasking(); } if ( c == '\r' ) { c = (char)SecureFTP.getInputStream().read(); if ( c == '\n' ) { break; } else { continue; } } else if ( c == '\n' ) { break; } else { password.append(c); } } return password.toString(); } public static boolean yesNoPrompt( String msg ) { return yesNoPrompt( msg, YN_NO ); } public static final short YN_NO = 0; public static final short YN_YES = 1; public static boolean yesNoPrompt( String msg, short defaultAction ) { boolean result = false; String defaultChoice = null; switch ( defaultAction ) { case YN_YES: defaultChoice = "y"; result = true; break; case YN_NO: default: defaultChoice = "n"; result = false; break; } PrintStream out = SecureFTP.getFTPSession().getPrintStream(); out.print( msg + " [y|n](" + defaultChoice + "): " ); try { BufferedReader stdin = SecureFTP.getInput(); String input = stdin.readLine(); if ( input == null ) {} else if ( input.trim().length() == 0 ) {} else if ( input.trim().equalsIgnoreCase("y") ) { result = true; } else { result = false; } } catch ( IOException ioe ) {} return result; } public static final short YNA_NO = 0; public static final short YNA_YES = 1; public static final short YNA_ALWAYS = 2; public static short yesNoAlwaysPrompt( String msg ) { return yesNoAlwaysPrompt( msg, YNA_NO ); } public static short yesNoAlwaysPrompt( String msg, short defaultAction ) { short result = defaultAction; String defaultChoice = null; switch ( defaultAction ) { case YNA_YES: defaultChoice = "y"; break; case YNA_ALWAYS: defaultChoice = "a"; break; case YNA_NO: default: defaultChoice = "n"; break; } PrintStream out = SecureFTP.getFTPSession().getPrintStream(); out.print( msg + " [y|n|a](" + defaultChoice + "): " ); try { BufferedReader stdin = SecureFTP.getInput(); String input = stdin.readLine(); if ( input == null ) {} else if ( input.trim().length() == 0 ) {} else if ( input.trim().equalsIgnoreCase("y") ) { result = YNA_YES; } else if ( input.trim().equalsIgnoreCase("a") ) { result = YNA_ALWAYS; } else { result = YNA_NO; } } catch ( IOException ioe ) {} return result; } } class MaskingThread extends Thread { private boolean stop = false; private String prompt; public MaskingThread( String prompt ) { this.prompt = prompt; } public void run() { while (!stop) { try { System.out.print(" \b\r" + prompt); System.out.flush(); sleep(5); } catch (InterruptedException ie) {} } } public void stopMasking() { stop = true; } } class ProgressThread extends Thread implements Progress { private boolean stop = false; private String progress = ""; private long total = 0; private int indeterminateState = -1; public void run() { while (!stop) { try { System.out.print(" \b\r" + progress); System.out.flush(); sleep(5); } catch (InterruptedException ie) {} } } public boolean isRunning() { return !stop; } public void startProgress() {} public void finishProgress() { stop = true; DecimalFormat df = new DecimalFormat("#.##"); df.setGroupingUsed( true ); df.setMaximumFractionDigits( 2 ); double kbTot = total / 1024.0; double mbTot = kbTot / 1024.0; double gbTot = mbTot / 1024.0; if ( kbTot >= 1 && mbTot < 1 ) { System.out.println(" \b\r[********************] 100% : " + df.format(kbTot) + " of " + df.format(kbTot) + " KB transferred" ); } else if ( mbTot >= 1 && gbTot < 1 ) { System.out.println(" \b\r[********************] 100% : " + df.format(mbTot) + " of " + df.format(mbTot) + " MB transferred" ); } else if ( gbTot >= 1 ) { System.out.println(" \b\r[********************] 100% : " + df.format(gbTot) + " of " + df.format(gbTot) + " GB transferred" ); } else if ( total > 0 ) { System.out.println(" \b\r[********************] 100% : " + total + " of " + total + " bytes transferred" ); } else if ( total < 0 ) { System.out.println(" \b\r[********************] 100%"); } } public void updateProgress( long pos, long total ) { double percentDone = ((pos * 1.0) / total) * 100; this.total = pos; StringBuffer buf = new StringBuffer("["); if ( total > 0 && percentDone <= 100 ) { for ( int i = 0; i < (int)percentDone / 5; i++ ) { buf.append("*"); } for ( int i = (int)percentDone / 5; i < 20; i++ ) { buf.append(" "); } } // indeterminate else { indeterminateState++; switch ( indeterminateState % 3 ) { case 0: buf.append("* * * * * * * "); break; case 1: buf.append(" * * * * * * *"); break; case 2: buf.append(" * * * * * * "); break; } } buf.append("] "); if ( indeterminateState < 0 ) { buf.append((int)Math.ceil(percentDone)); } else { buf.append("unk"); } buf.append("% : "); DecimalFormat df = new DecimalFormat("#.##"); df.setGroupingUsed( true ); df.setMaximumFractionDigits( 2 ); double kbPos = pos / 1024.0; double mbPos = kbPos / 1024.0; double gbPos = mbPos / 1024.0; double kbTot = total / 1024.0; double mbTot = kbTot / 1024.0; double gbTot = mbTot / 1024.0; if ( (kbPos >= 1 && mbPos < 1) || (kbTot >= 1 && mbTot < 1) ) { buf.append(df.format(kbPos)); if ( indeterminateState < 0 ) { buf.append(" of "); buf.append(df.format(kbTot)); } buf.append(" KB transferred" ); } else if ( (mbPos >= 1 && gbPos < 1) || (mbTot >= 1 && gbTot < 1) ) { buf.append(df.format(mbPos)); if ( indeterminateState < 0 ) { buf.append(" of "); buf.append(df.format(mbTot)); } buf.append(" MB transferred " ); } else if ( gbPos >= 1 || gbTot >= 1 ) { buf.append(df.format(gbPos)); if ( indeterminateState < 0 ) { buf.append(" of "); buf.append(df.format(gbTot)); } buf.append(" GB transferred" ); } else { buf.append(pos); if ( indeterminateState < 0 ) { buf.append(" of "); buf.append(total); } buf.append(" bytes transferred" ); } progress = buf.toString(); } }