# HG changeset patch # User wenzelm # Date 1476047320 -7200 # Node ID a967b5a07f9204c09b3ab1c82987b4044cdabd65 # Parent f2c8f6b11dcf74c7d48efb60555ffe48f3851907 support for SSH in Isabelle/Scala; diff -r f2c8f6b11dcf -r a967b5a07f92 Admin/components/components.sha1 --- a/Admin/components/components.sha1 Sun Oct 09 16:27:01 2016 +0200 +++ b/Admin/components/components.sha1 Sun Oct 09 23:08:40 2016 +0200 @@ -153,6 +153,7 @@ 5659440f6b86db29f0c9c0de7249b7e24a647126 scala-2.9.2.tar.gz 43b5afbcad575ab6817d2289756ca22fd2ef43a9 spass-3.8ds.tar.gz 8d20968603f45a2c640081df1ace6a8b0527452a sqlite-jdbc-3.8.11.2.tar.gz +2369f06e8d095f9ba26df938b1a96000e535afff ssh-java-20161009.tar.gz 1f4a2053cc1f34fa36c4d9d2ac906ad4ebc863fd sumatra_pdf-2.1.1.tar.gz 601e08d048d8e50b0729429c8928b667d9b6bde9 sumatra_pdf-2.3.2.tar.gz 14d46c2eb1a34821703da59d543433f581e91df3 sumatra_pdf-2.4.tar.gz diff -r f2c8f6b11dcf -r a967b5a07f92 Admin/components/main --- a/Admin/components/main Sun Oct 09 16:27:01 2016 +0200 +++ b/Admin/components/main Sun Oct 09 23:08:40 2016 +0200 @@ -12,6 +12,7 @@ kodkodi-1.5.2 polyml-5.6-1 scala-2.11.8 +ssh-java-20161009 spass-3.8ds sqlite-jdbc-3.8.11.2 xz-java-1.5 diff -r f2c8f6b11dcf -r a967b5a07f92 src/Pure/General/ssh.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Pure/General/ssh.scala Sun Oct 09 23:08:40 2016 +0200 @@ -0,0 +1,107 @@ +/* Title: Pure/General/ssh.scala + Author: Makarius + +Support for Secure Shell. +*/ + +package isabelle + + +import com.jcraft.jsch.{JSch, Logger => JSch_Logger, Session => JSch_Session, + OpenSSHConfig, UserInfo, ChannelExec, ChannelSftp} + + +object SSH +{ + /* init */ + + def apply(config_dir: Path = Path.explode("~/.ssh"), + config_file: Path = Path.explode("~/.ssh/config"), + identity_files: List[Path] = + List("~/.ssh/id_dsa", "~/.ssh/id_ecdsa", "~/.ssh/id_rsa").map(Path.explode(_))): SSH = + { + if (!config_dir.is_dir) error("Bad ssh config directory: " + config_dir) + + val jsch = new JSch + + if (config_file.is_file) + jsch.setConfigRepository(OpenSSHConfig.parseFile(File.platform_path(config_file))) + + val known_hosts = config_dir + Path.explode("known_hosts") + if (!known_hosts.is_file) known_hosts.file.createNewFile + jsch.setKnownHosts(File.platform_path(known_hosts)) + + for (identity_file <- identity_files if identity_file.is_file) + jsch.addIdentity(File.platform_path(identity_file)) + + new SSH(jsch) + } + + + /* logging */ + + def logging(verbose: Boolean = true, debug: Boolean = false) + { + JSch.setLogger(if (verbose) new Logger(debug) else null) + } + + private class Logger(debug: Boolean) extends JSch_Logger + { + def isEnabled(level: Int): Boolean = level != JSch_Logger.DEBUG || debug + + def log(level: Int, msg: String) + { + level match { + case JSch_Logger.ERROR | JSch_Logger.FATAL => Output.error_message(msg) + case JSch_Logger.WARN => Output.warning(msg) + case _ => Output.writeln(msg) + } + } + } + + + /* session */ + + class Session private[SSH](val jsch: JSch, val session: JSch_Session) + { + override def toString: String = + (if (session.getUserName == null) "" else session.getUserName + "@") + + (if (session.getHost == null) "" else session.getHost) + + (if (session.getPort == 22) "" else ":" + session.getPort) + + def open: Session = { session.connect; this } + def close: Session = { session.disconnect; this } + + def channel_exec: ChannelExec = + session.openChannel("exec").asInstanceOf[ChannelExec] + + def channel_sftp: ChannelSftp = + session.openChannel("sftp").asInstanceOf[ChannelSftp] + } + + object No_User_Info extends UserInfo + { + def getPassphrase: String = null + def getPassword: String = null + def promptPassword(msg: String): Boolean = false + def promptPassphrase(msg: String): Boolean = false + def promptYesNo(msg: String): Boolean = false + def showMessage(msg: String): Unit = Output.writeln(msg) + } +} + +class SSH private(val jsch: JSch) +{ + def session(host: String, port: Int = 22, user: String = null, + compression: Boolean = true): SSH.Session = + { + val session = jsch.getSession(user, host, port) + if (compression) { + session.setConfig("compression.s2c", "zlib@openssh.com,zlib,none") + session.setConfig("compression.c2s", "zlib@openssh.com,zlib,none") + session.setConfig("compression_level", "9") + } + session.setUserInfo(SSH.No_User_Info) + new SSH.Session(jsch, session) + } +} diff -r f2c8f6b11dcf -r a967b5a07f92 src/Pure/build-jars --- a/src/Pure/build-jars Sun Oct 09 16:27:01 2016 +0200 +++ b/src/Pure/build-jars Sun Oct 09 23:08:40 2016 +0200 @@ -48,6 +48,7 @@ General/sha1.scala General/sql.scala General/sqlite.scala + General/ssh.scala General/symbol.scala General/time.scala General/timing.scala