/* -*-mode:java; c-basic-offset:2; -*- */
import com.jcraft.jsch.*;
import java.io.*; 
/*
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
*/

public class Sftp{
  public static void main(String[] arg){

    if (arg.length!=6) {
      System.err.println("usage: java Sftp user host password_f lfile rfile rrfile");
      System.exit(-1);
    }      
    String user       = arg[0];
    String host       = arg[1];
    String password_f = arg[2];
    String lfile      = arg[3];
    String rfile      = arg[4];
    String rrfile     = arg[5];

    System.out.println("user       = " + user);
    System.out.println("host       = " + host);
    System.out.println("password_f = " + password_f);
    System.out.println("lfile      = " + lfile);
    System.out.println("rfile      = " + rfile);
    System.out.println("rrfile     = " + rrfile);

    try{

      FileInputStream fis = new FileInputStream(password_f);
      byte[] buf=new byte[1024];
      while(true){
        int len=fis.read(buf, 0, buf.length);
	if(len<=0) break;
      }
      String password = new String(buf).trim();

      JSch jsch=new JSch();

      jsch.setKnownHosts("known_hosts");

      Session session=jsch.getSession(user, host, 22);

      session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
      session.setPassword(password);

      session.connect();

      Channel channel=session.openChannel("sftp");
      channel.connect();
      ChannelSftp c=(ChannelSftp)channel;

      java.io.InputStream in=System.in;
      java.io.PrintStream out=System.out;

      java.util.Vector cmds=new java.util.Vector();

      // action without IO; delete the remote file rfile, copy lfile to rfile, 
      // copy back rfile to rrfile
      SftpProgressMonitor m=new MyProgressMonitor();
      // out.print("Looking for " + rfile + "\n");
      try {
	    c.ls(rfile);
        out.print("Removing remove file " + rfile + "\n");
        try {
  	  c.rm(rfile);
        }
        catch(SftpException e){
        System.out.println(e);
        }
        out.print("removed " + rfile + "\n");
      }
      catch(SftpException e){
        out.print("Cannot find " + rfile + "\n");
      }
      int modemode=ChannelSftp.OVERWRITE;
      out.print("Copying local file " + lfile + " to remote file " + rfile +"\n");
      try {
        c.put(lfile, rfile,  m, modemode);
      }
      catch(SftpException e){
        System.out.println(e);
      }
      out.print("copied\n");
      out.print("Copying remote file " + rfile + " back to new local file " + rrfile +"\n");
      try {
        c.get(rfile, rrfile, m, modemode);
      }
      catch(SftpException e){
        System.out.println(e);
      }
      out.print("copied\n");
      c.quit();

/*
      byte[] buf=new byte[1024] ;
      int i;
      String str;
      int level=0;

      while(true){

        out.print("sftp> ");
	cmds.removeAllElements();
        i=in.read(buf, 0, 1024);
	if(i<=0)break;

        i--;
        if(i>0 && buf[i-1]==0x0d)i--;
        //str=new String(buf, 0, i);
        //System.out.println("|"+str+"|");
	int s=0;
	for(int ii=0; ii<i; ii++){
          if(buf[ii]==' '){
            if(ii-s>0){ cmds.addElement(new String(buf, s, ii-s)); }
	    while(ii<i){if(buf[ii]!=' ')break; ii++;}
	    s=ii;
	  }
	}
	if(s<i){ cmds.addElement(new String(buf, s, i-s)); }
	if(cmds.size()==0)continue;

	String cmd=(String)cmds.elementAt(0);
	if(cmd.equals("quit")){
          c.quit();
	  break;
	}
	if(cmd.equals("exit")){
          c.exit();
	  break;
	}
 	if(cmd.equals("rekey")){
 	  session.rekey();
 	  continue;
 	}
 	if(cmd.equals("compression")){
          if(cmds.size()<2){
	    out.println("compression level: "+level);
            continue;
	  }
	  try{
	    level=Integer.parseInt((String)cmds.elementAt(1));
	    java.util.Hashtable config=new java.util.Hashtable();
	    if(level==0){
	      config.put("compression.s2c", "none");
	      config.put("compression.c2s", "none");
	    }
	    else{
	      config.put("compression.s2c", "zlib,none");
	      config.put("compression.c2s", "zlib,none");
	    }
	    session.setConfig(config);
	  }
	  catch(Exception e){}
 	  continue;
	}
	if(cmd.equals("cd") || cmd.equals("lcd")){
          if(cmds.size()<2) continue;
	  String path=(String)cmds.elementAt(1);
	  try{
	    if(cmd.equals("cd")) c.cd(path);
	    else c.lcd(path);
	  }
	  catch(SftpException e){
	    System.out.println(e.message);
	  }
	  continue;
	}
	if(cmd.equals("rm") || cmd.equals("rmdir") || cmd.equals("mkdir")){
          if(cmds.size()<2) continue;
	  String path=(String)cmds.elementAt(1);
	  try{
	    if(cmd.equals("rm")) c.rm(path);
	    else if(cmd.equals("rmdir")) c.rmdir(path);
	    else c.mkdir(path);
	  }
	  catch(SftpException e){
	    System.out.println(e.message);
	  }
	  continue;
	}
	if(cmd.equals("chgrp") || cmd.equals("chown") || cmd.equals("chmod")){
          if(cmds.size()!=3) continue;
	  String path=(String)cmds.elementAt(2);
	  int foo=0;
	  if(cmd.equals("chmod")){
            byte[] bar=((String)cmds.elementAt(1)).getBytes();
            int k;
            for(int j=0; j<bar.length; j++){
              k=bar[j];
	      if(k<'0'||k>'7'){foo=-1; break;}
  	      foo<<=3;
	      foo|=(k-'0');
	    }
	    if(foo==-1)continue;
	  }
	  else{
  	    try{foo=Integer.parseInt((String)cmds.elementAt(1));}
	    catch(Exception e){continue;}
	  }
	  try{
	    if(cmd.equals("chgrp")){ c.chgrp(foo, path); }
	    else if(cmd.equals("chown")){ c.chown(foo, path); }
	    else if(cmd.equals("chmod")){ c.chmod(foo, path); }
	  }
	  catch(SftpException e){
	    System.out.println(e.message);
	  }
	  continue;
	}
	if(cmd.equals("pwd") || cmd.equals("lpwd")){
           str=(cmd.equals("pwd")?"Remote":"Local");
	   str+=" working directory: ";
          if(cmd.equals("pwd")) str+=c.pwd();
	  else str+=c.lpwd();
	  out.println(str);
	  continue;
	}
	if(cmd.equals("ls") || cmd.equals("dir")){
	  String path=".";
	  if(cmds.size()==2) path=(String)cmds.elementAt(1);
	  try{
	    java.util.Vector vv=c.ls(path);
	    if(vv!=null){
	      for(int ii=0; ii<vv.size(); ii++){
		/*
		Object obj=vv.elementAt(ii);
		if(obj instanceof com.jcraft.jsch.ChannelSftp.Ssh_exp_name )
		  out.println(((com.jcraft.jsch.ChannelSftp.Ssh_exp_name)obj).getLongname());
		else if(obj instanceof java.lang.String)
		  out.println(obj);
		else
		  throw new Exception("opps, got an odd type back");
		*/
/*
		out.println(vv.elementAt(ii));
	      }
	    }
	  }
	  catch(SftpException e){
	    System.out.println(e.message);
	  }
	  continue;
	}
	if(cmd.equals("lls") || cmd.equals("ldir")){
	  String path=".";
	  if(cmds.size()==2) path=(String)cmds.elementAt(1);
	  try{
	    java.io.File file=new java.io.File(path);
	    if(!file.exists()){
	      out.println(path+": No such file or directory");
              continue; 
            }
	    if(file.isDirectory()){
	      String[] list=file.list();
	      for(int ii=0; ii<list.length; ii++){
		out.println(list[ii]);
	      }
	      continue;
	    }
	    out.println(path);
	  }
	  catch(Exception e){
	    System.out.println(e);
	  }
	  continue;
	}
	if(cmd.equals("get") || 
	   cmd.equals("get-resume") || cmd.equals("get-append") || 
	   cmd.equals("put") || 
	   cmd.equals("put-resume") || cmd.equals("put-append")
	   ){
	  if(cmds.size()!=2 && cmds.size()!=3) continue;
	  String p1=(String)cmds.elementAt(1);
//	  String p2=p1;
	  String p2=".";
	  if(cmds.size()==3)p2=(String)cmds.elementAt(2);
	  try{
	    SftpProgressMonitor monitor=new MyProgressMonitor();
	    if(cmd.startsWith("get")){
	      int mode=ChannelSftp.OVERWRITE;
	      if(cmd.equals("get-resume")){ mode=ChannelSftp.RESUME; }
	      else if(cmd.equals("get-append")){ mode=ChannelSftp.APPEND; } 
	      c.get(p1, p2, monitor, mode);
	    }
	    else{ 
	      int mode=ChannelSftp.OVERWRITE;
	      if(cmd.equals("put-resume")){ mode=ChannelSftp.RESUME; }
	      else if(cmd.equals("put-append")){ mode=ChannelSftp.APPEND; } 
	      c.put(p1, p2, monitor, mode); 
	    }
	  }
	  catch(SftpException e){
	    System.out.println(e.message);
	  }
	  continue;
	}
/*
	if(cmd.equals("foo")){
	  try{
	    java.io.InputStream pis=c.get((String)cmds.elementAt(1));
	    try{
	      while(true){
		int iii=pis.read();
		if(iii<=0)break;
		System.out.print(new Character((char)(iii&0xff)));
	      }
	    }
	    catch(Exception ee){
	      System.out.println("!!!!"+ee);
	      ee.printStackTrace();
	    }
	    pis.close();
	  }
	  catch(Exception e){
	    System.out.println("!!!"+e);
	  }
	  continue;
	}
	if(cmd.equals("bar")){
	  try{
	    java.io.OutputStream pos=c.put((String)cmds.elementAt(1));
	    pos.write(((String)cmds.elementAt(2)).getBytes());
	    pos.flush();
	    pos.close();
	  }
	  catch(Exception e){
	    System.out.println("!!!"+e);
	  }
	  continue;
	}
*/
/*
	if(cmd.equals("ln") || cmd.equals("symlink") || cmd.equals("rename")){
          if(cmds.size()!=3) continue;
	  String p1=(String)cmds.elementAt(1);
	  String p2=(String)cmds.elementAt(2);
	  try{
	    if(cmd.equals("rename")) c.rename(p1, p2);
	    else c.symlink(p1, p2);
	  }
	  catch(SftpException e){
	    System.out.println(e.message);
	  }
	  continue;
	}
	if(cmd.equals("stat") || cmd.equals("lstat")){
          if(cmds.size()!=2) continue;
	  String p1=(String)cmds.elementAt(1);
	  SftpATTRS attrs=null;
	  try{
	    if(cmd.equals("stat")) attrs=c.stat(p1);
	    else attrs=c.lstat(p1);
	  }
	  catch(SftpException e){
	    System.out.println(e.message);
	  }
	  if(attrs!=null){
            out.println(attrs);
	  }
	  else{
	  }
	  continue;
	}
	if(cmd.equals("version")){
	  out.println("SFTP protocol version "+c.version());
	  continue;
	}
	if(cmd.equals("help") || cmd.equals("?")){
	  out.println(help);
	  continue;
	}
        out.println("unimplemented command: "+cmd);
      }
*/
      session.disconnect();
    }
    catch(Exception e){
      System.out.println(e);
    }
    System.exit(0);
  }

  /*
  public static class MyUserInfo implements UserInfo{
    public String getPassword(){ return passwd; }
    public boolean promptYesNo(String str){
      Object[] options={ "yes", "no" };
      int foo=JOptionPane.showOptionDialog(null, 
             str,
             "Warning", 
             JOptionPane.DEFAULT_OPTION, 
             JOptionPane.WARNING_MESSAGE,
             null, options, options[0]);
       return foo==0;
    }
  
    String passwd;
    JTextField passwordField=(JTextField)new JPasswordField(20);

    public String getPassphrase(){ return null; }
    public boolean promptPassphrase(String message){ return true; }
    public boolean promptPassword(String message){
      Object[] ob={passwordField}; 
      int result=
	  JOptionPane.showConfirmDialog(null, ob, message,
					JOptionPane.OK_CANCEL_OPTION);
      if(result==JOptionPane.OK_OPTION){
	passwd=passwordField.getText();
	return true;
      }
      else{ return false; }
    }
    public void showMessage(String message){
      JOptionPane.showMessageDialog(null, message);
    }
  }
  */

/*
  public static class MyProgressMonitor implements com.jcraft.jsch.ProgressMonitor{
    JProgressBar progressBar;
    JFrame frame;
    long count=0;
    long max=0;

    public void init(String info, long max){
      this.max=max;
      if(frame==null){
        frame=new JFrame();
	frame.setSize(200, 20);
        progressBar = new JProgressBar();
      }
      count=0;

      frame.setTitle(info);
      progressBar.setMaximum((int)max);
      progressBar.setMinimum((int)0);
      progressBar.setValue((int)count);
      progressBar.setStringPainted(true);

      JPanel p=new JPanel();
      p.add(progressBar);
      frame.getContentPane().add(progressBar);
      frame.setVisible(true);
      System.out.println("!info:"+info+", max="+max+" "+progressBar);
    }
    public void count(long count){
      this.count+=count;
      System.out.println("count: "+count);
      progressBar.setValue((int)this.count);
    }
    public void end(){
      System.out.println("end");
      progressBar.setValue((int)this.max);
      frame.setVisible(false);
    }
  }
*/

  public static class MyProgressMonitor implements SftpProgressMonitor{
    // ProgressMonitor monitor;
    long count=0;
    long max=0;
    public void init(int op, String src, String dest, long max){
      this.max=max;
      /* monitor=new ProgressMonitor(null, 
				  ((op==SftpProgressMonitor.PUT)? 
				   "put" : "get")+": "+src, 
				  "",  0, (int)max);
      */
      count=0;
      // monitor.setProgress((int)this.count);
      // monitor.setMillisToDecideToPopup(1000);
    }
    public boolean count(long count){
      this.count+=count;
      return true;
      // monitor.setProgress((int)this.count);
      // monitor.setNote("Completed "+this.count+" out of "+max+".");
      // return !(monitor.isCanceled());
    }
    public void end(){
      // monitor.close();
    }
  }

  private static String help =
"      Available commands:\n"+
"      * means unimplemented command.\n"+
"cd path                       Change remote directory to 'path'\n"+
"lcd path                      Change local directory to 'path'\n"+
"chgrp grp path                Change group of file 'path' to 'grp'\n"+
"chmod mode path               Change permissions of file 'path' to 'mode'\n"+
"chown own path                Change owner of file 'path' to 'own'\n"+
"help                          Display this help text\n"+
"get remote-path [local-path]  Download file\n"+
"get-resume remote-path [local-path]  Resume to download file.\n"+
"get-append remote-path [local-path]  Append remote file to local file\n"+
"*lls [ls-options [path]]      Display local directory listing\n"+
"ln oldpath newpath            Symlink remote file\n"+
"*lmkdir path                  Create local directory\n"+
"lpwd                          Print local working directory\n"+
"ls [path]                     Display remote directory listing\n"+
"*lumask umask                 Set local umask to 'umask'\n"+
"mkdir path                    Create remote directory\n"+
"put local-path [remote-path]  Upload file\n"+
"put-resume local-path [remote-path]  Resume to upload file\n"+
"put-append local-path [remote-path]  Append local file to remote file.\n"+
"pwd                           Display remote working directory\n"+
"stat path                     Display info about path\n"+
"exit                          Quit sftp\n"+
"quit                          Quit sftp\n"+
"rename oldpath newpath        Rename remote file\n"+
"rmdir path                    Remove remote directory\n"+
"rm path                       Delete remote file\n"+
"symlink oldpath newpath       Symlink remote file\n"+
"rekey                         Key re-exchanging\n"+
"compression level             Packet compression will be enabled\n"+
"version                       Show SFTP version\n"+
"?                             Synonym for help";
}
