1 21 22 package org.armedbear.j; 23 24 import gnu.regexp.RE; 25 import gnu.regexp.REException; 26 import gnu.regexp.REMatch; 27 import gnu.regexp.UncheckedRE; 28 import java.io.IOException ; 29 import java.io.OutputStreamWriter ; 30 import java.util.ArrayList ; 31 import java.util.List ; 32 import javax.swing.SwingUtilities ; 33 34 public final class SshSession implements Constants 35 { 36 public static final int DEFAULT_PORT = 22; 37 38 private static final int TRY_AGAIN = 0; 39 private static final int AUTHENTICATED = 1; 40 private static final int PASSWORD = 2; 41 private static final int PASSPHRASE = 3; 42 private static final int YES = 4; 43 private static final int NO = 5; 44 45 private static final String PROMPT = "$ "; 46 47 private static ArrayList sessionList; 48 49 private static CleanupThread cleanupThread; 50 51 private String hostName; 52 private String userName; 53 private String password; 54 private String passphrase; 55 private int port; 56 57 private boolean locked; 58 59 private Process process; 60 61 private OutputStreamWriter stdin; 62 private StdoutThread stdoutThread; 63 private StderrThread stderrThread; 64 65 private FastStringBuffer output = new FastStringBuffer(); 66 67 private boolean connected; 68 69 private String loginDirectory; 70 71 private boolean echo; 72 73 private String cd = "\\cd"; 75 76 private Buffer outputBuffer; 77 78 private String passwordTitle; 79 private String passwordPrompt; 80 81 private SshSession(SshFile file, boolean locked) 82 { 83 hostName = file.getHostName(); 84 Debug.assertTrue(hostName != null); 85 userName = file.getUserName(); 86 password = file.getPassword(); 87 port = file.getPort(); 88 this.locked = locked; 89 register(this); 90 } 91 92 private SshSession(SshSession other, boolean locked) 93 { 94 hostName = other.getHostName(); 95 Debug.assertTrue(hostName != null); 96 userName = other.getUserName(); 97 password = other.getPassword(); 98 passphrase = other.getPassphrase(); 99 port = other.getPort(); 100 this.locked = locked; 101 register(this); 102 } 103 104 private static synchronized void register(SshSession session) 105 { 106 if (sessionList == null) 107 sessionList = new ArrayList (); 108 sessionList.add(session); 109 if (cleanupThread == null) { 110 cleanupThread = new CleanupThread(cleanupRunnable); 111 cleanupThread.start(); 112 } 113 Log.debug("leaving register() session count = " + sessionList.size()); 114 } 115 116 private static synchronized void unregister(SshSession session) 117 { 118 if (sessionList == null) { 119 Debug.bug(); 120 return; 121 } 122 if (!sessionList.contains(session)) 123 Debug.bug(); 124 sessionList.remove(session); 125 Log.debug("leaving unregister() session count = " 126 + sessionList.size()); 127 } 128 129 public static synchronized SshSession getSession(SshFile file) 130 { 131 if (file == null) { 132 Debug.bug(); 133 return null; 134 } 135 if (file.getHostName() == null) { 136 Debug.bug(); 137 return null; 138 } 139 if (file.getUserName() == null) { 140 Debug.bug(); 141 file.setUserName(System.getProperty("user.name")); 142 } 143 SshSession session = lockSession(file); 144 if (session != null) 145 return session; 146 session = findSession(file); 148 if (session != null) 149 return new SshSession(session, true); 150 return new SshSession(file, true); 152 } 153 154 private static SshSession lockSession(SshFile file) 156 { 157 if (sessionList != null) { 158 for (int i = sessionList.size(); i-- > 0;) { 159 SshSession session = (SshSession) sessionList.get(i); 160 if (session.getUserName().equals(file.getUserName())) { 161 if (session.getHostName().equals(file.getHostName())) { 162 if (session.getPort() == file.getPort()) { 163 if (session.lock()) { 164 return session; 165 } 166 } 167 } 168 } 169 } 170 } 171 return null; 172 } 173 174 private static SshSession findSession(SshFile file) 176 { 177 if (sessionList != null) { 178 for (int i = sessionList.size(); i-- > 0;) { 179 SshSession session = (SshSession) sessionList.get(i); 180 if (session.getUserName().equals(file.getUserName())) { 181 if (session.getHostName().equals(file.getHostName())) { 182 if (session.getPort() == file.getPort()) { 183 return session; 184 } 185 } 186 } 187 } 188 } 189 return null; 190 } 191 192 public final synchronized boolean isLocked() 193 { 194 return locked; 195 } 196 197 private synchronized boolean lock() 198 { 199 if (locked) 200 return false; 201 locked = true; 202 return true; 203 } 204 205 public synchronized void unlock() 206 { 207 if (locked) 208 locked = false; 209 else 210 Debug.bug("SshSession.unlock session was not locked"); 211 synchronized (SshSession.class) { 212 if (sessionList != null) 213 Log.debug("unlock session count = " + sessionList.size()); 214 else 215 Debug.bug("SshSession.unlock no session list"); 216 } 217 } 218 219 public final String getHostName() 220 { 221 return hostName; 222 } 223 224 public final String getUserName() 225 { 226 return userName; 227 } 228 229 public final String getPassword() 230 { 231 return password; 232 } 233 234 public final void setPassword(String password) 235 { 236 this.password = password; 237 } 238 239 public final String getPassphrase() 240 { 241 return passphrase; 242 } 243 244 public final int getPort() 245 { 246 return port; 247 } 248 249 public final String getLoginDirectory() 250 { 251 return loginDirectory; 252 } 253 254 public void setOutputBuffer(Buffer buf) 255 { 256 outputBuffer = buf; 257 } 258 259 public boolean isDirectory(String canonicalPath) 260 { 261 SshFile file = 262 new SshFile(hostName, canonicalPath, userName, null, port); 263 if (DirectoryCache.getDirectoryCache().getListing(file) != null) 264 return true; 265 if (!connect()) 266 return false; 267 try { 268 return changeDirectory(canonicalPath); 269 } 270 catch (Exception e) { 271 Log.error(e); 272 } 273 try { 275 Thread.sleep(1000); 276 } 277 catch (InterruptedException e) { 278 Log.error(e); 279 } 280 try { 282 Log.warn("isDirectory() retrying after exception ..."); 283 command(""); 285 return changeDirectory(canonicalPath); 286 } 287 catch (Exception e) { 288 Log.error(e); 290 return false; 291 } 292 } 293 294 private String stat(String canonicalPath) 295 { 296 FastStringBuffer sb = new FastStringBuffer("stat -t \""); 297 sb.append(canonicalPath); 298 sb.append('"'); 299 String cmd = sb.toString(); 300 String response = command(cmd); 301 Log.debug(cmd + " " + response); 302 if (response != null && response.startsWith(canonicalPath)) 303 return response.substring(canonicalPath.length()).trim(); 304 return null; 305 } 306 307 private static int getType(String s) 309 { 310 if (s != null) { 311 List tokens = Utilities.tokenize(s); 312 if (tokens.size() == 14) { 313 String token = (String ) tokens.get(2); 314 Log.debug("token = |" + token + "|"); 315 try { 316 int n = Integer.parseInt(token, 16); 317 Log.debug("n = " + Integer.toString(n, 8)); 318 if ((n & 0040000) == 0040000) 319 return File.TYPE_DIRECTORY; 320 if ((n & 0120000) == 0120000) 321 return File.TYPE_LINK; 322 if ((n & 0100000) == 0100000) 323 return File.TYPE_FILE; 324 } 325 catch (NumberFormatException e) {} 326 } 327 } 328 return File.TYPE_UNKNOWN; 329 } 330 331 private boolean changeDirectory(String canonicalPath) throws Exception 333 { 334 FastStringBuffer sb = new FastStringBuffer(cd); 335 sb.append(" \""); 336 sb.append(canonicalPath); 337 sb.append('"'); 338 String cmd = sb.toString(); 339 Log.debug("changeDirectory cmd = |" + cmd + "|"); 340 String response = command(cmd); 341 Log.debug("changeDirectory response = |" + response + "|"); 342 if (response == null) 343 throw new Exception (); if (response.indexOf("Command not found") >= 0) { 345 if (cd.equals("\\cd")) { 346 cd = "cd"; 348 response = command(cd + " \"" + canonicalPath + '"'); 349 if (response == null) 350 throw new Exception (); } else 352 return false; 353 } 354 if (response.equals(PROMPT)) { 355 Log.debug("changeDirectory succeeded"); 357 return true; 358 } 359 String lower = response.toLowerCase(); 360 if (lower.indexOf("not a directory") >= 0) 361 return false; 362 else if (lower.indexOf("no such file or directory") >= 0) 363 return false; 364 int index = response.indexOf('\r'); 367 if (index < 0) 368 index = response.indexOf('\n'); 369 if (index >= 0) { 370 String beginning = response.substring(0, index); 371 Log.debug("beginning = |" + beginning + "|"); 372 if (cmd.startsWith(beginning)) { 373 Log.debug("cmd starts with beginning!"); 374 index = response.lastIndexOf((char)8); 375 if (index >= 0) { 376 Log.debug("backspace found!"); 377 String end = response.substring(index+1); 378 Log.debug("end = |" + end + "|"); 379 if (cmd.endsWith(end)) { 380 Log.debug("cmd ends with end!"); 381 return true; 382 } 383 } 384 } 385 } 386 throw new Exception (); 388 } 389 390 public boolean exists(String canonicalPath) 391 { 392 if (connect()) { 393 String response = lsld(canonicalPath); 394 if (response != null && response.length() > 0) { 395 char c = response.charAt(0); 396 if (c == 'd' || c == '-') 397 return true; 398 } 399 } 400 return false; 401 } 402 403 public static String getDirectoryListing(File file) 404 { 405 if (!(file instanceof SshFile)) { 406 Debug.assertTrue(false); 407 return null; 408 } 409 String listing = DirectoryCache.getDirectoryCache().getListing(file); 410 if (listing == null) { 411 SshSession session = getSession((SshFile)file); 412 if (session != null) { 413 listing = session.retrieveDirectoryListing(file); 414 session.unlock(); 415 if (listing != null) 416 DirectoryCache.getDirectoryCache().put(file, listing); 417 } 418 } 419 return listing; 420 } 421 422 public String retrieveDirectoryListing(File file) 423 { 424 if (!(file instanceof SshFile)) { 425 Debug.bug(); 426 return null; 427 } 428 if (!isLocked()) { 429 Debug.bug(); 430 return null; 431 } 432 if (connect()) { 433 try { 434 if (changeDirectory(file.canonicalPath())) 436 return lsla(); 438 } 439 catch (Exception e) { 440 Log.error(e); 441 } 442 } 443 return null; 444 } 445 446 public synchronized boolean chmod(SshFile file, int permissions) 447 { 448 if (permissions != 0 && connect()) { 449 FastStringBuffer sb = new FastStringBuffer("chmod "); 450 sb.append(Integer.toString(permissions, 8)); 451 sb.append(' '); 452 sb.append(file.canonicalPath()); 453 final String response = command(sb.toString()); 454 if (response != null && response.indexOf("chmod:") < 0) { 456 DirectoryCache.getDirectoryCache().purge(file); 458 return true; 459 } 460 } 461 return false; 462 } 463 464 public synchronized boolean isConnected() 465 { 466 return connected; 467 } 468 469 public synchronized boolean connect() 470 { 471 if (connected) { 472 Log.debug("SshSession.connect(): already connected"); 473 return true; 474 } 475 FastStringBuffer sb = new FastStringBuffer("jpty ssh "); 476 if (userName != null && userName.length() > 0) { 477 sb.append("-l "); 478 sb.append(userName); 479 sb.append(' '); 480 } 481 if (port != DEFAULT_PORT) { 482 sb.append("-p "); 483 sb.append(port); 484 sb.append(' '); 485 } 486 sb.append(hostName); 487 try { 488 process = Runtime.getRuntime().exec(sb.toString()); 489 } 490 catch (Throwable t) { 491 Log.error(t); 492 return false; 493 } 494 try { 495 stdin = new OutputStreamWriter (process.getOutputStream()); 496 int timeout = 497 Editor.preferences().getIntegerProperty(Property.SSH_TIMEOUT); 498 Log.debug("ssh timeout is " + timeout + " ms"); 499 stdoutThread = new StdoutThread(); 500 stdoutThread.setTimeOut(timeout); 501 stderrThread = new StderrThread(); 502 stderrThread.setTimeOut(timeout); 503 stdoutThread.start(); 504 stderrThread.start(); 505 } 506 catch (Throwable t) { 507 Log.error(t); 508 return false; 509 } 510 if (!authenticate()) { 511 killProcess(); 512 String message = output.toString().trim(); 513 if (message.length() == 0) 514 message = "Authentication failed"; 515 MessageDialog.showMessageDialog(message, "Error"); 516 return false; 517 } 518 if (!connected) { 519 killProcess(); 520 MessageDialog.showMessageDialog("Lost connection", "Error"); 521 } 522 return connected; 523 } 524 525 private void initializeConnection() 526 { 527 boolean oldEcho = echo; 528 echo = true; 529 String response = command("exec /bin/sh"); 530 Log.debug("response = |" + response + "|"); 531 FastStringBuffer sb = new FastStringBuffer("PS1='"); 532 sb.append(PROMPT); 533 sb.append('\''); 534 response = command(sb.toString()); 535 Log.debug("response = |" + response + "|"); 536 Log.debug("PROMPT = |" + PROMPT + "|"); 537 command("unset MAILCHECK"); 538 loginDirectory = getCurrentDirectory(); 539 connected = (loginDirectory != null); 540 echo = oldEcho; 541 } 542 543 private boolean authenticate() 544 { 545 output.setLength(0); 546 int response; 547 while ((response = checkInitialResponse()) == TRY_AGAIN) { 548 Log.debug("authenticate() TRY_AGAIN"); 549 try { 550 final long TIMEOUT = 30000; long start = System.currentTimeMillis(); 552 wait(TIMEOUT); 553 if (System.currentTimeMillis() - start > TIMEOUT) 554 return false; 555 } 556 catch (InterruptedException e) { 557 Log.debug("SshSession.connect interrupted!"); 558 return false; 559 } 560 } 561 if (response == AUTHENTICATED) { 562 initializeConnection(); 563 return connected; 564 } 565 if (response == PASSWORD) 566 return authenticateWithPassword(); 567 if (response == PASSPHRASE) 568 return authenticateWithPassphrase(); 569 return false; 570 } 571 572 private boolean authenticateWithPassword() 573 { 574 if (password == null) { 575 password = Netrc.getPassword(hostName, userName); 576 if (password == null) { 577 if (SwingUtilities.isEventDispatchThread()) 578 getPasswordRunnable.run(); 579 else { 580 try { 581 SwingUtilities.invokeAndWait(getPasswordRunnable); 582 } 583 catch (Exception e) { 584 Log.error(e); 585 } 586 } 587 if (password == null) { 588 killProcess(); 589 return false; 590 } 591 } 592 } 593 return _authenticate(password); 594 } 595 596 private boolean authenticateWithPassphrase() 597 { 598 if (passphrase == null) { 599 if (SwingUtilities.isEventDispatchThread()) 600 getPassphraseRunnable.run(); 601 else { 602 try { 603 SwingUtilities.invokeAndWait(getPassphraseRunnable); 604 } 605 catch (Exception e) { 606 Log.error(e); 607 } 608 } 609 if (passphrase == null) { 610 killProcess(); 611 return false; 612 } 613 } 614 return _authenticate(passphrase); 615 } 616 617 private boolean _authenticate(String pass) 618 { 619 output.setLength(0); 620 boolean oldEcho = echo; 621 echo = true; 622 sendPass(pass); 623 if (checkAuthenticationResponse()) { 624 Log.debug("authenticate SUCCEEDED!"); 625 initializeConnection(); 626 echo = oldEcho; 627 return connected; 628 } else { 629 Log.debug("authenticate FAILED!"); 630 echo = oldEcho; 631 return false; 632 } 633 } 634 635 private int checkInitialResponse() 636 { 637 final String s = output.toString().trim(); 638 String check; 639 int index = s.lastIndexOf("\r\n"); 640 if (index >= 0) { 641 check = s.substring(index+2); 642 } else { 643 index = s.lastIndexOf('\n'); 644 if (index >=0 ) 645 check = s.substring(index+1); 646 else 647 check = s; 648 } 649 Log.debug("check = |" + check + "|"); 650 String lower = check.toLowerCase(); 651 if (lower.indexOf("connection refused") >= 0) 652 return NO; 653 if (lower.endsWith("password:")) { 654 passwordTitle = "Password"; 655 passwordPrompt = check; 656 return PASSWORD; 657 } 658 if (s.startsWith("Password:") && lower.endsWith("response:")) { 659 passwordTitle = "Password"; 660 passwordPrompt = check; 661 return PASSWORD; 662 } 663 if (lower.startsWith("enter passphrase ") && lower.endsWith(":")) { 664 password = null; 666 passwordTitle = "Passphrase"; 667 passwordPrompt = check; 668 return PASSPHRASE; 669 } 670 RE promptRE = getPromptRE(); 671 if (promptRE.getMatch(lower) != null) 672 return AUTHENTICATED; 673 return TRY_AGAIN; 674 } 675 676 private boolean checkAuthenticationResponse() 677 { 678 String s = output.toString(); 679 Log.debug("checkAuthenticationResponse output = |" + output + "|"); 680 int result = checkResponse(s); 681 Log.debug("checkAuthenticationResponse result = " + result); 682 while (result == TRY_AGAIN) { 683 try { 684 wait(); 685 } 686 catch (InterruptedException e) { 687 Log.error(e); 688 return false; 689 } 690 s = output.toString(); 691 Log.debug("checkAuthenticationResponse output = |" + output + "|"); 692 result = checkResponse(s); 693 Log.debug("checkAuthenticationResponse result = " + result); 694 } 695 Log.debug("checkAuthenticationResponse returning " + (result == YES)); 696 return result == YES; 697 } 698 699 private int checkResponse(String s) 701 { 702 if (s.toLowerCase().indexOf("denied") >= 0) 703 return NO; 704 String prompt = null; 705 for (int i = s.length(); i-- > 0;) { 706 char c = s.charAt(i); 707 if (c == '\r' || c == '\n') { 708 prompt = s.substring(i+1); 709 break; 710 } 711 } 712 if (prompt == null) 713 prompt = s; 714 Log.debug("prompt = |" + reveal(prompt) + "|"); 715 RE promptRE = getPromptRE(); 716 Debug.assertTrue(promptRE != null); 717 REMatch match = promptRE.getMatch(prompt); 718 if (match != null) 719 return YES; 720 return TRY_AGAIN; 721 } 722 723 private RE _promptRE; 724 725 public RE getPromptRE() 726 { 727 if (_promptRE == null) { 728 try { 729 _promptRE = new RE(Editor.preferences(). 730 getStringProperty(Property.SSH_PROMPT_PATTERN)); 731 } 732 catch (REException e) { 733 Log.error(e); 734 _promptRE = new UncheckedRE(DEFAULT_SHELL_PROMPT_PATTERN); 735 } 736 } 737 Debug.assertTrue(_promptRE != null); 738 return _promptRE; 739 } 740 741 private Runnable getPasswordRunnable = new Runnable () { 742 public void run() 743 { 744 final Editor editor = Editor.currentEditor(); 745 editor.setDefaultCursor(); 746 password = PasswordDialog.showPasswordDialog(editor, passwordPrompt, 747 passwordTitle); 748 editor.setWaitCursor(); 749 } 750 }; 751 752 private Runnable getPassphraseRunnable = new Runnable () { 753 public void run() 754 { 755 final Editor editor = Editor.currentEditor(); 756 editor.setDefaultCursor(); 757 passphrase = PasswordDialog.showPasswordDialog(editor, passwordPrompt, 758 passwordTitle); 759 editor.setWaitCursor(); 760 } 761 }; 762 763 private String getCurrentDirectory() 764 { 765 final String s = command("pwd"); 766 if (s == null) 767 return null; int index = s.indexOf("\r\n"); 769 if (index < 0) 770 index = s.indexOf('\n'); 771 final String dir = index >= 0 ? s.substring(0, index) : s; 772 Log.debug("getCurrentDirectory() returning |" + dir + "|"); 773 return dir; 774 } 775 776 private void disconnect() 777 { 778 if (connected) { 779 try { 780 stdin.write("exit\n"); 781 } 782 catch (Exception e) { 783 Log.error(e); 784 } 785 killProcess(); 786 } 787 } 788 789 private void killProcess() 790 { 791 Process p = process; if (p != null) { 793 try { 794 Log.debug("calling Process.destroy()"); 795 p.destroy(); 796 Log.debug("calling Process.waitFor()"); 797 p.waitFor(); 798 } 799 catch (InterruptedException e) { 800 Log.error(e); 801 } 802 process = null; 803 synchronized (this) { 804 if (stdin != null) { 805 try { 806 stdin.close(); 807 } 808 catch (IOException e) { 809 Log.error(e); 810 } 811 stdin = null; 812 } 813 if (stdoutThread != null) { 814 stdoutThread.cancel(); 815 stdoutThread = null; 816 } 817 if (stderrThread != null) { 818 stderrThread.cancel(); 819 stderrThread = null; 820 } 821 } 822 } 823 connected = false; 824 } 825 826 public synchronized final void dispose() 827 { 828 Log.debug("SshSession.dispose"); 829 if (connected) 830 disconnect(); 831 unregister(this); 832 } 833 834 private synchronized String command(String cmd) 835 { 836 if (!write(cmd.concat("\n"))) 837 return null; 838 output.setLength(0); 839 while (output.length() == 0) { 840 try { 841 wait(); 842 } 843 catch (InterruptedException e) { 844 Log.error(e); 845 } 846 } 847 String s = output.toString(); 848 if (s.startsWith(cmd)) { 850 int i = cmd.length(); 851 while (i < s.length()) { 852 char c = s.charAt(i); 853 if (c == '\r' || c == '\n') 854 ++i; 855 else 856 break; 857 } 858 if (i > cmd.length()) 859 s = s.substring(i); 860 } 861 int index = s.lastIndexOf("\r\n"); 863 if (index >= 0) { 864 s = s.substring(0, index); 865 } else { 866 index = s.lastIndexOf('\n'); 867 if (index >= 0) 868 s = s.substring(0, index); 869 } 870 return s; 871 } 872 873 private static final RE totalRE = new UncheckedRE("\\n?[^0-9]+ [0-9]+"); 874 875 private synchronized String lsla() 876 { 877 boolean valid = false; 878 if (!write("\\ls -la\n")) 879 return null; 880 output.setLength(0); 881 String s = null; 882 for (int i = 0; i < 2; i++) { 883 if (i > 0) 884 Log.debug("lsla retry " + i); 885 try { 886 wait(); 887 } 888 catch (InterruptedException e) { 889 Log.error(e); 890 return null; 891 } 892 s = output.toString(); 893 REMatch match = totalRE.getMatch(s); 894 Log.debug("match = |" + match + "|"); 895 if (match == null) { 896 Log.error("lsla no \"total\" line"); 897 continue; 898 } 899 s = s.substring(match.getEndIndex()); 900 int index = s.indexOf('\n'); 901 if (index < 0) { 902 Log.error("lsla no '\\n'"); 904 continue; 905 } 906 s = s.substring(index + 1); 907 valid = true; 908 break; 909 } 910 if (!valid) { 911 Log.error("lsla output not valid - returning null"); 912 return null; 913 } 914 int index = s.lastIndexOf("\r\n"); 916 if (index >= 0) 917 s = s.substring(0, index); 918 else { 919 index = s.lastIndexOf('\n'); 920 if (index >= 0) 921 s = s.substring(0, index); 922 } 923 return s; 924 } 925 926 private synchronized String lsld(String path) 928 { 929 Debug.assertTrue(path != null); 930 Debug.assertTrue(path.length() != 0); 931 FastStringBuffer sb = new FastStringBuffer("\\ls -ld \""); 932 sb.append(path); 933 sb.append('"'); 934 sb.append('\n'); 935 if (!write(sb.toString())) 936 return null; 937 output.setLength(0); 938 while (output.length() == 0){ 939 try { 940 wait(); 941 } 942 catch (InterruptedException e) { 943 Log.error(e); 944 } 945 } 946 String s = output.toString(); 947 948 if (s.startsWith("ls -ld ")) { 950 int index = s.indexOf('\n'); 952 if (index < 0) 953 return null; s = s.substring(index + 1); 955 } 956 957 while (s.length() > 0 && s.charAt(0) == '<') { 959 int index = s.indexOf('\n'); 960 if (index < 0) 961 return null; s = s.substring(index + 1); 963 } 964 965 int index = s.indexOf("\r\n"); 967 if (index >= 0) { 968 s = s.substring(0, index); 969 } else { 970 index = s.lastIndexOf('\n'); 971 if (index >= 0) 972 s = s.substring(0, index); 973 } 974 return s; 975 } 976 977 private void sendPass(String pass) 979 { 980 Debug.assertTrue(pass != null); 981 try { 982 stdin.write(pass); 983 stdin.write("\n"); 984 stdin.flush(); 985 if (outputBuffer != null) { 986 FastStringBuffer sb = new FastStringBuffer("==> "); 987 for (int i = pass.length(); i-- > 0;) 988 sb.append('*'); 989 sb.append('\n'); 990 writeToOutputBuffer(sb.toString()); 991 } 992 } 993 catch (Exception e) { 994 Log.error(e); 995 } 996 } 997 998 private boolean write(String s) 999 { 1000 try { 1001 if (echo || Editor.preferences().getBooleanProperty(Property.SSH_ECHO)) 1002 Log.debug("==> |" + s + "|"); 1003 if (outputBuffer != null) 1004 writeToOutputBuffer("==> " + s); 1005 stdin.write(s); 1006 stdin.flush(); 1007 return true; 1008 } 1009 catch (IOException e) { 1010 Log.error(e); 1011 killProcess(); 1012 return false; 1013 } 1014 } 1015 1016 private void writeToOutputBuffer(final String s) 1017 { 1018 Runnable r = new Runnable () { 1019 public void run() 1020 { 1021 final Buffer buf = outputBuffer; 1024 if (buf == null) 1025 return; 1026 try { 1027 buf.lockWrite(); 1028 } 1029 catch (InterruptedException e) { 1030 Log.debug(e); 1031 return; 1032 } 1033 try { 1034 buf.append(s); 1035 buf.renumber(); 1036 } 1037 finally { 1038 buf.unlockWrite(); 1039 } 1040 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1041 Editor ed = it.nextEditor(); 1042 if (ed.getBuffer() == buf) { 1043 ed.setDot(buf.getEnd()); 1044 ed.moveCaretToDotCol(); 1045 ed.setUpdateFlag(REPAINT); 1046 ed.updateDisplay(); 1047 } 1048 } 1049 } 1050 }; 1051 SwingUtilities.invokeLater(r); 1052 } 1053 1054 public void checkLogin() 1055 { 1056 if (userName == null) 1057 userName = System.getProperty("user.name"); 1058 if (password == null) { 1059 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 1060 Buffer buf = it.nextBuffer(); 1061 if (buf.getFile() instanceof SshFile) { 1062 SshFile f = (SshFile) buf.getFile(); 1063 if (f.hostName != null && f.hostName.equals(hostName)) { 1064 if (f.getUserName() != null && f.getUserName().equals(userName)) { 1065 password = f.getPassword(); 1066 break; 1067 } 1068 } 1069 } 1070 } 1071 } 1072 } 1073 1074 private static synchronized void cleanup() 1075 { 1076 if (!SwingUtilities.isEventDispatchThread()) { 1078 Debug.bug(); 1079 return; 1080 } 1081 if (sessionList != null) { 1082 for (int i = sessionList.size(); i-- > 0;) { 1083 SshSession session = (SshSession) sessionList.get(i); 1084 if (session.isLocked()) 1085 continue; 1086 String hostName = session.getHostName(); 1087 boolean inUse = false; 1088 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 1089 Buffer buf = it.nextBuffer(); 1090 if (buf.getFile() instanceof SshFile) { 1091 if (hostName.equals(buf.getFile().getHostName())) { 1092 inUse = true; 1093 break; 1094 } 1095 } 1096 } 1097 if (!inUse) 1098 session.dispose(); 1099 } 1100 if (sessionList.size() == 0) { 1101 sessionList = null; 1102 if (cleanupThread != null) { 1103 cleanupThread.cancel(); 1104 cleanupThread = null; 1105 } 1106 } 1107 } 1108 } 1109 1110 private static final Runnable cleanupRunnable = new Runnable () { 1111 public void run() 1112 { 1113 cleanup(); 1114 } 1115 }; 1116 1117 private String stdOutFilter(String s) 1118 { 1119 return s; 1120 } 1121 1122 private synchronized void stdOutUpdate(final String s) 1123 { 1124 if (echo || Editor.preferences().getBooleanProperty(Property.SSH_ECHO)) 1125 Log.debug("<== |" + s + "|"); 1126 if (outputBuffer != null) 1127 writeToOutputBuffer(s); 1128 output.append(s); 1129 notify(); 1130 } 1131 1132 private String stdErrFilter(String s) 1133 { 1134 return s; 1135 } 1136 1137 private void stdErrUpdate(final String s) 1138 { 1139 Log.debug("stderr: |" + s + "|"); 1140 } 1141 1142 private static String reveal(String s) 1143 { 1144 FastStringBuffer sb = new FastStringBuffer(); 1145 final int length = s.length(); 1146 for (int i = 0; i < length; i++) { 1147 char c = s.charAt(i); 1148 switch (c) { 1149 case '\r': 1150 sb.append("\\r"); 1151 break; 1152 case '\n': 1153 sb.append("\\n"); 1154 break; 1155 case '\t': 1156 sb.append("\\t"); 1157 break; 1158 default: 1159 sb.append(c); 1160 break; 1161 } 1162 } 1163 return sb.toString(); 1164 } 1165 1166 class StdoutThread extends ReaderThread 1167 { 1168 StdoutThread() 1170 { 1171 super(process.getInputStream()); 1172 } 1173 1174 public String filter(String s) 1175 { 1176 return stdOutFilter(s); 1177 } 1178 1179 public void update(String s) 1180 { 1181 stdOutUpdate(s); 1182 } 1183 } 1184 1185 class StderrThread extends ReaderThread 1186 { 1187 StderrThread() 1189 { 1190 super(process.getErrorStream()); 1191 } 1192 1193 public String filter(String s) 1194 { 1195 return stdErrFilter(s); 1196 } 1197 1198 public void update(String s) 1199 { 1200 stdErrUpdate(s); 1201 } 1202 } 1203} 1204 | Popular Tags |