[MERGE] Refactor loopback/paramiko/openssh/ssh connection opening
Andrew Bennetts
andrew at canonical.com
Fri Aug 25 06:30:41 BST 2006
Hi all,
This bundle gets rid of all the "if vendor == 'xxx'" statements scattered
throughout bzrlib/transport/sftp.py, and instead moves all the connection
establishing logic into a new file, bzrlib/transport/ssh.py. Code that's
purely about establishing an SSH connection has been moved out of sftp.py,
leaving sftp.py with just SFTP logic.
In addition to the moved code, ssh.py defines a bunch of new classes inheriting
from SSHVendor, which provides a consistent interface to establishing an SFTP
connection, regardless of the method used to do this. Soon it will also do a
similar thing for opening pipes to a command run over SSH; the smart server will
use this to run over SSH.
It's likely that I've missed adding some helpful docstrings, but overall I think
this is much cleaner than what was there before. I think some further tidying
is possible (e.g. I think a bunch of the host key management code belongs in
paramiko, and may in fact be there already), but nothing is worse than it was
before, just moved :)
-Andrew.
-------------- next part --------------
# Bazaar revision bundle v0.8
#
# message:
# Add docstrings and tweak method names in ssh.py
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Fri 2006-08-25 15:05:39.924999952 +1000
=== added file bzrlib/transport/ssh.py // file-id:ssh.py-20060824042150-0s9787k
... ng6zv1nwq-1
--- /dev/null
+++ bzrlib/transport/ssh.py
@@ -0,0 +1,406 @@
+# Copyright (C) 2005 Robey Pointer <robey at lag.net>
+# Copyright (C) 2005, 2006 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Foundation SSH support for SFTP and smart server."""
+
+import errno
+import getpass
+import os
+import socket
+import subprocess
+import sys
+
+from bzrlib.config import config_dir, ensure_config_dir_exists
+from bzrlib.errors import (ConnectionError,
+ ParamikoNotPresent,
+ TransportError,
+ )
+
+from bzrlib.osutils import pathjoin
+from bzrlib.trace import mutter, warning
+import bzrlib.ui
+
+try:
+ import paramiko
+except ImportError, e:
+ raise ParamikoNotPresent(e)
+else:
+ from paramiko.sftp_client import SFTPClient
+
+
+SYSTEM_HOSTKEYS = {}
+BZR_HOSTKEYS = {}
+
+
+_paramiko_version = getattr(paramiko, '__version_info__', (0, 0, 0))
+
+# Paramiko 1.5 tries to open a socket.AF_UNIX in order to connect
+# to ssh-agent. That attribute doesn't exist on win32 (it does in cygwin)
+# so we get an AttributeError exception. So we will not try to
+# connect to an agent if we are on win32 and using Paramiko older than 1.6
+_use_ssh_agent = (sys.platform != 'win32' or _paramiko_version >= (1, 6, 0))
+
+
+def _ignore_sigint():
+ # TODO: This should possibly ignore SIGHUP as well, but bzr currently
+ # doesn't handle it itself.
+ # <https://launchpad.net/products/bzr/+bug/41433/+index>
+ import signal
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+
+
+class LoopbackSFTP(object):
+ """Simple wrapper for a socket that pretends to be a paramiko Channel."""
+
+ def __init__(self, sock):
+ self.__socket = sock
+
+ def send(self, data):
+ return self.__socket.send(data)
+
+ def recv(self, n):
+ return self.__socket.recv(n)
+
+ def recv_ready(self):
+ return True
+
+ def close(self):
+ self.__socket.close()
+
+
+class SSHVendor(object):
+ """Abstract base class for SSH vendor implementations."""
+
+ def connect_sftp(self, username, password, host, port):
+ """Make an SSH connection, and return an SFTPClient.
+
+ :param username: an ascii string
+ :param password: an ascii string
+ :param host: a host name as an ascii string
+ :param port: a port number
+ :type port: int
+
+ :raises: ConnectionError if it cannot connect.
+
+ :rtype: paramiko.sftp_client.SFTPClient
+ """
+ raise NotImplementedError(self.connect_sftp)
+
+ def connect_ssh(self, username, password, host, port, command):
+ """Make an SSH connection, and return a pipe-like object."""
+ raise NotImplementedError(self.connect_ssh)
+
+
+class LoopbackVendor(SSHVendor):
+ """SSH "vendor" that connects over a plain TCP socket, not SSH."""
+
+ def connect_sftp(self, username, password, host, port):
+ sock = socket.socket()
+ try:
+ sock.connect((host, port))
+ except socket.error, e:
+ raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
+ % (host, port, e))
+ return SFTPClient(LoopbackSFTP(sock))
+
+
+class ParamikoVendor(SSHVendor):
+ """Vendor that uses paramiko."""
+
+ def connect_sftp(self, username, password, host, port):
+ global SYSTEM_HOSTKEYS, BZR_HOSTKEYS
+
+ load_host_keys()
+
+ try:
+ t = paramiko.Transport((host, port or 22))
+ t.set_log_channel('bzr.paramiko')
+ t.start_client()
+ except (paramiko.SSHException, socket.error), e:
+ raise ConnectionError('Unable to reach SSH host %s:%s: %s'
+ % (host, port, e))
+
+ server_key = t.get_remote_server_key()
+ server_key_hex = paramiko.util.hexify(server_key.get_fingerprint())
+ keytype = server_key.get_name()
+ if SYSTEM_HOSTKEYS.has_key(host) and SYSTEM_HOSTKEYS[host].has_key(keytype):
+ our_server_key = SYSTEM_HOSTKEYS[host][keytype]
+ our_server_key_hex = paramiko.util.hexify(our_server_key.get_fingerprint())
+ elif BZR_HOSTKEYS.has_key(host) and BZR_HOSTKEYS[host].has_key(keytype):
+ our_server_key = BZR_HOSTKEYS[host][keytype]
+ our_server_key_hex = paramiko.util.hexify(our_server_key.get_fingerprint())
+ else:
+ warning('Adding %s host key for %s: %s' % (keytype, host, server_key_hex))
+ if not BZR_HOSTKEYS.has_key(host):
+ BZR_HOSTKEYS[host] = {}
+ BZR_HOSTKEYS[host][keytype] = server_key
+ our_server_key = server_key
+ our_server_key_hex = paramiko.util.hexify(our_server_key.get_fingerprint())
+ save_host_keys()
+ if server_key != our_server_key:
+ filename1 = os.path.expanduser('~/.ssh/known_hosts')
+ filename2 = pathjoin(config_dir(), 'ssh_host_keys')
+ raise TransportError('Host keys for %s do not match! %s != %s' % \
+ (host, our_server_key_hex, server_key_hex),
+ ['Try editing %s or %s' % (filename1, filename2)])
+
+ _paramiko_auth(username, password, host, t)
+
+ try:
+ sftp = t.open_sftp_client()
+ except paramiko.SSHException, e:
+ raise ConnectionError('Unable to start sftp client %s:%d' %
+ (host, port), e)
+ return sftp
+
+
+class SubprocessVendor(SSHVendor):
+ """Abstract base class for vendors that use pipes to a subprocess."""
+
+ def connect_sftp(self, username, password, host, port):
+ try:
+ argv = self._get_vendor_specific_argv(username, host, port,
+ subsystem='sftp')
+ proc = subprocess.Popen(argv,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ **os_specific_subprocess_params())
+ sock = SSHSubprocess(proc)
+ return SFTPClient(sock)
+ except (EOFError, paramiko.SSHException), e:
+ raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
+ % (host, port, e))
+ except (OSError, IOError), e:
+ # If the machine is fast enough, ssh can actually exit
+ # before we try and send it the sftp request, which
+ # raises a Broken Pipe
+ if e.errno not in (errno.EPIPE,):
+ raise
+ raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
+ % (host, port, e))
+
+ def _get_vendor_specific_argv(self, username, host, port, subsystem=None,
+ command=None):
+ """Returns the argument list to run the subprocess with.
+
+ Exactly one of 'subsystem' and 'command' must be specified.
+ """
+ raise NotImplementedError(self._get_vendor_specific_argv)
+
+
+class OpenSSHSubprocessVendor(SubprocessVendor):
+ """SSH vendor that uses the 'ssh' executable from OpenSSH."""
+
+ def _get_vendor_specific_argv(self, username, host, port, subsystem=None,
+ command=None):
+ assert subsystem is not None or command is not None, (
+ 'Must specify a command or subsystem')
+ if subsystem is not None:
+ assert command is None, (
+ 'subsystem and command are mutually exclusive')
+ args = ['ssh',
+ '-oForwardX11=no', '-oForwardAgent=no',
+ '-oClearAllForwardings=yes', '-oProtocol=2',
+ '-oNoHostAuthenticationForLocalhost=yes']
+ if port is not None:
+ args.extend(['-p', str(port)])
+ if username is not None:
+ args.extend(['-l', username])
+ if subsystem is not None:
+ args.extend(['-s', host, subsystem])
+ else:
+ args.extend([host] + command)
+ return args
+
+
+class SSHCorpSubprocessVendor(SubprocessVendor):
+ """SSH vendor that uses the 'ssh' executable from SSH Corporation."""
+
+ def _get_vendor_specific_argv(self, username, host, port, subsystem=None,
+ command=None):
+ assert subsystem is not None or command is not None, (
+ 'Must specify a command or subsystem')
+ if subsystem is not None:
+ assert command is None, (
+ 'subsystem and command are mutually exclusive')
+ args = ['ssh', '-x']
+ if port is not None:
+ args.extend(['-p', str(port)])
+ if username is not None:
+ args.extend(['-l', username])
+ if subsystem is not None:
+ args.extend(['-s', subsystem, host])
+ else:
+ args.extend([host] + command)
+ return args
+
+
+def _paramiko_auth(username, password, host, paramiko_transport):
+ # paramiko requires a username, but it might be none if nothing was supplied
+ # use the local username, just in case.
+ # We don't override username, because if we aren't using paramiko,
+ # the username might be specified in ~/.ssh/config and we don't want to
+ # force it to something else
+ # Also, it would mess up the self.relpath() functionality
+ username = username or getpass.getuser()
+
+ if _use_ssh_agent:
+ agent = paramiko.Agent()
+ for key in agent.get_keys():
+ mutter('Trying SSH agent key %s' % paramiko.util.hexify(key.get_fingerprint()))
+ try:
+ paramiko_transport.auth_publickey(username, key)
+ return
+ except paramiko.SSHException, e:
+ pass
+
+ # okay, try finding id_rsa or id_dss? (posix only)
+ if _try_pkey_auth(paramiko_transport, paramiko.RSAKey, username, 'id_rsa'):
+ return
+ if _try_pkey_auth(paramiko_transport, paramiko.DSSKey, username, 'id_dsa'):
+ return
+
+ if password:
+ try:
+ paramiko_transport.auth_password(username, password)
+ return
+ except paramiko.SSHException, e:
+ pass
+
+ # give up and ask for a password
+ password = bzrlib.ui.ui_factory.get_password(
+ prompt='SSH %(user)s@%(host)s password',
+ user=username, host=host)
+ try:
+ paramiko_transport.auth_password(username, password)
+ except paramiko.SSHException, e:
+ raise ConnectionError('Unable to authenticate to SSH host as %s@%s' %
+ (username, host), e)
+
+
+def _try_pkey_auth(paramiko_transport, pkey_class, username, filename):
+ filename = os.path.expanduser('~/.ssh/' + filename)
+ try:
+ key = pkey_class.from_private_key_file(filename)
+ paramiko_transport.auth_publickey(username, key)
+ return True
+ except paramiko.PasswordRequiredException:
+ password = bzrlib.ui.ui_factory.get_password(
+ prompt='SSH %(filename)s password',
+ filename=filename)
+ try:
+ key = pkey_class.from_private_key_file(filename, password)
+ paramiko_transport.auth_publickey(username, key)
+ return True
+ except paramiko.SSHException:
+ mutter('SSH authentication via %s key failed.' % (os.path.basename(filename),))
+ except paramiko.SSHException:
+ mutter('SSH authentication via %s key failed.' % (os.path.basename(filename),))
+ except IOError:
+ pass
+ return False
+
+
+def load_host_keys():
+ """
+ Load system host keys (probably doesn't work on windows) and any
+ "discovered" keys from previous sessions.
+ """
+ global SYSTEM_HOSTKEYS, BZR_HOSTKEYS
+ try:
+ SYSTEM_HOSTKEYS = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
+ except Exception, e:
+ mutter('failed to load system host keys: ' + str(e))
+ bzr_hostkey_path = pathjoin(config_dir(), 'ssh_host_keys')
+ try:
+ BZR_HOSTKEYS = paramiko.util.load_host_keys(bzr_hostkey_path)
+ except Exception, e:
+ mutter('failed to load bzr host keys: ' + str(e))
+ save_host_keys()
+
+
+def save_host_keys():
+ """
+ Save "discovered" host keys in $(config)/ssh_host_keys/.
+ """
+ global SYSTEM_HOSTKEYS, BZR_HOSTKEYS
+ bzr_hostkey_path = pathjoin(config_dir(), 'ssh_host_keys')
+ ensure_config_dir_exists()
+
+ try:
+ f = open(bzr_hostkey_path, 'w')
+ f.write('# SSH host keys collected by bzr\n')
+ for hostname, keys in BZR_HOSTKEYS.iteritems():
+ for keytype, key in keys.iteritems():
+ f.write('%s %s %s\n' % (hostname, keytype, key.get_base64()))
+ f.close()
+ except IOError, e:
+ mutter('failed to save bzr host keys: ' + str(e))
+
+
+def os_specific_subprocess_params():
+ """Get O/S specific subprocess parameters."""
+ if sys.platform == 'win32':
+ # setting the process group and closing fds is not supported on
+ # win32
+ return {}
+ else:
+ # We close fds other than the pipes as the child process does not need
+ # them to be open.
+ #
+ # We also set the child process to ignore SIGINT. Normally the signal
+ # would be sent to every process in the foreground process group, but
+ # this causes it to be seen only by bzr and not by ssh. Python will
+ # generate a KeyboardInterrupt in bzr, and we will then have a chance
+ # to release locks or do other cleanup over ssh before the connection
+ # goes away.
+ # <https://launchpad.net/products/bzr/+bug/5987>
+ #
+ # Running it in a separate process group is not good because then it
+ # can't get non-echoed input of a password or passphrase.
+ # <https://launchpad.net/products/bzr/+bug/40508>
+ return {'preexec_fn': _ignore_sigint,
+ 'close_fds': True,
+ }
+
+class SSHSubprocess(object):
+ """A socket-like object that talks to an ssh subprocess via pipes."""
+ # TODO: this class probably belongs in bzrlib/transport/ssh.py
+
+ def __init__(self, proc):
+ self.proc = proc
+
+ def send(self, data):
+ return os.write(self.proc.stdin.fileno(), data)
+
+ def recv_ready(self):
+ # TODO: jam 20051215 this function is necessary to support the
+ # pipelined() function. In reality, it probably should use
+ # poll() or select() to actually return if there is data
+ # available, otherwise we probably don't get any benefit
+ return True
+
+ def recv(self, count):
+ return os.read(self.proc.stdout.fileno(), count)
+
+ def close(self):
+ self.proc.stdin.close()
+ self.proc.stdout.close()
+ self.proc.wait()
+
+
=== modified file bzrlib/errors.py // last-changed:andrew.bennetts at canonical.co
... m-20060825042009-7cc3e8069b6d5c1c
--- bzrlib/errors.py
+++ bzrlib/errors.py
@@ -1101,3 +1101,12 @@
def __init__(self):
BzrNewError.__init__(self)
+
+
+class UnknownSSH(BzrNewError):
+ """Unrecognised value for BZR_SSH environment variable: %(vendor)s"""
+
+ def __init__(self, vendor):
+ BzrNewError.__init__(self)
+ self.vendor = vendor
+
=== modified file bzrlib/tests/test_sftp_transport.py // last-changed:andrew.be
... nnetts at canonical.com-20060825042009-7cc3e8069b6d5c1c
--- bzrlib/tests/test_sftp_transport.py
+++ bzrlib/tests/test_sftp_transport.py
@@ -271,7 +271,8 @@
self._test_vendor = vendor
def test_connection_paramiko(self):
- self.set_vendor('none')
+ from bzrlib.transport import ssh
+ self.set_vendor(ssh.ParamikoVendor())
t = self.get_transport()
self.assertEqual('foobar\n', t.get('a_file').read())
@@ -317,7 +318,8 @@
def test_bad_connection_paramiko(self):
"""Test that a real connection attempt raises the right error"""
- self.set_vendor('none')
+ from bzrlib.transport import ssh
+ self.set_vendor(ssh.ParamikoVendor())
self.assertRaises(errors.ConnectionError,
bzrlib.transport.get_transport, self.bogus_url)
=== modified file bzrlib/transport/sftp.py
--- bzrlib/transport/sftp.py
+++ bzrlib/transport/sftp.py
@@ -18,11 +18,8 @@
"""Implementation of Transport over SFTP, using paramiko."""
import errno
-import getpass
-import itertools
import os
import random
-import re
import select
import socket
import stat
@@ -33,24 +30,23 @@
import urlparse
import weakref
-from bzrlib.config import config_dir, ensure_config_dir_exists
-from bzrlib.errors import (ConnectionError,
- FileExists,
- TransportNotPossible, NoSuchFile, PathNotChild,
+from bzrlib.errors import (FileExists,
+ NoSuchFile, PathNotChild,
TransportError,
LockError,
PathError,
ParamikoNotPresent,
+ UnknownSSH,
)
from bzrlib.osutils import pathjoin, fancy_rename, getcwd
-from bzrlib.trace import mutter, warning, error
+from bzrlib.trace import mutter, warning
from bzrlib.transport import (
register_urlparse_netloc_protocol,
Server,
split_url,
+ ssh,
Transport,
)
-import bzrlib.ui
import bzrlib.urlutils as urlutils
try:
@@ -63,57 +59,35 @@
CMD_HANDLE, CMD_OPEN)
from paramiko.sftp_attr import SFTPAttributes
from paramiko.sftp_file import SFTPFile
- from paramiko.sftp_client import SFTPClient
register_urlparse_netloc_protocol('sftp')
-def _ignore_sigint():
- # TODO: This should possibly ignore SIGHUP as well, but bzr currently
- # doesn't handle it itself.
- # <https://launchpad.net/products/bzr/+bug/41433/+index>
- import signal
- signal.signal(signal.SIGINT, signal.SIG_IGN)
-
-
-def os_specific_subprocess_params():
- """Get O/S specific subprocess parameters."""
- if sys.platform == 'win32':
- # setting the process group and closing fds is not supported on
- # win32
- return {}
- else:
- # We close fds other than the pipes as the child process does not need
- # them to be open.
- #
- # We also set the child process to ignore SIGINT. Normally the signal
- # would be sent to every process in the foreground process group, but
- # this causes it to be seen only by bzr and not by ssh. Python will
- # generate a KeyboardInterrupt in bzr, and we will then have a chance
- # to release locks or do other cleanup over ssh before the connection
- # goes away.
- # <https://launchpad.net/products/bzr/+bug/5987>
- #
- # Running it in a separate process group is not good because then it
- # can't get non-echoed input of a password or passphrase.
- # <https://launchpad.net/products/bzr/+bug/40508>
- return {'preexec_fn': _ignore_sigint,
- 'close_fds': True,
- }
+# This is a weakref dictionary, so that we can reuse connections
+# that are still active. Long term, it might be nice to have some
+# sort of expiration policy, such as disconnect if inactive for
+# X seconds. But that requires a lot more fanciness.
+_connected_hosts = weakref.WeakValueDictionary()
_paramiko_version = getattr(paramiko, '__version_info__', (0, 0, 0))
# don't use prefetch unless paramiko version >= 1.5.5 (there were bugs earlier)
_default_do_prefetch = (_paramiko_version >= (1, 5, 5))
-# Paramiko 1.5 tries to open a socket.AF_UNIX in order to connect
-# to ssh-agent. That attribute doesn't exist on win32 (it does in cygwin)
-# so we get an AttributeError exception. So we will not try to
-# connect to an agent if we are on win32 and using Paramiko older than 1.6
-_use_ssh_agent = (sys.platform != 'win32' or _paramiko_version >= (1, 6, 0))
-
-
+
+_ssh_vendors = {}
+
+def register_ssh_vendor(name, vendor_class):
+ """Register lazy-loaded SSH vendor class."""
+ _ssh_vendors[name] = vendor_class
+
+register_ssh_vendor('loopback', ssh.LoopbackVendor)
+register_ssh_vendor('paramiko', ssh.ParamikoVendor)
+register_ssh_vendor('none', ssh.ParamikoVendor)
+register_ssh_vendor('openssh', ssh.OpenSSHSubprocessVendor)
+register_ssh_vendor('ssh', ssh.SSHCorpSubprocessVendor)
+
_ssh_vendor = None
def _get_ssh_vendor():
"""Find out what version of SSH is on the system."""
@@ -121,12 +95,14 @@
if _ssh_vendor is not None:
return _ssh_vendor
- _ssh_vendor = 'none'
-
if 'BZR_SSH' in os.environ:
- _ssh_vendor = os.environ['BZR_SSH']
- if _ssh_vendor == 'paramiko':
- _ssh_vendor = 'none'
+ vendor_name = os.environ['BZR_SSH']
+ try:
+ klass = _ssh_vendors[vendor_name]
+ except KeyError:
+ raise UnknownSSH(vendor_name)
+ else:
+ _ssh_vendor = klass()
return _ssh_vendor
try:
@@ -134,7 +110,7 @@
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
- **os_specific_subprocess_params())
+ **ssh.os_specific_subprocess_params())
returncode = p.returncode
stdout, stderr = p.communicate()
except OSError:
@@ -142,95 +118,22 @@
stdout = stderr = ''
if 'OpenSSH' in stderr:
mutter('ssh implementation is OpenSSH')
- _ssh_vendor = 'openssh'
+ _ssh_vendor = ssh.OpenSSHSubprocessVendor()
elif 'SSH Secure Shell' in stderr:
mutter('ssh implementation is SSH Corp.')
- _ssh_vendor = 'ssh'
+ _ssh_vendor = ssh.SSHCorpSubprocessVendor()
- if _ssh_vendor != 'none':
+ if _ssh_vendor is not None:
return _ssh_vendor
# XXX: 20051123 jamesh
# A check for putty's plink or lsh would go here.
mutter('falling back to paramiko implementation')
+ _ssh_vendor = ssh.ParamikoVendor()
return _ssh_vendor
-class SFTPSubprocess:
- """A socket-like object that talks to an ssh subprocess via pipes."""
- def __init__(self, hostname, vendor, port=None, user=None):
- assert vendor in ['openssh', 'ssh']
- if vendor == 'openssh':
- args = ['ssh',
- '-oForwardX11=no', '-oForwardAgent=no',
- '-oClearAllForwardings=yes', '-oProtocol=2',
- '-oNoHostAuthenticationForLocalhost=yes']
- if port is not None:
- args.extend(['-p', str(port)])
- if user is not None:
- args.extend(['-l', user])
- args.extend(['-s', hostname, 'sftp'])
- elif vendor == 'ssh':
- args = ['ssh', '-x']
- if port is not None:
- args.extend(['-p', str(port)])
- if user is not None:
- args.extend(['-l', user])
- args.extend(['-s', 'sftp', hostname])
-
- self.proc = subprocess.Popen(args,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- **os_specific_subprocess_params())
-
- def send(self, data):
- return os.write(self.proc.stdin.fileno(), data)
-
- def recv_ready(self):
- # TODO: jam 20051215 this function is necessary to support the
- # pipelined() function. In reality, it probably should use
- # poll() or select() to actually return if there is data
- # available, otherwise we probably don't get any benefit
- return True
-
- def recv(self, count):
- return os.read(self.proc.stdout.fileno(), count)
-
- def close(self):
- self.proc.stdin.close()
- self.proc.stdout.close()
- self.proc.wait()
-
-
-class LoopbackSFTP(object):
- """Simple wrapper for a socket that pretends to be a paramiko Channel."""
-
- def __init__(self, sock):
- self.__socket = sock
-
- def send(self, data):
- return self.__socket.send(data)
-
- def recv(self, n):
- return self.__socket.recv(n)
-
- def recv_ready(self):
- return True
-
- def close(self):
- self.__socket.close()
-
-
-SYSTEM_HOSTKEYS = {}
-BZR_HOSTKEYS = {}
-
-# This is a weakref dictionary, so that we can reuse connections
-# that are still active. Long term, it might be nice to have some
-# sort of expiration policy, such as disconnect if inactive for
-# X seconds. But that requires a lot more fanciness.
-_connected_hosts = weakref.WeakValueDictionary()
-
def clear_connection_cache():
"""Remove all hosts from the SFTP connection cache.
@@ -239,43 +142,6 @@
_connected_hosts.clear()
-def load_host_keys():
- """
- Load system host keys (probably doesn't work on windows) and any
- "discovered" keys from previous sessions.
- """
- global SYSTEM_HOSTKEYS, BZR_HOSTKEYS
- try:
- SYSTEM_HOSTKEYS = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
- except Exception, e:
- mutter('failed to load system host keys: ' + str(e))
- bzr_hostkey_path = pathjoin(config_dir(), 'ssh_host_keys')
- try:
- BZR_HOSTKEYS = paramiko.util.load_host_keys(bzr_hostkey_path)
- except Exception, e:
- mutter('failed to load bzr host keys: ' + str(e))
- save_host_keys()
-
-
-def save_host_keys():
- """
- Save "discovered" host keys in $(config)/ssh_host_keys/.
- """
- global SYSTEM_HOSTKEYS, BZR_HOSTKEYS
- bzr_hostkey_path = pathjoin(config_dir(), 'ssh_host_keys')
- ensure_config_dir_exists()
-
- try:
- f = open(bzr_hostkey_path, 'w')
- f.write('# SSH host keys collected by bzr\n')
- for hostname, keys in BZR_HOSTKEYS.iteritems():
- for keytype, key in keys.iteritems():
- f.write('%s %s %s\n' % (hostname, keytype, key.get_base64()))
- f.close()
- except IOError, e:
- mutter('failed to save bzr host keys: ' + str(e))
-
-
class SFTPLock(object):
"""This fakes a lock in a remote location."""
__slots__ = ['path', 'lock_path', 'lock_file', 'transport']
@@ -812,156 +678,8 @@
TODO: Raise a more reasonable ConnectionFailed exception
"""
- global _connected_hosts
-
- idx = (self._host, self._port, self._username)
- try:
- self._sftp = _connected_hosts[idx]
- return
- except KeyError:
- pass
-
- vendor = _get_ssh_vendor()
- if vendor == 'loopback':
- sock = socket.socket()
- try:
- sock.connect((self._host, self._port))
- except socket.error, e:
- raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
- % (self._host, self._port, e))
- self._sftp = SFTPClient(LoopbackSFTP(sock))
- elif vendor != 'none':
- try:
- sock = SFTPSubprocess(self._host, vendor, self._port,
- self._username)
- self._sftp = SFTPClient(sock)
- except (EOFError, paramiko.SSHException), e:
- raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
- % (self._host, self._port, e))
- except (OSError, IOError), e:
- # If the machine is fast enough, ssh can actually exit
- # before we try and send it the sftp request, which
- # raises a Broken Pipe
- if e.errno not in (errno.EPIPE,):
- raise
- raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
- % (self._host, self._port, e))
- else:
- self._paramiko_connect()
-
- _connected_hosts[idx] = self._sftp
-
- def _paramiko_connect(self):
- global SYSTEM_HOSTKEYS, BZR_HOSTKEYS
-
- load_host_keys()
-
- try:
- t = paramiko.Transport((self._host, self._port or 22))
- t.set_log_channel('bzr.paramiko')
- t.start_client()
- except (paramiko.SSHException, socket.error), e:
- raise ConnectionError('Unable to reach SSH host %s:%s: %s'
- % (self._host, self._port, e))
-
- server_key = t.get_remote_server_key()
- server_key_hex = paramiko.util.hexify(server_key.get_fingerprint())
- keytype = server_key.get_name()
- if SYSTEM_HOSTKEYS.has_key(self._host) and SYSTEM_HOSTKEYS[self._host].has_key(keytype):
- our_server_key = SYSTEM_HOSTKEYS[self._host][keytype]
- our_server_key_hex = paramiko.util.hexify(our_server_key.get_fingerprint())
- elif BZR_HOSTKEYS.has_key(self._host) and BZR_HOSTKEYS[self._host].has_key(keytype):
- our_server_key = BZR_HOSTKEYS[self._host][keytype]
- our_server_key_hex = paramiko.util.hexify(our_server_key.get_fingerprint())
- else:
- warning('Adding %s host key for %s: %s' % (keytype, self._host, server_key_hex))
- if not BZR_HOSTKEYS.has_key(self._host):
- BZR_HOSTKEYS[self._host] = {}
- BZR_HOSTKEYS[self._host][keytype] = server_key
- our_server_key = server_key
- our_server_key_hex = paramiko.util.hexify(our_server_key.get_fingerprint())
- save_host_keys()
- if server_key != our_server_key:
- filename1 = os.path.expanduser('~/.ssh/known_hosts')
- filename2 = pathjoin(config_dir(), 'ssh_host_keys')
- raise TransportError('Host keys for %s do not match! %s != %s' % \
- (self._host, our_server_key_hex, server_key_hex),
- ['Try editing %s or %s' % (filename1, filename2)])
-
- self._sftp_auth(t)
-
- try:
- self._sftp = t.open_sftp_client()
- except paramiko.SSHException, e:
- raise ConnectionError('Unable to start sftp client %s:%d' %
- (self._host, self._port), e)
-
- def _sftp_auth(self, transport):
- # paramiko requires a username, but it might be none if nothing was supplied
- # use the local username, just in case.
- # We don't override self._username, because if we aren't using paramiko,
- # the username might be specified in ~/.ssh/config and we don't want to
- # force it to something else
- # Also, it would mess up the self.relpath() functionality
- username = self._username or getpass.getuser()
-
- if _use_ssh_agent:
- agent = paramiko.Agent()
- for key in agent.get_keys():
- mutter('Trying SSH agent key %s' % paramiko.util.hexify(key.get_fingerprint()))
- try:
- transport.auth_publickey(username, key)
- return
- except paramiko.SSHException, e:
- pass
-
- # okay, try finding id_rsa or id_dss? (posix only)
- if self._try_pkey_auth(transport, paramiko.RSAKey, username, 'id_rsa'):
- return
- if self._try_pkey_auth(transport, paramiko.DSSKey, username, 'id_dsa'):
- return
-
- if self._password:
- try:
- transport.auth_password(username, self._password)
- return
- except paramiko.SSHException, e:
- pass
-
- # FIXME: Don't keep a password held in memory if you can help it
- #self._password = None
-
- # give up and ask for a password
- password = bzrlib.ui.ui_factory.get_password(
- prompt='SSH %(user)s@%(host)s password',
- user=username, host=self._host)
- try:
- transport.auth_password(username, password)
- except paramiko.SSHException, e:
- raise ConnectionError('Unable to authenticate to SSH host as %s@%s' %
- (username, self._host), e)
-
- def _try_pkey_auth(self, transport, pkey_class, username, filename):
- filename = os.path.expanduser('~/.ssh/' + filename)
- try:
- key = pkey_class.from_private_key_file(filename)
- transport.auth_publickey(username, key)
- return True
- except paramiko.PasswordRequiredException:
- password = bzrlib.ui.ui_factory.get_password(
- prompt='SSH %(filename)s password',
- filename=filename)
- try:
- key = pkey_class.from_private_key_file(filename, password)
- transport.auth_publickey(username, key)
- return True
- except paramiko.SSHException:
- mutter('SSH authentication via %s key failed.' % (os.path.basename(filename),))
- except paramiko.SSHException:
- mutter('SSH authentication via %s key failed.' % (os.path.basename(filename),))
- except IOError:
- pass
- return False
+ self._sftp = _sftp_connect(self._host, self._port, self._username,
+ self._password)
def _sftp_open_exclusive(self, abspath, mode=None):
"""Open a remote path exclusively.
@@ -996,7 +714,6 @@
# ------------- server test implementation --------------
-import socket
import threading
from bzrlib.tests.stub_sftp import StubServer, StubSFTPServer
@@ -1149,7 +866,7 @@
self._server_homedir = None
self._listener = None
self._root = None
- self._vendor = 'none'
+ self._vendor = ssh.ParamikoVendor()
# sftp server logs
self.logs = []
self.add_latency = 0
@@ -1236,7 +953,7 @@
def __init__(self):
super(SFTPServerWithoutSSH, self).__init__()
- self._vendor = 'loopback'
+ self._vendor = ssh.LoopbackVendor()
def _run_server(self, sock):
class FakeChannel(object):
@@ -1294,6 +1011,31 @@
super(SFTPSiblingAbsoluteServer, self).setUp()
+def _sftp_connect(host, port, username, password):
+ """Connect to the remote sftp server.
+
+ :raises: a TransportError 'could not connect'.
+
+ :returns: an paramiko.sftp_client.SFTPClient
+
+ TODO: Raise a more reasonable ConnectionFailed exception
+ """
+ idx = (host, port, username)
+ try:
+ return _connected_hosts[idx]
+ except KeyError:
+ pass
+
+ sftp = _sftp_connect_uncached(host, port, username, password)
+ _connected_hosts[idx] = sftp
+ return sftp
+
+def _sftp_connect_uncached(host, port, username, password):
+ vendor = _get_ssh_vendor()
+ sftp = vendor.connect_sftp(username, password, host, port)
+ return sftp
+
+
def get_test_permutations():
"""Return the permutations to be used in testing."""
return [(SFTPTransport, SFTPAbsoluteServer),
# revision id: andrew.bennetts at canonical.com-20060825050539-08009a757f120d12
# sha1: 04eaf8594b0c98412e6b6f32542d4627eceb03e6
# inventory sha1: b6df4fc80ebfc2f6a30532cf3cbc9a13b3816477
# parent ids:
# andrew.bennetts at canonical.com-20060825042009-7cc3e8069b6d5c1c
# base id: andrew.bennetts at canonical.com-20060823035252-470ec76fa9d07b15
# properties:
# branch-nick: sftp refactoring 2
# message:
# Make _get_ssh_vendor return the vendor object, rather than just a string.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Fri 2006-08-25 14:20:09.352999926 +1000
=== modified file bzrlib/errors.py // encoding:base64
LS0tIGJ6cmxpYi9lcnJvcnMucHkKKysrIGJ6cmxpYi9lcnJvcnMucHkKQEAgLTExMDEsMyArMTEw
MSwxMiBAQAogCiAgICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgICBCenJOZXdFcnJvci5f
X2luaXRfXyhzZWxmKSAgICAKKworCitjbGFzcyBVbmtub3duU1NIKEJ6ck5ld0Vycm9yKToKKyAg
ICAiIiJVbnJlY29nbmlzZWQgdmFsdWUgZm9yIEJaUl9TU0ggZW52aXJvbm1lbnQgdmFyaWFibGU6
ICUodmVuZG9yKXMiIiIKKworICAgIGRlZiBfX2luaXRfXyhzZWxmLCB2ZW5kb3IpOgorICAgICAg
ICBCenJOZXdFcnJvci5fX2luaXRfXyhzZWxmKQorICAgICAgICBzZWxmLnZlbmRvciA9IHZlbmRv
cgorCgo=
=== modified file bzrlib/tests/test_sftp_transport.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3NmdHBfdHJhbnNwb3J0LnB5CisrKyBienJsaWIvdGVzdHMv
dGVzdF9zZnRwX3RyYW5zcG9ydC5weQpAQCAtMjcxLDcgKzI3MSw4IEBACiAgICAgICAgIHNlbGYu
X3Rlc3RfdmVuZG9yID0gdmVuZG9yCiAKICAgICBkZWYgdGVzdF9jb25uZWN0aW9uX3BhcmFtaWtv
KHNlbGYpOgotICAgICAgICBzZWxmLnNldF92ZW5kb3IoJ25vbmUnKQorICAgICAgICBmcm9tIGJ6
cmxpYi50cmFuc3BvcnQgaW1wb3J0IHNzaAorICAgICAgICBzZWxmLnNldF92ZW5kb3Ioc3NoLlBh
cmFtaWtvVmVuZG9yKCkpCiAgICAgICAgIHQgPSBzZWxmLmdldF90cmFuc3BvcnQoKQogICAgICAg
ICBzZWxmLmFzc2VydEVxdWFsKCdmb29iYXJcbicsIHQuZ2V0KCdhX2ZpbGUnKS5yZWFkKCkpCiAK
QEAgLTMxNyw3ICszMTgsOCBAQAogCiAgICAgZGVmIHRlc3RfYmFkX2Nvbm5lY3Rpb25fcGFyYW1p
a28oc2VsZik6CiAgICAgICAgICIiIlRlc3QgdGhhdCBhIHJlYWwgY29ubmVjdGlvbiBhdHRlbXB0
IHJhaXNlcyB0aGUgcmlnaHQgZXJyb3IiIiIKLSAgICAgICAgc2VsZi5zZXRfdmVuZG9yKCdub25l
JykKKyAgICAgICAgZnJvbSBienJsaWIudHJhbnNwb3J0IGltcG9ydCBzc2gKKyAgICAgICAgc2Vs
Zi5zZXRfdmVuZG9yKHNzaC5QYXJhbWlrb1ZlbmRvcigpKQogICAgICAgICBzZWxmLmFzc2VydFJh
aXNlcyhlcnJvcnMuQ29ubmVjdGlvbkVycm9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICBi
enJsaWIudHJhbnNwb3J0LmdldF90cmFuc3BvcnQsIHNlbGYuYm9ndXNfdXJsKQogCgo=
=== modified file bzrlib/transport/sftp.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc2Z0cC5weQorKysgYnpybGliL3RyYW5zcG9ydC9zZnRwLnB5
CkBAIC0zNSw2ICszNSw3IEBACiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2NrRXJyb3Is
IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUGF0aEVycm9yLAogICAgICAgICAgICAgICAg
ICAgICAgICAgICAgUGFyYW1pa29Ob3RQcmVzZW50LAorICAgICAgICAgICAgICAgICAgICAgICAg
ICAgVW5rbm93blNTSCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIGZyb20gYnpybGli
Lm9zdXRpbHMgaW1wb3J0IHBhdGhqb2luLCBmYW5jeV9yZW5hbWUsIGdldGN3ZAogZnJvbSBienJs
aWIudHJhY2UgaW1wb3J0IG11dHRlciwgd2FybmluZwpAQCAtNjcsNiArNjgsMTggQEAKIF9kZWZh
dWx0X2RvX3ByZWZldGNoID0gKF9wYXJhbWlrb192ZXJzaW9uID49ICgxLCA1LCA1KSkKIAogCitf
c3NoX3ZlbmRvcnMgPSB7fQorCitkZWYgcmVnaXN0ZXJfc3NoX3ZlbmRvcihuYW1lLCB2ZW5kb3Jf
Y2xhc3MpOgorICAgICIiIlJlZ2lzdGVyIGxhenktbG9hZGVkIFNTSCB2ZW5kb3IgY2xhc3MuIiIi
IAorICAgIF9zc2hfdmVuZG9yc1tuYW1lXSA9IHZlbmRvcl9jbGFzcworCityZWdpc3Rlcl9zc2hf
dmVuZG9yKCdsb29wYmFjaycsIHNzaC5Mb29wYmFja1ZlbmRvcikKK3JlZ2lzdGVyX3NzaF92ZW5k
b3IoJ3BhcmFtaWtvJywgc3NoLlBhcmFtaWtvVmVuZG9yKQorcmVnaXN0ZXJfc3NoX3ZlbmRvcign
bm9uZScsIHNzaC5QYXJhbWlrb1ZlbmRvcikKK3JlZ2lzdGVyX3NzaF92ZW5kb3IoJ29wZW5zc2gn
LCBzc2guT3BlblNTSFN1YnByb2Nlc3NWZW5kb3IpCityZWdpc3Rlcl9zc2hfdmVuZG9yKCdzc2gn
LCBzc2guU1NIQ29ycFN1YnByb2Nlc3NWZW5kb3IpCisgICAgCiBfc3NoX3ZlbmRvciA9IE5vbmUK
IGRlZiBfZ2V0X3NzaF92ZW5kb3IoKToKICAgICAiIiJGaW5kIG91dCB3aGF0IHZlcnNpb24gb2Yg
U1NIIGlzIG9uIHRoZSBzeXN0ZW0uIiIiCkBAIC03NCwxMiArODcsMTQgQEAKICAgICBpZiBfc3No
X3ZlbmRvciBpcyBub3QgTm9uZToKICAgICAgICAgcmV0dXJuIF9zc2hfdmVuZG9yCiAKLSAgICBf
c3NoX3ZlbmRvciA9ICdub25lJwotCiAgICAgaWYgJ0JaUl9TU0gnIGluIG9zLmVudmlyb246Ci0g
ICAgICAgIF9zc2hfdmVuZG9yID0gb3MuZW52aXJvblsnQlpSX1NTSCddCi0gICAgICAgIGlmIF9z
c2hfdmVuZG9yID09ICdwYXJhbWlrbyc6Ci0gICAgICAgICAgICBfc3NoX3ZlbmRvciA9ICdub25l
JworICAgICAgICB2ZW5kb3JfbmFtZSA9IG9zLmVudmlyb25bJ0JaUl9TU0gnXQorICAgICAgICB0
cnk6CisgICAgICAgICAgICBrbGFzcyA9IF9zc2hfdmVuZG9yc1t2ZW5kb3JfbmFtZV0KKyAgICAg
ICAgZXhjZXB0IEtleUVycm9yOgorICAgICAgICAgICAgcmFpc2UgVW5rbm93blNTSCh2ZW5kb3Jf
bmFtZSkKKyAgICAgICAgZWxzZToKKyAgICAgICAgICAgIF9zc2hfdmVuZG9yID0ga2xhc3MoKQog
ICAgICAgICByZXR1cm4gX3NzaF92ZW5kb3IKIAogICAgIHRyeToKQEAgLTk1LDE4ICsxMTAsMTkg
QEAKICAgICAgICAgc3Rkb3V0ID0gc3RkZXJyID0gJycKICAgICBpZiAnT3BlblNTSCcgaW4gc3Rk
ZXJyOgogICAgICAgICBtdXR0ZXIoJ3NzaCBpbXBsZW1lbnRhdGlvbiBpcyBPcGVuU1NIJykKLSAg
ICAgICAgX3NzaF92ZW5kb3IgPSAnb3BlbnNzaCcKKyAgICAgICAgX3NzaF92ZW5kb3IgPSBzc2gu
T3BlblNTSFN1YnByb2Nlc3NWZW5kb3IoKQogICAgIGVsaWYgJ1NTSCBTZWN1cmUgU2hlbGwnIGlu
IHN0ZGVycjoKICAgICAgICAgbXV0dGVyKCdzc2ggaW1wbGVtZW50YXRpb24gaXMgU1NIIENvcnAu
JykKLSAgICAgICAgX3NzaF92ZW5kb3IgPSAnc3NoJworICAgICAgICBfc3NoX3ZlbmRvciA9IHNz
aC5TU0hDb3JwU3VicHJvY2Vzc1ZlbmRvcigpCiAKLSAgICBpZiBfc3NoX3ZlbmRvciAhPSAnbm9u
ZSc6CisgICAgaWYgX3NzaF92ZW5kb3IgaXMgbm90IE5vbmU6CiAgICAgICAgIHJldHVybiBfc3No
X3ZlbmRvcgogCiAgICAgIyBYWFg6IDIwMDUxMTIzIGphbWVzaAogICAgICMgQSBjaGVjayBmb3Ig
cHV0dHkncyBwbGluayBvciBsc2ggd291bGQgZ28gaGVyZS4KIAogICAgIG11dHRlcignZmFsbGlu
ZyBiYWNrIHRvIHBhcmFtaWtvIGltcGxlbWVudGF0aW9uJykKKyAgICBfc3NoX3ZlbmRvciA9IHNz
aC5QYXJhbWlrb1ZlbmRvcigpCiAgICAgcmV0dXJuIF9zc2hfdmVuZG9yCiAKIApAQCAtODQyLDcg
Kzg1OCw3IEBACiAgICAgICAgIHNlbGYuX3NlcnZlcl9ob21lZGlyID0gTm9uZQogICAgICAgICBz
ZWxmLl9saXN0ZW5lciA9IE5vbmUKICAgICAgICAgc2VsZi5fcm9vdCA9IE5vbmUKLSAgICAgICAg
c2VsZi5fdmVuZG9yID0gJ25vbmUnCisgICAgICAgIHNlbGYuX3ZlbmRvciA9IHNzaC5QYXJhbWlr
b1ZlbmRvcigpCiAgICAgICAgICMgc2Z0cCBzZXJ2ZXIgbG9ncwogICAgICAgICBzZWxmLmxvZ3Mg
PSBbXQogICAgICAgICBzZWxmLmFkZF9sYXRlbmN5ID0gMApAQCAtOTI5LDcgKzk0NSw3IEBACiAK
ICAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgIHN1cGVyKFNGVFBTZXJ2ZXJXaXRob3V0
U1NILCBzZWxmKS5fX2luaXRfXygpCi0gICAgICAgIHNlbGYuX3ZlbmRvciA9ICdsb29wYmFjaycK
KyAgICAgICAgc2VsZi5fdmVuZG9yID0gc3NoLkxvb3BiYWNrVmVuZG9yKCkKIAogICAgIGRlZiBf
cnVuX3NlcnZlcihzZWxmLCBzb2NrKToKICAgICAgICAgY2xhc3MgRmFrZUNoYW5uZWwob2JqZWN0
KToKQEAgLTEwMDcsMTkgKzEwMjMsOCBAQAogICAgIHJldHVybiBzZnRwCiAKIGRlZiBfc2Z0cF9j
b25uZWN0X3VuY2FjaGVkKGhvc3QsIHBvcnQsIHVzZXJuYW1lLCBwYXNzd29yZCk6Ci0gICAgIyBU
T0RPOiB1c2UgYSByZWdpc3RyYXRpb24gZGljdGlvbmFyeSByYXRoZXIgdGhhbiBhIGJpZyBpZi9l
bGlmIGNoYWluLgogICAgIHZlbmRvciA9IF9nZXRfc3NoX3ZlbmRvcigpCi0gICAgaWYgdmVuZG9y
ID09ICdsb29wYmFjayc6Ci0gICAgICAgIHZlbmRvckltcGwgPSBzc2guTG9vcGJhY2tWZW5kb3Io
KQotICAgIGVsaWYgdmVuZG9yID09ICdub25lJzoKLSAgICAgICAgdmVuZG9ySW1wbCA9IHNzaC5Q
YXJhbWlrb1ZlbmRvcigpCi0gICAgZWxpZiB2ZW5kb3IgPT0gJ29wZW5zc2gnOgotICAgICAgICB2
ZW5kb3JJbXBsID0gc3NoLk9wZW5TU0hTdWJwcm9jZXNzVmVuZG9yKCkKLSAgICBlbGlmIHZlbmRv
ciA9PSAnc3NoJzoKLSAgICAgICAgdmVuZG9ySW1wbCA9IHNzaC5TU0hDb3JwU3VicHJvY2Vzc1Zl
bmRvcigpCi0gICAgZWxzZToKLSAgICAgICAgYXNzZXJ0IEZhbHNlLCAiVW5rbm93biBTU0ggdmVu
ZG9yOiAlciIgJSAodmVuZG9yLCkKLSAgICBzZnRwID0gdmVuZG9ySW1wbC5jb25uZWN0X3NmdHAo
dXNlcm5hbWUsIHBhc3N3b3JkLCBob3N0LCBwb3J0KQorICAgIHNmdHAgPSB2ZW5kb3IuY29ubmVj
dF9zZnRwKHVzZXJuYW1lLCBwYXNzd29yZCwgaG9zdCwgcG9ydCkKICAgICByZXR1cm4gc2Z0cAog
CiAKCg==
# revision id: andrew.bennetts at canonical.com-20060825042009-7cc3e8069b6d5c1c
# sha1: 9580be882294d6c055625a3bb32a27c414b4d20d
# inventory sha1: 976e630ded7c14534b7d95fe5f0d8a509ec31199
# parent ids:
# andrew.bennetts at canonical.com-20060824091407-af213b6a30b6066a
# properties:
# branch-nick: sftp refactoring 2
# message:
# Move more generic SSH code from sftp.py into ssh.py, and start unifying the connection establishing logic.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Thu 2006-08-24 19:14:07.552999973 +1000
=== modified file bzrlib/transport/sftp.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc2Z0cC5weQorKysgYnpybGliL3RyYW5zcG9ydC9zZnRwLnB5
CkBAIC0yOSw4ICsyOSw3IEBACiBpbXBvcnQgdXJsbGliCiBpbXBvcnQgdXJscGFyc2UKIAotZnJv
bSBienJsaWIuZXJyb3JzIGltcG9ydCAoQ29ubmVjdGlvbkVycm9yLAotICAgICAgICAgICAgICAg
ICAgICAgICAgICAgRmlsZUV4aXN0cywgCitmcm9tIGJ6cmxpYi5lcnJvcnMgaW1wb3J0IChGaWxl
RXhpc3RzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5vU3VjaEZpbGUsIFBhdGhOb3RD
aGlsZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYW5zcG9ydEVycm9yLAogICAgICAg
ICAgICAgICAgICAgICAgICAgICAgTG9ja0Vycm9yLCAKQEAgLTQ2LDcgKzQ1LDYgQEAKICAgICBz
c2gsCiAgICAgVHJhbnNwb3J0LAogICAgICkKLWltcG9ydCBienJsaWIudWkKIGltcG9ydCBienJs
aWIudXJsdXRpbHMgYXMgdXJsdXRpbHMKIAogdHJ5OgpAQCAtNTksNDYgKzU3LDExIEBACiAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgQ01EX0hBTkRMRSwgQ01EX09QRU4pCiAgICAgZnJv
bSBwYXJhbWlrby5zZnRwX2F0dHIgaW1wb3J0IFNGVFBBdHRyaWJ1dGVzCiAgICAgZnJvbSBwYXJh
bWlrby5zZnRwX2ZpbGUgaW1wb3J0IFNGVFBGaWxlCi0gICAgZnJvbSBwYXJhbWlrby5zZnRwX2Ns
aWVudCBpbXBvcnQgU0ZUUENsaWVudAogCiAKIHJlZ2lzdGVyX3VybHBhcnNlX25ldGxvY19wcm90
b2NvbCgnc2Z0cCcpCiAKIAotZGVmIF9pZ25vcmVfc2lnaW50KCk6Ci0gICAgIyBUT0RPOiBUaGlz
IHNob3VsZCBwb3NzaWJseSBpZ25vcmUgU0lHSFVQIGFzIHdlbGwsIGJ1dCBienIgY3VycmVudGx5
Ci0gICAgIyBkb2Vzbid0IGhhbmRsZSBpdCBpdHNlbGYuCi0gICAgIyA8aHR0cHM6Ly9sYXVuY2hw
YWQubmV0L3Byb2R1Y3RzL2J6ci8rYnVnLzQxNDMzLytpbmRleD4KLSAgICBpbXBvcnQgc2lnbmFs
Ci0gICAgc2lnbmFsLnNpZ25hbChzaWduYWwuU0lHSU5ULCBzaWduYWwuU0lHX0lHTikKLSAgICAK
LQotZGVmIG9zX3NwZWNpZmljX3N1YnByb2Nlc3NfcGFyYW1zKCk6Ci0gICAgIiIiR2V0IE8vUyBz
cGVjaWZpYyBzdWJwcm9jZXNzIHBhcmFtZXRlcnMuIiIiCi0gICAgaWYgc3lzLnBsYXRmb3JtID09
ICd3aW4zMic6Ci0gICAgICAgICMgc2V0dGluZyB0aGUgcHJvY2VzcyBncm91cCBhbmQgY2xvc2lu
ZyBmZHMgaXMgbm90IHN1cHBvcnRlZCBvbiAKLSAgICAgICAgIyB3aW4zMgotICAgICAgICByZXR1
cm4ge30KLSAgICBlbHNlOgotICAgICAgICAjIFdlIGNsb3NlIGZkcyBvdGhlciB0aGFuIHRoZSBw
aXBlcyBhcyB0aGUgY2hpbGQgcHJvY2VzcyBkb2VzIG5vdCBuZWVkIAotICAgICAgICAjIHRoZW0g
dG8gYmUgb3Blbi4KLSAgICAgICAgIwotICAgICAgICAjIFdlIGFsc28gc2V0IHRoZSBjaGlsZCBw
cm9jZXNzIHRvIGlnbm9yZSBTSUdJTlQuICBOb3JtYWxseSB0aGUgc2lnbmFsCi0gICAgICAgICMg
d291bGQgYmUgc2VudCB0byBldmVyeSBwcm9jZXNzIGluIHRoZSBmb3JlZ3JvdW5kIHByb2Nlc3Mg
Z3JvdXAsIGJ1dAotICAgICAgICAjIHRoaXMgY2F1c2VzIGl0IHRvIGJlIHNlZW4gb25seSBieSBi
enIgYW5kIG5vdCBieSBzc2guICBQeXRob24gd2lsbAotICAgICAgICAjIGdlbmVyYXRlIGEgS2V5
Ym9hcmRJbnRlcnJ1cHQgaW4gYnpyLCBhbmQgd2Ugd2lsbCB0aGVuIGhhdmUgYSBjaGFuY2UKLSAg
ICAgICAgIyB0byByZWxlYXNlIGxvY2tzIG9yIGRvIG90aGVyIGNsZWFudXAgb3ZlciBzc2ggYmVm
b3JlIHRoZSBjb25uZWN0aW9uCi0gICAgICAgICMgZ29lcyBhd2F5LiAgCi0gICAgICAgICMgPGh0
dHBzOi8vbGF1bmNocGFkLm5ldC9wcm9kdWN0cy9ienIvK2J1Zy81OTg3PgotICAgICAgICAjCi0g
ICAgICAgICMgUnVubmluZyBpdCBpbiBhIHNlcGFyYXRlIHByb2Nlc3MgZ3JvdXAgaXMgbm90IGdv
b2QgYmVjYXVzZSB0aGVuIGl0Ci0gICAgICAgICMgY2FuJ3QgZ2V0IG5vbi1lY2hvZWQgaW5wdXQg
b2YgYSBwYXNzd29yZCBvciBwYXNzcGhyYXNlLgotICAgICAgICAjIDxodHRwczovL2xhdW5jaHBh
ZC5uZXQvcHJvZHVjdHMvYnpyLytidWcvNDA1MDg+Ci0gICAgICAgIHJldHVybiB7J3ByZWV4ZWNf
Zm4nOiBfaWdub3JlX3NpZ2ludCwKLSAgICAgICAgICAgICAgICAnY2xvc2VfZmRzJzogVHJ1ZSwK
LSAgICAgICAgICAgICAgICB9Ci0KLQogX3BhcmFtaWtvX3ZlcnNpb24gPSBnZXRhdHRyKHBhcmFt
aWtvLCAnX192ZXJzaW9uX2luZm9fXycsICgwLCAwLCAwKSkKICMgZG9uJ3QgdXNlIHByZWZldGNo
IHVubGVzcyBwYXJhbWlrbyB2ZXJzaW9uID49IDEuNS41ICh0aGVyZSB3ZXJlIGJ1Z3MgZWFybGll
cikKIF9kZWZhdWx0X2RvX3ByZWZldGNoID0gKF9wYXJhbWlrb192ZXJzaW9uID49ICgxLCA1LCA1
KSkKQEAgLTEyNCw3ICs4Nyw3IEBACiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZGlu
PXN1YnByb2Nlc3MuUElQRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Rkb3V0PXN1
YnByb2Nlc3MuUElQRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RkZXJyPXN1YnBy
b2Nlc3MuUElQRSwKLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKipvc19zcGVjaWZpY19z
dWJwcm9jZXNzX3BhcmFtcygpKQorICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKnNzaC5v
c19zcGVjaWZpY19zdWJwcm9jZXNzX3BhcmFtcygpKQogICAgICAgICByZXR1cm5jb2RlID0gcC5y
ZXR1cm5jb2RlCiAgICAgICAgIHN0ZG91dCwgc3RkZXJyID0gcC5jb21tdW5pY2F0ZSgpCiAgICAg
ZXhjZXB0IE9TRXJyb3I6CkBAIC0xNDcsNTIgKzExMCw2IEBACiAgICAgcmV0dXJuIF9zc2hfdmVu
ZG9yCiAKIAotY2xhc3MgU0ZUUFN1YnByb2Nlc3M6Ci0gICAgIiIiQSBzb2NrZXQtbGlrZSBvYmpl
Y3QgdGhhdCB0YWxrcyB0byBhbiBzc2ggc3VicHJvY2VzcyB2aWEgcGlwZXMuIiIiCi0gICAgZGVm
IF9faW5pdF9fKHNlbGYsIGhvc3RuYW1lLCB2ZW5kb3IsIHBvcnQ9Tm9uZSwgdXNlcj1Ob25lKToK
LSAgICAgICAgYXNzZXJ0IHZlbmRvciBpbiBbJ29wZW5zc2gnLCAnc3NoJ10KLSAgICAgICAgaWYg
dmVuZG9yID09ICdvcGVuc3NoJzoKLSAgICAgICAgICAgIGFyZ3MgPSBbJ3NzaCcsCi0gICAgICAg
ICAgICAgICAgICAgICctb0ZvcndhcmRYMTE9bm8nLCAnLW9Gb3J3YXJkQWdlbnQ9bm8nLAotICAg
ICAgICAgICAgICAgICAgICAnLW9DbGVhckFsbEZvcndhcmRpbmdzPXllcycsICctb1Byb3RvY29s
PTInLAotICAgICAgICAgICAgICAgICAgICAnLW9Ob0hvc3RBdXRoZW50aWNhdGlvbkZvckxvY2Fs
aG9zdD15ZXMnXQotICAgICAgICAgICAgaWYgcG9ydCBpcyBub3QgTm9uZToKLSAgICAgICAgICAg
ICAgICBhcmdzLmV4dGVuZChbJy1wJywgc3RyKHBvcnQpXSkKLSAgICAgICAgICAgIGlmIHVzZXIg
aXMgbm90IE5vbmU6Ci0gICAgICAgICAgICAgICAgYXJncy5leHRlbmQoWyctbCcsIHVzZXJdKQot
ICAgICAgICAgICAgYXJncy5leHRlbmQoWyctcycsIGhvc3RuYW1lLCAnc2Z0cCddKQotICAgICAg
ICBlbGlmIHZlbmRvciA9PSAnc3NoJzoKLSAgICAgICAgICAgIGFyZ3MgPSBbJ3NzaCcsICcteCdd
Ci0gICAgICAgICAgICBpZiBwb3J0IGlzIG5vdCBOb25lOgotICAgICAgICAgICAgICAgIGFyZ3Mu
ZXh0ZW5kKFsnLXAnLCBzdHIocG9ydCldKQotICAgICAgICAgICAgaWYgdXNlciBpcyBub3QgTm9u
ZToKLSAgICAgICAgICAgICAgICBhcmdzLmV4dGVuZChbJy1sJywgdXNlcl0pCi0gICAgICAgICAg
ICBhcmdzLmV4dGVuZChbJy1zJywgJ3NmdHAnLCBob3N0bmFtZV0pCi0KLSAgICAgICAgc2VsZi5w
cm9jID0gc3VicHJvY2Vzcy5Qb3BlbihhcmdzLAotICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIHN0ZGluPXN1YnByb2Nlc3MuUElQRSwKLSAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICBzdGRvdXQ9c3VicHJvY2Vzcy5QSVBFLAotICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICoqb3Nfc3BlY2lmaWNfc3VicHJvY2Vzc19wYXJhbXMoKSkKLQot
ICAgIGRlZiBzZW5kKHNlbGYsIGRhdGEpOgotICAgICAgICByZXR1cm4gb3Mud3JpdGUoc2VsZi5w
cm9jLnN0ZGluLmZpbGVubygpLCBkYXRhKQotCi0gICAgZGVmIHJlY3ZfcmVhZHkoc2VsZik6Ci0g
ICAgICAgICMgVE9ETzogamFtIDIwMDUxMjE1IHRoaXMgZnVuY3Rpb24gaXMgbmVjZXNzYXJ5IHRv
IHN1cHBvcnQgdGhlCi0gICAgICAgICMgcGlwZWxpbmVkKCkgZnVuY3Rpb24uIEluIHJlYWxpdHks
IGl0IHByb2JhYmx5IHNob3VsZCB1c2UKLSAgICAgICAgIyBwb2xsKCkgb3Igc2VsZWN0KCkgdG8g
YWN0dWFsbHkgcmV0dXJuIGlmIHRoZXJlIGlzIGRhdGEKLSAgICAgICAgIyBhdmFpbGFibGUsIG90
aGVyd2lzZSB3ZSBwcm9iYWJseSBkb24ndCBnZXQgYW55IGJlbmVmaXQKLSAgICAgICAgcmV0dXJu
IFRydWUKLQotICAgIGRlZiByZWN2KHNlbGYsIGNvdW50KToKLSAgICAgICAgcmV0dXJuIG9zLnJl
YWQoc2VsZi5wcm9jLnN0ZG91dC5maWxlbm8oKSwgY291bnQpCi0KLSAgICBkZWYgY2xvc2Uoc2Vs
Zik6Ci0gICAgICAgIHNlbGYucHJvYy5zdGRpbi5jbG9zZSgpCi0gICAgICAgIHNlbGYucHJvYy5z
dGRvdXQuY2xvc2UoKQotICAgICAgICBzZWxmLnByb2Mud2FpdCgpCi0KLQogZGVmIGNsZWFyX2Nv
bm5lY3Rpb25fY2FjaGUoKToKICAgICAiIiJSZW1vdmUgYWxsIGhvc3RzIGZyb20gdGhlIFNGVFAg
Y29ubmVjdGlvbiBjYWNoZS4KIApAQCAtMTA3NSw3ICs5OTIsNyBAQAogCiAgICAgOnJhaXNlczog
YSBUcmFuc3BvcnRFcnJvciAnY291bGQgbm90IGNvbm5lY3QnLgogCi0gICAgOnJldHVybnM6IGFu
IFNGVFBDbGllbnQKKyAgICA6cmV0dXJuczogYW4gcGFyYW1pa28uc2Z0cF9jbGllbnQuU0ZUUENs
aWVudAogCiAgICAgVE9ETzogUmFpc2UgYSBtb3JlIHJlYXNvbmFibGUgQ29ubmVjdGlvbkZhaWxl
ZCBleGNlcHRpb24KICAgICAiIiIKQEAgLTEwOTAsMzMgKzEwMDcsMjAgQEAKICAgICByZXR1cm4g
c2Z0cAogCiBkZWYgX3NmdHBfY29ubmVjdF91bmNhY2hlZChob3N0LCBwb3J0LCB1c2VybmFtZSwg
cGFzc3dvcmQpOgorICAgICMgVE9ETzogdXNlIGEgcmVnaXN0cmF0aW9uIGRpY3Rpb25hcnkgcmF0
aGVyIHRoYW4gYSBiaWcgaWYvZWxpZiBjaGFpbi4KICAgICB2ZW5kb3IgPSBfZ2V0X3NzaF92ZW5k
b3IoKQogICAgIGlmIHZlbmRvciA9PSAnbG9vcGJhY2snOgotICAgICAgICBzZnRwID0gc3NoLkxv
b3BiYWNrVmVuZG9yKCkuY29ubmVjdF9zZnRwKHVzZXJuYW1lLCBwYXNzd29yZCwgaG9zdCwgcG9y
dCkKKyAgICAgICAgdmVuZG9ySW1wbCA9IHNzaC5Mb29wYmFja1ZlbmRvcigpCiAgICAgZWxpZiB2
ZW5kb3IgPT0gJ25vbmUnOgotICAgICAgICBzZnRwID0gc3NoLlBhcmFtaWtvVmVuZG9yKCkuY29u
bmVjdF9zZnRwKHVzZXJuYW1lLCBwYXNzd29yZCwgaG9zdCwgcG9ydCkKKyAgICAgICAgdmVuZG9y
SW1wbCA9IHNzaC5QYXJhbWlrb1ZlbmRvcigpCisgICAgZWxpZiB2ZW5kb3IgPT0gJ29wZW5zc2gn
OgorICAgICAgICB2ZW5kb3JJbXBsID0gc3NoLk9wZW5TU0hTdWJwcm9jZXNzVmVuZG9yKCkKKyAg
ICBlbGlmIHZlbmRvciA9PSAnc3NoJzoKKyAgICAgICAgdmVuZG9ySW1wbCA9IHNzaC5TU0hDb3Jw
U3VicHJvY2Vzc1ZlbmRvcigpCiAgICAgZWxzZToKLSAgICAgICAgc2Z0cCA9IF9zdWJwcm9jZXNz
X2Nvbm5lY3Rfc2Z0cCh1c2VybmFtZSwgcGFzc3dvcmQsIGhvc3QsIHBvcnQsIHZlbmRvcikKLSAg
ICByZXR1cm4gc2Z0cAotCi1kZWYgX3N1YnByb2Nlc3NfY29ubmVjdF9zZnRwKHVzZXJuYW1lLCBw
YXNzd29yZCwgaG9zdCwgcG9ydCwgdmVuZG9yKToKLSAgICB0cnk6Ci0gICAgICAgIHNvY2sgPSBT
RlRQU3VicHJvY2Vzcyhob3N0LCB2ZW5kb3IsIHBvcnQsIHVzZXJuYW1lKQotICAgICAgICBzZnRw
ID0gU0ZUUENsaWVudChzb2NrKQotICAgIGV4Y2VwdCAoRU9GRXJyb3IsIHBhcmFtaWtvLlNTSEV4
Y2VwdGlvbiksIGU6Ci0gICAgICAgIHJhaXNlIENvbm5lY3Rpb25FcnJvcignVW5hYmxlIHRvIGNv
bm5lY3QgdG8gU1NIIGhvc3QgJXM6JXM6ICVzJwotICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgJSAoaG9zdCwgcG9ydCwgZSkpCi0gICAgZXhjZXB0IChPU0Vycm9yLCBJT0Vycm9yKSwgZToK
LSAgICAgICAgIyBJZiB0aGUgbWFjaGluZSBpcyBmYXN0IGVub3VnaCwgc3NoIGNhbiBhY3R1YWxs
eSBleGl0Ci0gICAgICAgICMgYmVmb3JlIHdlIHRyeSBhbmQgc2VuZCBpdCB0aGUgc2Z0cCByZXF1
ZXN0LCB3aGljaAotICAgICAgICAjIHJhaXNlcyBhIEJyb2tlbiBQaXBlCi0gICAgICAgIGlmIGUu
ZXJybm8gbm90IGluIChlcnJuby5FUElQRSwpOgotICAgICAgICAgICAgcmFpc2UKLSAgICAgICAg
cmFpc2UgQ29ubmVjdGlvbkVycm9yKCdVbmFibGUgdG8gY29ubmVjdCB0byBTU0ggaG9zdCAlczol
czogJXMnCi0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAlIChob3N0LCBwb3J0LCBlKSkK
LSAgICByZXR1cm4gc2Z0cAotCi0KKyAgICAgICAgYXNzZXJ0IEZhbHNlLCAiVW5rbm93biBTU0gg
dmVuZG9yOiAlciIgJSAodmVuZG9yLCkKKyAgICBzZnRwID0gdmVuZG9ySW1wbC5jb25uZWN0X3Nm
dHAodXNlcm5hbWUsIHBhc3N3b3JkLCBob3N0LCBwb3J0KQorICAgIHJldHVybiBzZnRwCiAKIAog
ZGVmIGdldF90ZXN0X3Blcm11dGF0aW9ucygpOgoK
=== modified file bzrlib/transport/ssh.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc3NoLnB5CisrKyBienJsaWIvdHJhbnNwb3J0L3NzaC5weQpA
QCAtMTcsOSArMTcsMTEgQEAKIAogIiIiRm91bmRhdGlvbiBTU0ggc3VwcG9ydCBmb3IgU0ZUUCBh
bmQgc21hcnQgc2VydmVyLiIiIgogCitpbXBvcnQgZXJybm8KIGltcG9ydCBnZXRwYXNzCiBpbXBv
cnQgb3MKIGltcG9ydCBzb2NrZXQKK2ltcG9ydCBzdWJwcm9jZXNzCiBpbXBvcnQgc3lzCiBpbXBv
cnQgd2Vha3JlZgogCkBAIC02MCw2ICs2MiwxNSBAQAogX3VzZV9zc2hfYWdlbnQgPSAoc3lzLnBs
YXRmb3JtICE9ICd3aW4zMicgb3IgX3BhcmFtaWtvX3ZlcnNpb24gPj0gKDEsIDYsIDApKQogCiAK
K2RlZiBfaWdub3JlX3NpZ2ludCgpOgorICAgICMgVE9ETzogVGhpcyBzaG91bGQgcG9zc2libHkg
aWdub3JlIFNJR0hVUCBhcyB3ZWxsLCBidXQgYnpyIGN1cnJlbnRseQorICAgICMgZG9lc24ndCBo
YW5kbGUgaXQgaXRzZWxmLgorICAgICMgPGh0dHBzOi8vbGF1bmNocGFkLm5ldC9wcm9kdWN0cy9i
enIvK2J1Zy80MTQzMy8raW5kZXg+CisgICAgaW1wb3J0IHNpZ25hbAorICAgIHNpZ25hbC5zaWdu
YWwoc2lnbmFsLlNJR0lOVCwgc2lnbmFsLlNJR19JR04pCisgICAgCisKKwogY2xhc3MgTG9vcGJh
Y2tTRlRQKG9iamVjdCk6CiAgICAgIiIiU2ltcGxlIHdyYXBwZXIgZm9yIGEgc29ja2V0IHRoYXQg
cHJldGVuZHMgdG8gYmUgYSBwYXJhbWlrbyBDaGFubmVsLiIiIgogCkBAIC0xNDksMTUgKzE2MCw3
MyBAQAogCiAKIGNsYXNzIFN1YnByb2Nlc3NWZW5kb3IoU1NIVmVuZG9yKToKLSAgICBwYXNzCisg
ICAgZGVmIGNvbm5lY3Rfc2Z0cChzZWxmLCB1c2VybmFtZSwgcGFzc3dvcmQsIGhvc3QsIHBvcnQp
OgorICAgICAgICB0cnk6CisgICAgICAgICAgICBhcmdzID0gc2VsZi5nZXRfYXJncyh1c2VybmFt
ZSwgaG9zdCwgcG9ydCwgc3Vic3lzdGVtPSdzZnRwJykKKyAgICAgICAgICAgIHByb2MgPSBzdWJw
cm9jZXNzLlBvcGVuKGFyZ3MsCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBz
dGRpbj1zdWJwcm9jZXNzLlBJUEUsCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICBzdGRvdXQ9c3VicHJvY2Vzcy5QSVBFLAorICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgKipvc19zcGVjaWZpY19zdWJwcm9jZXNzX3BhcmFtcygpKQorICAgICAgICAgICAgc29j
ayA9IFNTSFN1YnByb2Nlc3MocHJvYykKKyAgICAgICAgICAgIHJldHVybiBTRlRQQ2xpZW50KHNv
Y2spCisgICAgICAgIGV4Y2VwdCAoRU9GRXJyb3IsIHBhcmFtaWtvLlNTSEV4Y2VwdGlvbiksIGU6
CisgICAgICAgICAgICByYWlzZSBDb25uZWN0aW9uRXJyb3IoJ1VuYWJsZSB0byBjb25uZWN0IHRv
IFNTSCBob3N0ICVzOiVzOiAlcycKKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAl
IChob3N0LCBwb3J0LCBlKSkKKyAgICAgICAgZXhjZXB0IChPU0Vycm9yLCBJT0Vycm9yKSwgZToK
KyAgICAgICAgICAgICMgSWYgdGhlIG1hY2hpbmUgaXMgZmFzdCBlbm91Z2gsIHNzaCBjYW4gYWN0
dWFsbHkgZXhpdAorICAgICAgICAgICAgIyBiZWZvcmUgd2UgdHJ5IGFuZCBzZW5kIGl0IHRoZSBz
ZnRwIHJlcXVlc3QsIHdoaWNoCisgICAgICAgICAgICAjIHJhaXNlcyBhIEJyb2tlbiBQaXBlCisg
ICAgICAgICAgICBpZiBlLmVycm5vIG5vdCBpbiAoZXJybm8uRVBJUEUsKToKKyAgICAgICAgICAg
ICAgICByYWlzZQorICAgICAgICAgICAgcmFpc2UgQ29ubmVjdGlvbkVycm9yKCdVbmFibGUgdG8g
Y29ubmVjdCB0byBTU0ggaG9zdCAlczolczogJXMnCisgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgJSAoaG9zdCwgcG9ydCwgZSkpCisKKyAgICBkZWYgZ2V0X2FyZ3Moc2VsZiwgdXNl
cm5hbWUsIGhvc3QsIHBvcnQsIHN1YnN5c3RlbT1Ob25lLCBjb21tYW5kPU5vbmUpOgorICAgICAg
ICByYWlzZSBOb3RJbXBsZW1lbnRlZEVycm9yKHNlbGYuZ2V0X2FyZ3MpCiAKIAogY2xhc3MgT3Bl
blNTSFN1YnByb2Nlc3NWZW5kb3IoU3VicHJvY2Vzc1ZlbmRvcik6Ci0gICAgcGFzcworICAgIAor
ICAgIGRlZiBnZXRfYXJncyhzZWxmLCB1c2VybmFtZSwgaG9zdCwgcG9ydCwgc3Vic3lzdGVtPU5v
bmUsIGNvbW1hbmQ9Tm9uZSk6CisgICAgICAgIGFzc2VydCBzdWJzeXN0ZW0gaXMgbm90IE5vbmUg
b3IgY29tbWFuZCBpcyBub3QgTm9uZSwgKAorICAgICAgICAgICAgJ011c3Qgc3BlY2lmeSBhIGNv
bW1hbmQgb3Igc3Vic3lzdGVtJykKKyAgICAgICAgaWYgc3Vic3lzdGVtIGlzIG5vdCBOb25lOgor
ICAgICAgICAgICAgYXNzZXJ0IGNvbW1hbmQgaXMgTm9uZSwgKAorICAgICAgICAgICAgICAgICdz
dWJzeXN0ZW0gYW5kIGNvbW1hbmQgYXJlIG11dHVhbGx5IGV4Y2x1c2l2ZScpCisgICAgICAgIGFy
Z3MgPSBbJ3NzaCcsCisgICAgICAgICAgICAgICAgJy1vRm9yd2FyZFgxMT1ubycsICctb0Zvcndh
cmRBZ2VudD1ubycsCisgICAgICAgICAgICAgICAgJy1vQ2xlYXJBbGxGb3J3YXJkaW5ncz15ZXMn
LCAnLW9Qcm90b2NvbD0yJywKKyAgICAgICAgICAgICAgICAnLW9Ob0hvc3RBdXRoZW50aWNhdGlv
bkZvckxvY2FsaG9zdD15ZXMnXQorICAgICAgICBpZiBwb3J0IGlzIG5vdCBOb25lOgorICAgICAg
ICAgICAgYXJncy5leHRlbmQoWyctcCcsIHN0cihwb3J0KV0pCisgICAgICAgIGlmIHVzZXJuYW1l
IGlzIG5vdCBOb25lOgorICAgICAgICAgICAgYXJncy5leHRlbmQoWyctbCcsIHVzZXJuYW1lXSkK
KyAgICAgICAgaWYgc3Vic3lzdGVtIGlzIG5vdCBOb25lOgorICAgICAgICAgICAgYXJncy5leHRl
bmQoWyctcycsIGhvc3QsIHN1YnN5c3RlbV0pCisgICAgICAgIGVsc2U6CisgICAgICAgICAgICBh
cmdzLmV4dGVuZChbaG9zdF0gKyBjb21tYW5kKQorICAgICAgICByZXR1cm4gYXJncwogCiAKIGNs
YXNzIFNTSENvcnBTdWJwcm9jZXNzVmVuZG9yKFN1YnByb2Nlc3NWZW5kb3IpOgotICAgIHBhc3MK
KworICAgIGRlZiBnZXRfYXJncyhzZWxmLCB1c2VybmFtZSwgaG9zdCwgcG9ydCwgc3Vic3lzdGVt
PU5vbmUsIGNvbW1hbmQ9Tm9uZSk6CisgICAgICAgIGFzc2VydCBzdWJzeXN0ZW0gaXMgbm90IE5v
bmUgb3IgY29tbWFuZCBpcyBub3QgTm9uZSwgKAorICAgICAgICAgICAgJ011c3Qgc3BlY2lmeSBh
IGNvbW1hbmQgb3Igc3Vic3lzdGVtJykKKyAgICAgICAgaWYgc3Vic3lzdGVtIGlzIG5vdCBOb25l
OgorICAgICAgICAgICAgYXNzZXJ0IGNvbW1hbmQgaXMgTm9uZSwgKAorICAgICAgICAgICAgICAg
ICdzdWJzeXN0ZW0gYW5kIGNvbW1hbmQgYXJlIG11dHVhbGx5IGV4Y2x1c2l2ZScpCisgICAgICAg
IGFyZ3MgPSBbJ3NzaCcsICcteCddCisgICAgICAgIGlmIHBvcnQgaXMgbm90IE5vbmU6CisgICAg
ICAgICAgICBhcmdzLmV4dGVuZChbJy1wJywgc3RyKHBvcnQpXSkKKyAgICAgICAgaWYgdXNlcm5h
bWUgaXMgbm90IE5vbmU6CisgICAgICAgICAgICBhcmdzLmV4dGVuZChbJy1sJywgdXNlcm5hbWVd
KQorICAgICAgICBpZiBzdWJzeXN0ZW0gaXMgbm90IE5vbmU6CisgICAgICAgICAgICBhcmdzLmV4
dGVuZChbJy1zJywgc3Vic3lzdGVtLCBob3N0XSkKKyAgICAgICAgZWxzZToKKyAgICAgICAgICAg
IGFyZ3MuZXh0ZW5kKFtob3N0XSArIGNvbW1hbmQpCisgICAgICAgIHJldHVybiBhcmdzCisKICAg
ICAKIAogZGVmIF9wYXJhbWlrb19hdXRoKHVzZXJuYW1lLCBwYXNzd29yZCwgaG9zdCwgcGFyYW1p
a29fdHJhbnNwb3J0KToKQEAgLTI2MywzICszMzIsNTQgQEAKICAgICAgICAgbXV0dGVyKCdmYWls
ZWQgdG8gc2F2ZSBienIgaG9zdCBrZXlzOiAnICsgc3RyKGUpKQogCiAKK2RlZiBvc19zcGVjaWZp
Y19zdWJwcm9jZXNzX3BhcmFtcygpOgorICAgICIiIkdldCBPL1Mgc3BlY2lmaWMgc3VicHJvY2Vz
cyBwYXJhbWV0ZXJzLiIiIgorICAgIGlmIHN5cy5wbGF0Zm9ybSA9PSAnd2luMzInOgorICAgICAg
ICAjIHNldHRpbmcgdGhlIHByb2Nlc3MgZ3JvdXAgYW5kIGNsb3NpbmcgZmRzIGlzIG5vdCBzdXBw
b3J0ZWQgb24gCisgICAgICAgICMgd2luMzIKKyAgICAgICAgcmV0dXJuIHt9CisgICAgZWxzZToK
KyAgICAgICAgIyBXZSBjbG9zZSBmZHMgb3RoZXIgdGhhbiB0aGUgcGlwZXMgYXMgdGhlIGNoaWxk
IHByb2Nlc3MgZG9lcyBub3QgbmVlZCAKKyAgICAgICAgIyB0aGVtIHRvIGJlIG9wZW4uCisgICAg
ICAgICMKKyAgICAgICAgIyBXZSBhbHNvIHNldCB0aGUgY2hpbGQgcHJvY2VzcyB0byBpZ25vcmUg
U0lHSU5ULiAgTm9ybWFsbHkgdGhlIHNpZ25hbAorICAgICAgICAjIHdvdWxkIGJlIHNlbnQgdG8g
ZXZlcnkgcHJvY2VzcyBpbiB0aGUgZm9yZWdyb3VuZCBwcm9jZXNzIGdyb3VwLCBidXQKKyAgICAg
ICAgIyB0aGlzIGNhdXNlcyBpdCB0byBiZSBzZWVuIG9ubHkgYnkgYnpyIGFuZCBub3QgYnkgc3No
LiAgUHl0aG9uIHdpbGwKKyAgICAgICAgIyBnZW5lcmF0ZSBhIEtleWJvYXJkSW50ZXJydXB0IGlu
IGJ6ciwgYW5kIHdlIHdpbGwgdGhlbiBoYXZlIGEgY2hhbmNlCisgICAgICAgICMgdG8gcmVsZWFz
ZSBsb2NrcyBvciBkbyBvdGhlciBjbGVhbnVwIG92ZXIgc3NoIGJlZm9yZSB0aGUgY29ubmVjdGlv
bgorICAgICAgICAjIGdvZXMgYXdheS4gIAorICAgICAgICAjIDxodHRwczovL2xhdW5jaHBhZC5u
ZXQvcHJvZHVjdHMvYnpyLytidWcvNTk4Nz4KKyAgICAgICAgIworICAgICAgICAjIFJ1bm5pbmcg
aXQgaW4gYSBzZXBhcmF0ZSBwcm9jZXNzIGdyb3VwIGlzIG5vdCBnb29kIGJlY2F1c2UgdGhlbiBp
dAorICAgICAgICAjIGNhbid0IGdldCBub24tZWNob2VkIGlucHV0IG9mIGEgcGFzc3dvcmQgb3Ig
cGFzc3BocmFzZS4KKyAgICAgICAgIyA8aHR0cHM6Ly9sYXVuY2hwYWQubmV0L3Byb2R1Y3RzL2J6
ci8rYnVnLzQwNTA4PgorICAgICAgICByZXR1cm4geydwcmVleGVjX2ZuJzogX2lnbm9yZV9zaWdp
bnQsCisgICAgICAgICAgICAgICAgJ2Nsb3NlX2Zkcyc6IFRydWUsCisgICAgICAgICAgICAgICAg
fQorCitjbGFzcyBTU0hTdWJwcm9jZXNzKG9iamVjdCk6CisgICAgIiIiQSBzb2NrZXQtbGlrZSBv
YmplY3QgdGhhdCB0YWxrcyB0byBhbiBzc2ggc3VicHJvY2VzcyB2aWEgcGlwZXMuIiIiCisgICAg
IyBUT0RPOiB0aGlzIGNsYXNzIHByb2JhYmx5IGJlbG9uZ3MgaW4gYnpybGliL3RyYW5zcG9ydC9z
c2gucHkKKworICAgIGRlZiBfX2luaXRfXyhzZWxmLCBwcm9jKToKKyAgICAgICAgc2VsZi5wcm9j
ID0gcHJvYworCisgICAgZGVmIHNlbmQoc2VsZiwgZGF0YSk6CisgICAgICAgIHJldHVybiBvcy53
cml0ZShzZWxmLnByb2Muc3RkaW4uZmlsZW5vKCksIGRhdGEpCisKKyAgICBkZWYgcmVjdl9yZWFk
eShzZWxmKToKKyAgICAgICAgIyBUT0RPOiBqYW0gMjAwNTEyMTUgdGhpcyBmdW5jdGlvbiBpcyBu
ZWNlc3NhcnkgdG8gc3VwcG9ydCB0aGUKKyAgICAgICAgIyBwaXBlbGluZWQoKSBmdW5jdGlvbi4g
SW4gcmVhbGl0eSwgaXQgcHJvYmFibHkgc2hvdWxkIHVzZQorICAgICAgICAjIHBvbGwoKSBvciBz
ZWxlY3QoKSB0byBhY3R1YWxseSByZXR1cm4gaWYgdGhlcmUgaXMgZGF0YQorICAgICAgICAjIGF2
YWlsYWJsZSwgb3RoZXJ3aXNlIHdlIHByb2JhYmx5IGRvbid0IGdldCBhbnkgYmVuZWZpdAorICAg
ICAgICByZXR1cm4gVHJ1ZQorCisgICAgZGVmIHJlY3Yoc2VsZiwgY291bnQpOgorICAgICAgICBy
ZXR1cm4gb3MucmVhZChzZWxmLnByb2Muc3Rkb3V0LmZpbGVubygpLCBjb3VudCkKKworICAgIGRl
ZiBjbG9zZShzZWxmKToKKyAgICAgICAgc2VsZi5wcm9jLnN0ZGluLmNsb3NlKCkKKyAgICAgICAg
c2VsZi5wcm9jLnN0ZG91dC5jbG9zZSgpCisgICAgICAgIHNlbGYucHJvYy53YWl0KCkKKworCgo=
# revision id: andrew.bennetts at canonical.com-20060824091407-af213b6a30b6066a
# sha1: a47b0b9c28e6fff245d3efa9b3441ab092063ae8
# inventory sha1: 4824a44a585dad1fc48a100cf08a6a401ba73d15
# parent ids:
# andrew.bennetts at canonical.com-20060824042731-46d9e0f9d4da568a
# properties:
# branch-nick: sftp refactoring 2
# message:
# Tidy up some unused imports.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Thu 2006-08-24 14:27:31.141999960 +1000
=== modified file bzrlib/transport/sftp.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc2Z0cC5weQorKysgYnpybGliL3RyYW5zcG9ydC9zZnRwLnB5
CkBAIC0xOCwxMSArMTgsOCBAQAogIiIiSW1wbGVtZW50YXRpb24gb2YgVHJhbnNwb3J0IG92ZXIg
U0ZUUCwgdXNpbmcgcGFyYW1pa28uIiIiCiAKIGltcG9ydCBlcnJubwotaW1wb3J0IGdldHBhc3MK
LWltcG9ydCBpdGVydG9vbHMKIGltcG9ydCBvcwogaW1wb3J0IHJhbmRvbQotaW1wb3J0IHJlCiBp
bXBvcnQgc2VsZWN0CiBpbXBvcnQgc29ja2V0CiBpbXBvcnQgc3RhdApAQCAtMzEsMTkgKzI4LDE3
IEBACiBpbXBvcnQgdGltZQogaW1wb3J0IHVybGxpYgogaW1wb3J0IHVybHBhcnNlCi1pbXBvcnQg
d2Vha3JlZgogCi1mcm9tIGJ6cmxpYi5jb25maWcgaW1wb3J0IGNvbmZpZ19kaXIsIGVuc3VyZV9j
b25maWdfZGlyX2V4aXN0cwogZnJvbSBienJsaWIuZXJyb3JzIGltcG9ydCAoQ29ubmVjdGlvbkVy
cm9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRmlsZUV4aXN0cywgCi0gICAgICAgICAg
ICAgICAgICAgICAgICAgICBUcmFuc3BvcnROb3RQb3NzaWJsZSwgTm9TdWNoRmlsZSwgUGF0aE5v
dENoaWxkLAorICAgICAgICAgICAgICAgICAgICAgICAgICAgTm9TdWNoRmlsZSwgUGF0aE5vdENo
aWxkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhbnNwb3J0RXJyb3IsCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICBMb2NrRXJyb3IsIAogICAgICAgICAgICAgICAgICAgICAgICAg
ICAgUGF0aEVycm9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUGFyYW1pa29Ob3RQcmVz
ZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogZnJvbSBienJsaWIub3N1dGlscyBp
bXBvcnQgcGF0aGpvaW4sIGZhbmN5X3JlbmFtZSwgZ2V0Y3dkCi1mcm9tIGJ6cmxpYi50cmFjZSBp
bXBvcnQgbXV0dGVyLCB3YXJuaW5nLCBlcnJvcgorZnJvbSBienJsaWIudHJhY2UgaW1wb3J0IG11
dHRlciwgd2FybmluZwogZnJvbSBienJsaWIudHJhbnNwb3J0IGltcG9ydCAoCiAgICAgcmVnaXN0
ZXJfdXJscGFyc2VfbmV0bG9jX3Byb3RvY29sLAogICAgIFNlcnZlciwKQEAgLTc3OCw3ICs3NzMs
NiBAQAogCiAKICMgLS0tLS0tLS0tLS0tLSBzZXJ2ZXIgdGVzdCBpbXBsZW1lbnRhdGlvbiAtLS0t
LS0tLS0tLS0tLQotaW1wb3J0IHNvY2tldAogaW1wb3J0IHRocmVhZGluZwogCiBmcm9tIGJ6cmxp
Yi50ZXN0cy5zdHViX3NmdHAgaW1wb3J0IFN0dWJTZXJ2ZXIsIFN0dWJTRlRQU2VydmVyCgo=
# revision id: andrew.bennetts at canonical.com-20060824042731-46d9e0f9d4da568a
# sha1: e3ac41e3f2eb9d6108469301a0cff7e76f21bfcd
# inventory sha1: 2ee3ad6cd8072b16eff8451992b17e74e42137d7
# parent ids:
# andrew.bennetts at canonical.com-20060824042616-7fa6f48fab37e678
# properties:
# branch-nick: sftp refactoring 2
# message:
# Fix some missing imports with a bit of help from pyflakes.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Thu 2006-08-24 14:26:16.039000034 +1000
=== modified file bzrlib/transport/ssh.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc3NoLnB5CisrKyBienJsaWIvdHJhbnNwb3J0L3NzaC5weQpA
QCAtMTcsNiArMTcsNyBAQAogCiAiIiJGb3VuZGF0aW9uIFNTSCBzdXBwb3J0IGZvciBTRlRQIGFu
ZCBzbWFydCBzZXJ2ZXIuIiIiCiAKK2ltcG9ydCBnZXRwYXNzCiBpbXBvcnQgb3MKIGltcG9ydCBz
b2NrZXQKIGltcG9ydCBzeXMKQEAgLTI4LDggKzI5LDkgQEAKICAgICAgICAgICAgICAgICAgICAg
ICAgICAgIFRyYW5zcG9ydEVycm9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogCi1m
cm9tIGJ6cmxpYi5vc3V0aWxzIGltcG9ydCBwYXRoam9pbiwgZmFuY3lfcmVuYW1lLCBnZXRjd2QK
K2Zyb20gYnpybGliLm9zdXRpbHMgaW1wb3J0IHBhdGhqb2luCiBmcm9tIGJ6cmxpYi50cmFjZSBp
bXBvcnQgbXV0dGVyLCB3YXJuaW5nCitpbXBvcnQgYnpybGliLnVpCiAKIHRyeToKICAgICBpbXBv
cnQgcGFyYW1pa28KQEAgLTQ5LDYgKzUxLDggQEAKICMgWCBzZWNvbmRzLiBCdXQgdGhhdCByZXF1
aXJlcyBhIGxvdCBtb3JlIGZhbmNpbmVzcy4KIF9jb25uZWN0ZWRfaG9zdHMgPSB3ZWFrcmVmLldl
YWtWYWx1ZURpY3Rpb25hcnkoKQogCitfcGFyYW1pa29fdmVyc2lvbiA9IGdldGF0dHIocGFyYW1p
a28sICdfX3ZlcnNpb25faW5mb19fJywgKDAsIDAsIDApKQorCiAjIFBhcmFtaWtvIDEuNSB0cmll
cyB0byBvcGVuIGEgc29ja2V0LkFGX1VOSVggaW4gb3JkZXIgdG8gY29ubmVjdAogIyB0byBzc2gt
YWdlbnQuIFRoYXQgYXR0cmlidXRlIGRvZXNuJ3QgZXhpc3Qgb24gd2luMzIgKGl0IGRvZXMgaW4g
Y3lnd2luKQogIyBzbyB3ZSBnZXQgYW4gQXR0cmlidXRlRXJyb3IgZXhjZXB0aW9uLiBTbyB3ZSB3
aWxsIG5vdCB0cnkgdG8KCg==
# revision id: andrew.bennetts at canonical.com-20060824042616-7fa6f48fab37e678
# sha1: d2494a911a5b1b8fe3698d2f0105bda6e96ce145
# inventory sha1: c1263dea83eea801cd7d92c84c2ff03f44103b08
# parent ids:
# andrew.bennetts at canonical.com-20060824042240-58a184f25a126261
# properties:
# branch-nick: sftp refactoring 2
# message:
# Start moving SSH connection code into bzrlib/transport/ssh.py
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Thu 2006-08-24 14:22:40.615999937 +1000
=== added file bzrlib/transport/ssh.py // file-id:ssh.py-20060824042150-0s9787k
... ng6zv1nwq-1 // encoding:base64
LS0tIC9kZXYvbnVsbAorKysgYnpybGliL3RyYW5zcG9ydC9zc2gucHkKQEAgLTAsMCArMSwyNjEg
QEAKKyMgQ29weXJpZ2h0IChDKSAyMDA1IFJvYmV5IFBvaW50ZXIgPHJvYmV5QGxhZy5uZXQ+Cisj
IENvcHlyaWdodCAoQykgMjAwNSwgMjAwNiBDYW5vbmljYWwgTHRkCisjCisjIFRoaXMgcHJvZ3Jh
bSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5
CisjIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2Ug
YXMgcHVibGlzaGVkIGJ5CisjIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2
ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCisjIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVy
IHZlcnNpb24uCisjCisjIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0
aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAorIyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhv
dXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgorIyBNRVJDSEFOVEFCSUxJVFkgb3IgRklU
TkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisjIEdOVSBHZW5lcmFsIFB1
YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCisjCisjIFlvdSBzaG91bGQgaGF2ZSByZWNl
aXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCisjIGFsb25nIHdp
dGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCisjIEZv
dW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAw
MjExMS0xMzA3ICBVU0EKKworIiIiRm91bmRhdGlvbiBTU0ggc3VwcG9ydCBmb3IgU0ZUUCBhbmQg
c21hcnQgc2VydmVyLiIiIgorCitpbXBvcnQgb3MKK2ltcG9ydCBzb2NrZXQKK2ltcG9ydCBzeXMK
K2ltcG9ydCB3ZWFrcmVmCisKK2Zyb20gYnpybGliLmNvbmZpZyBpbXBvcnQgY29uZmlnX2Rpciwg
ZW5zdXJlX2NvbmZpZ19kaXJfZXhpc3RzCitmcm9tIGJ6cmxpYi5lcnJvcnMgaW1wb3J0IChDb25u
ZWN0aW9uRXJyb3IsCisgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXJhbWlrb05vdFByZXNl
bnQsCisgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmFuc3BvcnRFcnJvciwKKyAgICAgICAg
ICAgICAgICAgICAgICAgICAgICkKKworZnJvbSBienJsaWIub3N1dGlscyBpbXBvcnQgcGF0aGpv
aW4sIGZhbmN5X3JlbmFtZSwgZ2V0Y3dkCitmcm9tIGJ6cmxpYi50cmFjZSBpbXBvcnQgbXV0dGVy
LCB3YXJuaW5nCisKK3RyeToKKyAgICBpbXBvcnQgcGFyYW1pa28KK2V4Y2VwdCBJbXBvcnRFcnJv
ciwgZToKKyAgICByYWlzZSBQYXJhbWlrb05vdFByZXNlbnQoZSkKK2Vsc2U6CisgICAgZnJvbSBw
YXJhbWlrby5zZnRwX2NsaWVudCBpbXBvcnQgU0ZUUENsaWVudAorCisKK1NZU1RFTV9IT1NUS0VZ
UyA9IHt9CitCWlJfSE9TVEtFWVMgPSB7fQorCisKKyMgVGhpcyBpcyBhIHdlYWtyZWYgZGljdGlv
bmFyeSwgc28gdGhhdCB3ZSBjYW4gcmV1c2UgY29ubmVjdGlvbnMKKyMgdGhhdCBhcmUgc3RpbGwg
YWN0aXZlLiBMb25nIHRlcm0sIGl0IG1pZ2h0IGJlIG5pY2UgdG8gaGF2ZSBzb21lCisjIHNvcnQg
b2YgZXhwaXJhdGlvbiBwb2xpY3ksIHN1Y2ggYXMgZGlzY29ubmVjdCBpZiBpbmFjdGl2ZSBmb3IK
KyMgWCBzZWNvbmRzLiBCdXQgdGhhdCByZXF1aXJlcyBhIGxvdCBtb3JlIGZhbmNpbmVzcy4KK19j
b25uZWN0ZWRfaG9zdHMgPSB3ZWFrcmVmLldlYWtWYWx1ZURpY3Rpb25hcnkoKQorCisjIFBhcmFt
aWtvIDEuNSB0cmllcyB0byBvcGVuIGEgc29ja2V0LkFGX1VOSVggaW4gb3JkZXIgdG8gY29ubmVj
dAorIyB0byBzc2gtYWdlbnQuIFRoYXQgYXR0cmlidXRlIGRvZXNuJ3QgZXhpc3Qgb24gd2luMzIg
KGl0IGRvZXMgaW4gY3lnd2luKQorIyBzbyB3ZSBnZXQgYW4gQXR0cmlidXRlRXJyb3IgZXhjZXB0
aW9uLiBTbyB3ZSB3aWxsIG5vdCB0cnkgdG8KKyMgY29ubmVjdCB0byBhbiBhZ2VudCBpZiB3ZSBh
cmUgb24gd2luMzIgYW5kIHVzaW5nIFBhcmFtaWtvIG9sZGVyIHRoYW4gMS42CitfdXNlX3NzaF9h
Z2VudCA9IChzeXMucGxhdGZvcm0gIT0gJ3dpbjMyJyBvciBfcGFyYW1pa29fdmVyc2lvbiA+PSAo
MSwgNiwgMCkpCisKKworY2xhc3MgTG9vcGJhY2tTRlRQKG9iamVjdCk6CisgICAgIiIiU2ltcGxl
IHdyYXBwZXIgZm9yIGEgc29ja2V0IHRoYXQgcHJldGVuZHMgdG8gYmUgYSBwYXJhbWlrbyBDaGFu
bmVsLiIiIgorCisgICAgZGVmIF9faW5pdF9fKHNlbGYsIHNvY2spOgorICAgICAgICBzZWxmLl9f
c29ja2V0ID0gc29jaworIAorICAgIGRlZiBzZW5kKHNlbGYsIGRhdGEpOgorICAgICAgICByZXR1
cm4gc2VsZi5fX3NvY2tldC5zZW5kKGRhdGEpCisKKyAgICBkZWYgcmVjdihzZWxmLCBuKToKKyAg
ICAgICAgcmV0dXJuIHNlbGYuX19zb2NrZXQucmVjdihuKQorCisgICAgZGVmIHJlY3ZfcmVhZHko
c2VsZik6CisgICAgICAgIHJldHVybiBUcnVlCisKKyAgICBkZWYgY2xvc2Uoc2VsZik6CisgICAg
ICAgIHNlbGYuX19zb2NrZXQuY2xvc2UoKQorCisKK2NsYXNzIFNTSFZlbmRvcihvYmplY3QpOgor
ICAgIGRlZiBjb25uZWN0X3NmdHAoc2VsZiwgdXNlcm5hbWUsIHBhc3N3b3JkLCBob3N0LCBwb3J0
KToKKyAgICAgICAgcmFpc2UgTm90SW1wbGVtZW50ZWRFcnJvcihzZWxmLmNvbm5lY3Rfc2Z0cCkK
KworICAgIGRlZiBjb25uZWN0X3NzaChzZWxmLCB1c2VybmFtZSwgcGFzc3dvcmQsIGhvc3QsIHBv
cnQsIGNvbW1hbmQpOgorICAgICAgICByYWlzZSBOb3RJbXBsZW1lbnRlZEVycm9yKHNlbGYuY29u
bmVjdF9zc2gpCisgICAgICAgIAorCitjbGFzcyBMb29wYmFja1ZlbmRvcihTU0hWZW5kb3IpOgor
ICAgIAorICAgIGRlZiBjb25uZWN0X3NmdHAoc2VsZiwgdXNlcm5hbWUsIHBhc3N3b3JkLCBob3N0
LCBwb3J0KToKKyAgICAgICAgc29jayA9IHNvY2tldC5zb2NrZXQoKQorICAgICAgICB0cnk6Cisg
ICAgICAgICAgICBzb2NrLmNvbm5lY3QoKGhvc3QsIHBvcnQpKQorICAgICAgICBleGNlcHQgc29j
a2V0LmVycm9yLCBlOgorICAgICAgICAgICAgcmFpc2UgQ29ubmVjdGlvbkVycm9yKCdVbmFibGUg
dG8gY29ubmVjdCB0byBTU0ggaG9zdCAlczolczogJXMnCisgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgJSAoaG9zdCwgcG9ydCwgZSkpCisgICAgICAgIHJldHVybiBTRlRQQ2xpZW50
KExvb3BiYWNrU0ZUUChzb2NrKSkKKworCitjbGFzcyBQYXJhbWlrb1ZlbmRvcihTU0hWZW5kb3Ip
OgorCisgICAgZGVmIGNvbm5lY3Rfc2Z0cChzZWxmLCB1c2VybmFtZSwgcGFzc3dvcmQsIGhvc3Qs
IHBvcnQpOgorICAgICAgICBnbG9iYWwgU1lTVEVNX0hPU1RLRVlTLCBCWlJfSE9TVEtFWVMKKyAg
ICAgICAgCisgICAgICAgIGxvYWRfaG9zdF9rZXlzKCkKKworICAgICAgICB0cnk6CisgICAgICAg
ICAgICB0ID0gcGFyYW1pa28uVHJhbnNwb3J0KChob3N0LCBwb3J0IG9yIDIyKSkKKyAgICAgICAg
ICAgIHQuc2V0X2xvZ19jaGFubmVsKCdienIucGFyYW1pa28nKQorICAgICAgICAgICAgdC5zdGFy
dF9jbGllbnQoKQorICAgICAgICBleGNlcHQgKHBhcmFtaWtvLlNTSEV4Y2VwdGlvbiwgc29ja2V0
LmVycm9yKSwgZToKKyAgICAgICAgICAgIHJhaXNlIENvbm5lY3Rpb25FcnJvcignVW5hYmxlIHRv
IHJlYWNoIFNTSCBob3N0ICVzOiVzOiAlcycgCisgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgJSAoaG9zdCwgcG9ydCwgZSkpCisgICAgICAgICAgICAKKyAgICAgICAgc2VydmVyX2tl
eSA9IHQuZ2V0X3JlbW90ZV9zZXJ2ZXJfa2V5KCkKKyAgICAgICAgc2VydmVyX2tleV9oZXggPSBw
YXJhbWlrby51dGlsLmhleGlmeShzZXJ2ZXJfa2V5LmdldF9maW5nZXJwcmludCgpKQorICAgICAg
ICBrZXl0eXBlID0gc2VydmVyX2tleS5nZXRfbmFtZSgpCisgICAgICAgIGlmIFNZU1RFTV9IT1NU
S0VZUy5oYXNfa2V5KGhvc3QpIGFuZCBTWVNURU1fSE9TVEtFWVNbaG9zdF0uaGFzX2tleShrZXl0
eXBlKToKKyAgICAgICAgICAgIG91cl9zZXJ2ZXJfa2V5ID0gU1lTVEVNX0hPU1RLRVlTW2hvc3Rd
W2tleXR5cGVdCisgICAgICAgICAgICBvdXJfc2VydmVyX2tleV9oZXggPSBwYXJhbWlrby51dGls
LmhleGlmeShvdXJfc2VydmVyX2tleS5nZXRfZmluZ2VycHJpbnQoKSkKKyAgICAgICAgZWxpZiBC
WlJfSE9TVEtFWVMuaGFzX2tleShob3N0KSBhbmQgQlpSX0hPU1RLRVlTW2hvc3RdLmhhc19rZXko
a2V5dHlwZSk6CisgICAgICAgICAgICBvdXJfc2VydmVyX2tleSA9IEJaUl9IT1NUS0VZU1tob3N0
XVtrZXl0eXBlXQorICAgICAgICAgICAgb3VyX3NlcnZlcl9rZXlfaGV4ID0gcGFyYW1pa28udXRp
bC5oZXhpZnkob3VyX3NlcnZlcl9rZXkuZ2V0X2ZpbmdlcnByaW50KCkpCisgICAgICAgIGVsc2U6
CisgICAgICAgICAgICB3YXJuaW5nKCdBZGRpbmcgJXMgaG9zdCBrZXkgZm9yICVzOiAlcycgJSAo
a2V5dHlwZSwgaG9zdCwgc2VydmVyX2tleV9oZXgpKQorICAgICAgICAgICAgaWYgbm90IEJaUl9I
T1NUS0VZUy5oYXNfa2V5KGhvc3QpOgorICAgICAgICAgICAgICAgIEJaUl9IT1NUS0VZU1tob3N0
XSA9IHt9CisgICAgICAgICAgICBCWlJfSE9TVEtFWVNbaG9zdF1ba2V5dHlwZV0gPSBzZXJ2ZXJf
a2V5CisgICAgICAgICAgICBvdXJfc2VydmVyX2tleSA9IHNlcnZlcl9rZXkKKyAgICAgICAgICAg
IG91cl9zZXJ2ZXJfa2V5X2hleCA9IHBhcmFtaWtvLnV0aWwuaGV4aWZ5KG91cl9zZXJ2ZXJfa2V5
LmdldF9maW5nZXJwcmludCgpKQorICAgICAgICAgICAgc2F2ZV9ob3N0X2tleXMoKQorICAgICAg
ICBpZiBzZXJ2ZXJfa2V5ICE9IG91cl9zZXJ2ZXJfa2V5OgorICAgICAgICAgICAgZmlsZW5hbWUx
ID0gb3MucGF0aC5leHBhbmR1c2VyKCd+Ly5zc2gva25vd25faG9zdHMnKQorICAgICAgICAgICAg
ZmlsZW5hbWUyID0gcGF0aGpvaW4oY29uZmlnX2RpcigpLCAnc3NoX2hvc3Rfa2V5cycpCisgICAg
ICAgICAgICByYWlzZSBUcmFuc3BvcnRFcnJvcignSG9zdCBrZXlzIGZvciAlcyBkbyBub3QgbWF0
Y2ghICAlcyAhPSAlcycgJSBcCisgICAgICAgICAgICAgICAgKGhvc3QsIG91cl9zZXJ2ZXJfa2V5
X2hleCwgc2VydmVyX2tleV9oZXgpLAorICAgICAgICAgICAgICAgIFsnVHJ5IGVkaXRpbmcgJXMg
b3IgJXMnICUgKGZpbGVuYW1lMSwgZmlsZW5hbWUyKV0pCisKKyAgICAgICAgX3BhcmFtaWtvX2F1
dGgodXNlcm5hbWUsIHBhc3N3b3JkLCBob3N0LCB0KQorICAgICAgICAKKyAgICAgICAgdHJ5Ogor
ICAgICAgICAgICAgc2Z0cCA9IHQub3Blbl9zZnRwX2NsaWVudCgpCisgICAgICAgIGV4Y2VwdCBw
YXJhbWlrby5TU0hFeGNlcHRpb24sIGU6CisgICAgICAgICAgICByYWlzZSBDb25uZWN0aW9uRXJy
b3IoJ1VuYWJsZSB0byBzdGFydCBzZnRwIGNsaWVudCAlczolZCcgJQorICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgIChob3N0LCBwb3J0KSwgZSkKKyAgICAgICAgcmV0dXJuIHNmdHAK
KworCitjbGFzcyBTdWJwcm9jZXNzVmVuZG9yKFNTSFZlbmRvcik6CisgICAgcGFzcworCisKK2Ns
YXNzIE9wZW5TU0hTdWJwcm9jZXNzVmVuZG9yKFN1YnByb2Nlc3NWZW5kb3IpOgorICAgIHBhc3MK
KworCitjbGFzcyBTU0hDb3JwU3VicHJvY2Vzc1ZlbmRvcihTdWJwcm9jZXNzVmVuZG9yKToKKyAg
ICBwYXNzCisgICAgCisKK2RlZiBfcGFyYW1pa29fYXV0aCh1c2VybmFtZSwgcGFzc3dvcmQsIGhv
c3QsIHBhcmFtaWtvX3RyYW5zcG9ydCk6CisgICAgIyBwYXJhbWlrbyByZXF1aXJlcyBhIHVzZXJu
YW1lLCBidXQgaXQgbWlnaHQgYmUgbm9uZSBpZiBub3RoaW5nIHdhcyBzdXBwbGllZAorICAgICMg
dXNlIHRoZSBsb2NhbCB1c2VybmFtZSwganVzdCBpbiBjYXNlLgorICAgICMgV2UgZG9uJ3Qgb3Zl
cnJpZGUgdXNlcm5hbWUsIGJlY2F1c2UgaWYgd2UgYXJlbid0IHVzaW5nIHBhcmFtaWtvLAorICAg
ICMgdGhlIHVzZXJuYW1lIG1pZ2h0IGJlIHNwZWNpZmllZCBpbiB+Ly5zc2gvY29uZmlnIGFuZCB3
ZSBkb24ndCB3YW50IHRvCisgICAgIyBmb3JjZSBpdCB0byBzb21ldGhpbmcgZWxzZQorICAgICMg
QWxzbywgaXQgd291bGQgbWVzcyB1cCB0aGUgc2VsZi5yZWxwYXRoKCkgZnVuY3Rpb25hbGl0eQor
ICAgIHVzZXJuYW1lID0gdXNlcm5hbWUgb3IgZ2V0cGFzcy5nZXR1c2VyKCkKKworICAgIGlmIF91
c2Vfc3NoX2FnZW50OgorICAgICAgICBhZ2VudCA9IHBhcmFtaWtvLkFnZW50KCkKKyAgICAgICAg
Zm9yIGtleSBpbiBhZ2VudC5nZXRfa2V5cygpOgorICAgICAgICAgICAgbXV0dGVyKCdUcnlpbmcg
U1NIIGFnZW50IGtleSAlcycgJSBwYXJhbWlrby51dGlsLmhleGlmeShrZXkuZ2V0X2ZpbmdlcnBy
aW50KCkpKQorICAgICAgICAgICAgdHJ5OgorICAgICAgICAgICAgICAgIHBhcmFtaWtvX3RyYW5z
cG9ydC5hdXRoX3B1YmxpY2tleSh1c2VybmFtZSwga2V5KQorICAgICAgICAgICAgICAgIHJldHVy
bgorICAgICAgICAgICAgZXhjZXB0IHBhcmFtaWtvLlNTSEV4Y2VwdGlvbiwgZToKKyAgICAgICAg
ICAgICAgICBwYXNzCisgICAgCisgICAgIyBva2F5LCB0cnkgZmluZGluZyBpZF9yc2Egb3IgaWRf
ZHNzPyAgKHBvc2l4IG9ubHkpCisgICAgaWYgX3RyeV9wa2V5X2F1dGgocGFyYW1pa29fdHJhbnNw
b3J0LCBwYXJhbWlrby5SU0FLZXksIHVzZXJuYW1lLCAnaWRfcnNhJyk6CisgICAgICAgIHJldHVy
bgorICAgIGlmIF90cnlfcGtleV9hdXRoKHBhcmFtaWtvX3RyYW5zcG9ydCwgcGFyYW1pa28uRFNT
S2V5LCB1c2VybmFtZSwgJ2lkX2RzYScpOgorICAgICAgICByZXR1cm4KKworICAgIGlmIHBhc3N3
b3JkOgorICAgICAgICB0cnk6CisgICAgICAgICAgICBwYXJhbWlrb190cmFuc3BvcnQuYXV0aF9w
YXNzd29yZCh1c2VybmFtZSwgcGFzc3dvcmQpCisgICAgICAgICAgICByZXR1cm4KKyAgICAgICAg
ZXhjZXB0IHBhcmFtaWtvLlNTSEV4Y2VwdGlvbiwgZToKKyAgICAgICAgICAgIHBhc3MKKworICAg
ICMgZ2l2ZSB1cCBhbmQgYXNrIGZvciBhIHBhc3N3b3JkCisgICAgcGFzc3dvcmQgPSBienJsaWIu
dWkudWlfZmFjdG9yeS5nZXRfcGFzc3dvcmQoCisgICAgICAgICAgICBwcm9tcHQ9J1NTSCAlKHVz
ZXIpc0AlKGhvc3QpcyBwYXNzd29yZCcsCisgICAgICAgICAgICB1c2VyPXVzZXJuYW1lLCBob3N0
PWhvc3QpCisgICAgdHJ5OgorICAgICAgICBwYXJhbWlrb190cmFuc3BvcnQuYXV0aF9wYXNzd29y
ZCh1c2VybmFtZSwgcGFzc3dvcmQpCisgICAgZXhjZXB0IHBhcmFtaWtvLlNTSEV4Y2VwdGlvbiwg
ZToKKyAgICAgICAgcmFpc2UgQ29ubmVjdGlvbkVycm9yKCdVbmFibGUgdG8gYXV0aGVudGljYXRl
IHRvIFNTSCBob3N0IGFzICVzQCVzJyAlCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAo
dXNlcm5hbWUsIGhvc3QpLCBlKQorCisKK2RlZiBfdHJ5X3BrZXlfYXV0aChwYXJhbWlrb190cmFu
c3BvcnQsIHBrZXlfY2xhc3MsIHVzZXJuYW1lLCBmaWxlbmFtZSk6CisgICAgZmlsZW5hbWUgPSBv
cy5wYXRoLmV4cGFuZHVzZXIoJ34vLnNzaC8nICsgZmlsZW5hbWUpCisgICAgdHJ5OgorICAgICAg
ICBrZXkgPSBwa2V5X2NsYXNzLmZyb21fcHJpdmF0ZV9rZXlfZmlsZShmaWxlbmFtZSkKKyAgICAg
ICAgcGFyYW1pa29fdHJhbnNwb3J0LmF1dGhfcHVibGlja2V5KHVzZXJuYW1lLCBrZXkpCisgICAg
ICAgIHJldHVybiBUcnVlCisgICAgZXhjZXB0IHBhcmFtaWtvLlBhc3N3b3JkUmVxdWlyZWRFeGNl
cHRpb246CisgICAgICAgIHBhc3N3b3JkID0gYnpybGliLnVpLnVpX2ZhY3RvcnkuZ2V0X3Bhc3N3
b3JkKAorICAgICAgICAgICAgICAgIHByb21wdD0nU1NIICUoZmlsZW5hbWUpcyBwYXNzd29yZCcs
CisgICAgICAgICAgICAgICAgZmlsZW5hbWU9ZmlsZW5hbWUpCisgICAgICAgIHRyeToKKyAgICAg
ICAgICAgIGtleSA9IHBrZXlfY2xhc3MuZnJvbV9wcml2YXRlX2tleV9maWxlKGZpbGVuYW1lLCBw
YXNzd29yZCkKKyAgICAgICAgICAgIHBhcmFtaWtvX3RyYW5zcG9ydC5hdXRoX3B1YmxpY2tleSh1
c2VybmFtZSwga2V5KQorICAgICAgICAgICAgcmV0dXJuIFRydWUKKyAgICAgICAgZXhjZXB0IHBh
cmFtaWtvLlNTSEV4Y2VwdGlvbjoKKyAgICAgICAgICAgIG11dHRlcignU1NIIGF1dGhlbnRpY2F0
aW9uIHZpYSAlcyBrZXkgZmFpbGVkLicgJSAob3MucGF0aC5iYXNlbmFtZShmaWxlbmFtZSksKSkK
KyAgICBleGNlcHQgcGFyYW1pa28uU1NIRXhjZXB0aW9uOgorICAgICAgICBtdXR0ZXIoJ1NTSCBh
dXRoZW50aWNhdGlvbiB2aWEgJXMga2V5IGZhaWxlZC4nICUgKG9zLnBhdGguYmFzZW5hbWUoZmls
ZW5hbWUpLCkpCisgICAgZXhjZXB0IElPRXJyb3I6CisgICAgICAgIHBhc3MKKyAgICByZXR1cm4g
RmFsc2UKKworCitkZWYgbG9hZF9ob3N0X2tleXMoKToKKyAgICAiIiIKKyAgICBMb2FkIHN5c3Rl
bSBob3N0IGtleXMgKHByb2JhYmx5IGRvZXNuJ3Qgd29yayBvbiB3aW5kb3dzKSBhbmQgYW55Cisg
ICAgImRpc2NvdmVyZWQiIGtleXMgZnJvbSBwcmV2aW91cyBzZXNzaW9ucy4KKyAgICAiIiIKKyAg
ICBnbG9iYWwgU1lTVEVNX0hPU1RLRVlTLCBCWlJfSE9TVEtFWVMKKyAgICB0cnk6CisgICAgICAg
IFNZU1RFTV9IT1NUS0VZUyA9IHBhcmFtaWtvLnV0aWwubG9hZF9ob3N0X2tleXMob3MucGF0aC5l
eHBhbmR1c2VyKCd+Ly5zc2gva25vd25faG9zdHMnKSkKKyAgICBleGNlcHQgRXhjZXB0aW9uLCBl
OgorICAgICAgICBtdXR0ZXIoJ2ZhaWxlZCB0byBsb2FkIHN5c3RlbSBob3N0IGtleXM6ICcgKyBz
dHIoZSkpCisgICAgYnpyX2hvc3RrZXlfcGF0aCA9IHBhdGhqb2luKGNvbmZpZ19kaXIoKSwgJ3Nz
aF9ob3N0X2tleXMnKQorICAgIHRyeToKKyAgICAgICAgQlpSX0hPU1RLRVlTID0gcGFyYW1pa28u
dXRpbC5sb2FkX2hvc3Rfa2V5cyhienJfaG9zdGtleV9wYXRoKQorICAgIGV4Y2VwdCBFeGNlcHRp
b24sIGU6CisgICAgICAgIG11dHRlcignZmFpbGVkIHRvIGxvYWQgYnpyIGhvc3Qga2V5czogJyAr
IHN0cihlKSkKKyAgICAgICAgc2F2ZV9ob3N0X2tleXMoKQorCisKK2RlZiBzYXZlX2hvc3Rfa2V5
cygpOgorICAgICIiIgorICAgIFNhdmUgImRpc2NvdmVyZWQiIGhvc3Qga2V5cyBpbiAkKGNvbmZp
Zykvc3NoX2hvc3Rfa2V5cy8uCisgICAgIiIiCisgICAgZ2xvYmFsIFNZU1RFTV9IT1NUS0VZUywg
QlpSX0hPU1RLRVlTCisgICAgYnpyX2hvc3RrZXlfcGF0aCA9IHBhdGhqb2luKGNvbmZpZ19kaXIo
KSwgJ3NzaF9ob3N0X2tleXMnKQorICAgIGVuc3VyZV9jb25maWdfZGlyX2V4aXN0cygpCisKKyAg
ICB0cnk6CisgICAgICAgIGYgPSBvcGVuKGJ6cl9ob3N0a2V5X3BhdGgsICd3JykKKyAgICAgICAg
Zi53cml0ZSgnIyBTU0ggaG9zdCBrZXlzIGNvbGxlY3RlZCBieSBienJcbicpCisgICAgICAgIGZv
ciBob3N0bmFtZSwga2V5cyBpbiBCWlJfSE9TVEtFWVMuaXRlcml0ZW1zKCk6CisgICAgICAgICAg
ICBmb3Iga2V5dHlwZSwga2V5IGluIGtleXMuaXRlcml0ZW1zKCk6CisgICAgICAgICAgICAgICAg
Zi53cml0ZSgnJXMgJXMgJXNcbicgJSAoaG9zdG5hbWUsIGtleXR5cGUsIGtleS5nZXRfYmFzZTY0
KCkpKQorICAgICAgICBmLmNsb3NlKCkKKyAgICBleGNlcHQgSU9FcnJvciwgZToKKyAgICAgICAg
bXV0dGVyKCdmYWlsZWQgdG8gc2F2ZSBienIgaG9zdCBrZXlzOiAnICsgc3RyKGUpKQorCisKCg==
=== modified file bzrlib/transport/sftp.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc2Z0cC5weQorKysgYnpybGliL3RyYW5zcG9ydC9zZnRwLnB5
CkBAIC00OCw2ICs0OCw3IEBACiAgICAgcmVnaXN0ZXJfdXJscGFyc2VfbmV0bG9jX3Byb3RvY29s
LAogICAgIFNlcnZlciwKICAgICBzcGxpdF91cmwsCisgICAgc3NoLAogICAgIFRyYW5zcG9ydCwK
ICAgICApCiBpbXBvcnQgYnpybGliLnVpCkBAIC0xMDcsMTIgKzEwOCw2IEBACiAjIGRvbid0IHVz
ZSBwcmVmZXRjaCB1bmxlc3MgcGFyYW1pa28gdmVyc2lvbiA+PSAxLjUuNSAodGhlcmUgd2VyZSBi
dWdzIGVhcmxpZXIpCiBfZGVmYXVsdF9kb19wcmVmZXRjaCA9IChfcGFyYW1pa29fdmVyc2lvbiA+
PSAoMSwgNSwgNSkpCiAKLSMgUGFyYW1pa28gMS41IHRyaWVzIHRvIG9wZW4gYSBzb2NrZXQuQUZf
VU5JWCBpbiBvcmRlciB0byBjb25uZWN0Ci0jIHRvIHNzaC1hZ2VudC4gVGhhdCBhdHRyaWJ1dGUg
ZG9lc24ndCBleGlzdCBvbiB3aW4zMiAoaXQgZG9lcyBpbiBjeWd3aW4pCi0jIHNvIHdlIGdldCBh
biBBdHRyaWJ1dGVFcnJvciBleGNlcHRpb24uIFNvIHdlIHdpbGwgbm90IHRyeSB0bwotIyBjb25u
ZWN0IHRvIGFuIGFnZW50IGlmIHdlIGFyZSBvbiB3aW4zMiBhbmQgdXNpbmcgUGFyYW1pa28gb2xk
ZXIgdGhhbiAxLjYKLV91c2Vfc3NoX2FnZW50ID0gKHN5cy5wbGF0Zm9ybSAhPSAnd2luMzInIG9y
IF9wYXJhbWlrb192ZXJzaW9uID49ICgxLCA2LCAwKSkKLQogCiBfc3NoX3ZlbmRvciA9IE5vbmUK
IGRlZiBfZ2V0X3NzaF92ZW5kb3IoKToKQEAgLTIwMyw3NyArMTk4LDEyIEBACiAgICAgICAgIHNl
bGYucHJvYy53YWl0KCkKIAogCi1jbGFzcyBMb29wYmFja1NGVFAob2JqZWN0KToKLSAgICAiIiJT
aW1wbGUgd3JhcHBlciBmb3IgYSBzb2NrZXQgdGhhdCBwcmV0ZW5kcyB0byBiZSBhIHBhcmFtaWtv
IENoYW5uZWwuIiIiCi0KLSAgICBkZWYgX19pbml0X18oc2VsZiwgc29jayk6Ci0gICAgICAgIHNl
bGYuX19zb2NrZXQgPSBzb2NrCi0gCi0gICAgZGVmIHNlbmQoc2VsZiwgZGF0YSk6Ci0gICAgICAg
IHJldHVybiBzZWxmLl9fc29ja2V0LnNlbmQoZGF0YSkKLQotICAgIGRlZiByZWN2KHNlbGYsIG4p
OgotICAgICAgICByZXR1cm4gc2VsZi5fX3NvY2tldC5yZWN2KG4pCi0KLSAgICBkZWYgcmVjdl9y
ZWFkeShzZWxmKToKLSAgICAgICAgcmV0dXJuIFRydWUKLQotICAgIGRlZiBjbG9zZShzZWxmKToK
LSAgICAgICAgc2VsZi5fX3NvY2tldC5jbG9zZSgpCi0KLQotU1lTVEVNX0hPU1RLRVlTID0ge30K
LUJaUl9IT1NUS0VZUyA9IHt9Ci0KLSMgVGhpcyBpcyBhIHdlYWtyZWYgZGljdGlvbmFyeSwgc28g
dGhhdCB3ZSBjYW4gcmV1c2UgY29ubmVjdGlvbnMKLSMgdGhhdCBhcmUgc3RpbGwgYWN0aXZlLiBM
b25nIHRlcm0sIGl0IG1pZ2h0IGJlIG5pY2UgdG8gaGF2ZSBzb21lCi0jIHNvcnQgb2YgZXhwaXJh
dGlvbiBwb2xpY3ksIHN1Y2ggYXMgZGlzY29ubmVjdCBpZiBpbmFjdGl2ZSBmb3IKLSMgWCBzZWNv
bmRzLiBCdXQgdGhhdCByZXF1aXJlcyBhIGxvdCBtb3JlIGZhbmNpbmVzcy4KLV9jb25uZWN0ZWRf
aG9zdHMgPSB3ZWFrcmVmLldlYWtWYWx1ZURpY3Rpb25hcnkoKQotCiBkZWYgY2xlYXJfY29ubmVj
dGlvbl9jYWNoZSgpOgogICAgICIiIlJlbW92ZSBhbGwgaG9zdHMgZnJvbSB0aGUgU0ZUUCBjb25u
ZWN0aW9uIGNhY2hlLgogCiAgICAgUHJpbWFyaWx5IHVzZWZ1bCBmb3IgdGVzdCBjYXNlcyB3YW50
aW5nIHRvIGZvcmNlIGdhcmJhZ2UgY29sbGVjdGlvbi4KICAgICAiIiIKLSAgICBfY29ubmVjdGVk
X2hvc3RzLmNsZWFyKCkKLQotCi1kZWYgbG9hZF9ob3N0X2tleXMoKToKLSAgICAiIiIKLSAgICBM
b2FkIHN5c3RlbSBob3N0IGtleXMgKHByb2JhYmx5IGRvZXNuJ3Qgd29yayBvbiB3aW5kb3dzKSBh
bmQgYW55Ci0gICAgImRpc2NvdmVyZWQiIGtleXMgZnJvbSBwcmV2aW91cyBzZXNzaW9ucy4KLSAg
ICAiIiIKLSAgICBnbG9iYWwgU1lTVEVNX0hPU1RLRVlTLCBCWlJfSE9TVEtFWVMKLSAgICB0cnk6
Ci0gICAgICAgIFNZU1RFTV9IT1NUS0VZUyA9IHBhcmFtaWtvLnV0aWwubG9hZF9ob3N0X2tleXMo
b3MucGF0aC5leHBhbmR1c2VyKCd+Ly5zc2gva25vd25faG9zdHMnKSkKLSAgICBleGNlcHQgRXhj
ZXB0aW9uLCBlOgotICAgICAgICBtdXR0ZXIoJ2ZhaWxlZCB0byBsb2FkIHN5c3RlbSBob3N0IGtl
eXM6ICcgKyBzdHIoZSkpCi0gICAgYnpyX2hvc3RrZXlfcGF0aCA9IHBhdGhqb2luKGNvbmZpZ19k
aXIoKSwgJ3NzaF9ob3N0X2tleXMnKQotICAgIHRyeToKLSAgICAgICAgQlpSX0hPU1RLRVlTID0g
cGFyYW1pa28udXRpbC5sb2FkX2hvc3Rfa2V5cyhienJfaG9zdGtleV9wYXRoKQotICAgIGV4Y2Vw
dCBFeGNlcHRpb24sIGU6Ci0gICAgICAgIG11dHRlcignZmFpbGVkIHRvIGxvYWQgYnpyIGhvc3Qg
a2V5czogJyArIHN0cihlKSkKLSAgICAgICAgc2F2ZV9ob3N0X2tleXMoKQotCi0KLWRlZiBzYXZl
X2hvc3Rfa2V5cygpOgotICAgICIiIgotICAgIFNhdmUgImRpc2NvdmVyZWQiIGhvc3Qga2V5cyBp
biAkKGNvbmZpZykvc3NoX2hvc3Rfa2V5cy8uCi0gICAgIiIiCi0gICAgZ2xvYmFsIFNZU1RFTV9I
T1NUS0VZUywgQlpSX0hPU1RLRVlTCi0gICAgYnpyX2hvc3RrZXlfcGF0aCA9IHBhdGhqb2luKGNv
bmZpZ19kaXIoKSwgJ3NzaF9ob3N0X2tleXMnKQotICAgIGVuc3VyZV9jb25maWdfZGlyX2V4aXN0
cygpCi0KLSAgICB0cnk6Ci0gICAgICAgIGYgPSBvcGVuKGJ6cl9ob3N0a2V5X3BhdGgsICd3JykK
LSAgICAgICAgZi53cml0ZSgnIyBTU0ggaG9zdCBrZXlzIGNvbGxlY3RlZCBieSBienJcbicpCi0g
ICAgICAgIGZvciBob3N0bmFtZSwga2V5cyBpbiBCWlJfSE9TVEtFWVMuaXRlcml0ZW1zKCk6Ci0g
ICAgICAgICAgICBmb3Iga2V5dHlwZSwga2V5IGluIGtleXMuaXRlcml0ZW1zKCk6Ci0gICAgICAg
ICAgICAgICAgZi53cml0ZSgnJXMgJXMgJXNcbicgJSAoaG9zdG5hbWUsIGtleXR5cGUsIGtleS5n
ZXRfYmFzZTY0KCkpKQotICAgICAgICBmLmNsb3NlKCkKLSAgICBleGNlcHQgSU9FcnJvciwgZToK
LSAgICAgICAgbXV0dGVyKCdmYWlsZWQgdG8gc2F2ZSBienIgaG9zdCBrZXlzOiAnICsgc3RyKGUp
KQorICAgIHNzaC5fY29ubmVjdGVkX2hvc3RzLmNsZWFyKCkKIAogCiBjbGFzcyBTRlRQTG9jayhv
YmplY3QpOgpAQCAtMTE1NSwxNTUgKzEwODUsNDQgQEAKIAogICAgIFRPRE86IFJhaXNlIGEgbW9y
ZSByZWFzb25hYmxlIENvbm5lY3Rpb25GYWlsZWQgZXhjZXB0aW9uCiAgICAgIiIiCi0gICAgZ2xv
YmFsIF9jb25uZWN0ZWRfaG9zdHMKLQogICAgIGlkeCA9IChob3N0LCBwb3J0LCB1c2VybmFtZSkK
ICAgICB0cnk6Ci0gICAgICAgIHJldHVybiBfY29ubmVjdGVkX2hvc3RzW2lkeF0KKyAgICAgICAg
cmV0dXJuIHNzaC5fY29ubmVjdGVkX2hvc3RzW2lkeF0KICAgICBleGNlcHQgS2V5RXJyb3I6CiAg
ICAgICAgIHBhc3MKICAgICAKKyAgICBzZnRwID0gX3NmdHBfY29ubmVjdF91bmNhY2hlZChob3N0
LCBwb3J0LCB1c2VybmFtZSwgcGFzc3dvcmQpCisgICAgc3NoLl9jb25uZWN0ZWRfaG9zdHNbaWR4
XSA9IHNmdHAKKyAgICByZXR1cm4gc2Z0cAorCitkZWYgX3NmdHBfY29ubmVjdF91bmNhY2hlZCho
b3N0LCBwb3J0LCB1c2VybmFtZSwgcGFzc3dvcmQpOgogICAgIHZlbmRvciA9IF9nZXRfc3NoX3Zl
bmRvcigpCiAgICAgaWYgdmVuZG9yID09ICdsb29wYmFjayc6Ci0gICAgICAgIHNvY2sgPSBzb2Nr
ZXQuc29ja2V0KCkKLSAgICAgICAgdHJ5OgotICAgICAgICAgICAgc29jay5jb25uZWN0KChob3N0
LCBwb3J0KSkKLSAgICAgICAgZXhjZXB0IHNvY2tldC5lcnJvciwgZToKLSAgICAgICAgICAgIHJh
aXNlIENvbm5lY3Rpb25FcnJvcignVW5hYmxlIHRvIGNvbm5lY3QgdG8gU1NIIGhvc3QgJXM6JXM6
ICVzJwotICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICUgKGhvc3QsIHBvcnQsIGUp
KQotICAgICAgICBzZnRwID0gU0ZUUENsaWVudChMb29wYmFja1NGVFAoc29jaykpCisgICAgICAg
IHNmdHAgPSBzc2guTG9vcGJhY2tWZW5kb3IoKS5jb25uZWN0X3NmdHAodXNlcm5hbWUsIHBhc3N3
b3JkLCBob3N0LCBwb3J0KQogICAgIGVsaWYgdmVuZG9yID09ICdub25lJzoKLSAgICAgICAgc2Z0
cCA9IF9wYXJhbWlrb19jb25uZWN0KHVzZXJuYW1lLCBwYXNzd29yZCwgaG9zdCwgcG9ydCkKLSAg
ICBlbHNlOgotICAgICAgICB0cnk6Ci0gICAgICAgICAgICBzb2NrID0gU0ZUUFN1YnByb2Nlc3Mo
aG9zdCwgdmVuZG9yLCBwb3J0LCB1c2VybmFtZSkKLSAgICAgICAgICAgIHNmdHAgPSBTRlRQQ2xp
ZW50KHNvY2spCi0gICAgICAgIGV4Y2VwdCAoRU9GRXJyb3IsIHBhcmFtaWtvLlNTSEV4Y2VwdGlv
biksIGU6Ci0gICAgICAgICAgICByYWlzZSBDb25uZWN0aW9uRXJyb3IoJ1VuYWJsZSB0byBjb25u
ZWN0IHRvIFNTSCBob3N0ICVzOiVzOiAlcycKLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAlIChob3N0LCBwb3J0LCBlKSkKLSAgICAgICAgZXhjZXB0IChPU0Vycm9yLCBJT0Vycm9y
KSwgZToKLSAgICAgICAgICAgICMgSWYgdGhlIG1hY2hpbmUgaXMgZmFzdCBlbm91Z2gsIHNzaCBj
YW4gYWN0dWFsbHkgZXhpdAotICAgICAgICAgICAgIyBiZWZvcmUgd2UgdHJ5IGFuZCBzZW5kIGl0
IHRoZSBzZnRwIHJlcXVlc3QsIHdoaWNoCi0gICAgICAgICAgICAjIHJhaXNlcyBhIEJyb2tlbiBQ
aXBlCi0gICAgICAgICAgICBpZiBlLmVycm5vIG5vdCBpbiAoZXJybm8uRVBJUEUsKToKLSAgICAg
ICAgICAgICAgICByYWlzZQotICAgICAgICAgICAgcmFpc2UgQ29ubmVjdGlvbkVycm9yKCdVbmFi
bGUgdG8gY29ubmVjdCB0byBTU0ggaG9zdCAlczolczogJXMnCi0gICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgJSAoaG9zdCwgcG9ydCwgZSkpCi0KLSAgICBfY29ubmVjdGVkX2hvc3Rz
W2lkeF0gPSBzZnRwCi0gICAgcmV0dXJuIHNmdHAKLQotCi1kZWYgX3RyeV9wa2V5X2F1dGgocGFy
YW1pa29fdHJhbnNwb3J0LCBwa2V5X2NsYXNzLCB1c2VybmFtZSwgZmlsZW5hbWUpOgotICAgIGZp
bGVuYW1lID0gb3MucGF0aC5leHBhbmR1c2VyKCd+Ly5zc2gvJyArIGZpbGVuYW1lKQotICAgIHRy
eToKLSAgICAgICAga2V5ID0gcGtleV9jbGFzcy5mcm9tX3ByaXZhdGVfa2V5X2ZpbGUoZmlsZW5h
bWUpCi0gICAgICAgIHBhcmFtaWtvX3RyYW5zcG9ydC5hdXRoX3B1YmxpY2tleSh1c2VybmFtZSwg
a2V5KQotICAgICAgICByZXR1cm4gVHJ1ZQotICAgIGV4Y2VwdCBwYXJhbWlrby5QYXNzd29yZFJl
cXVpcmVkRXhjZXB0aW9uOgotICAgICAgICBwYXNzd29yZCA9IGJ6cmxpYi51aS51aV9mYWN0b3J5
LmdldF9wYXNzd29yZCgKLSAgICAgICAgICAgICAgICBwcm9tcHQ9J1NTSCAlKGZpbGVuYW1lKXMg
cGFzc3dvcmQnLAotICAgICAgICAgICAgICAgIGZpbGVuYW1lPWZpbGVuYW1lKQotICAgICAgICB0
cnk6Ci0gICAgICAgICAgICBrZXkgPSBwa2V5X2NsYXNzLmZyb21fcHJpdmF0ZV9rZXlfZmlsZShm
aWxlbmFtZSwgcGFzc3dvcmQpCi0gICAgICAgICAgICBwYXJhbWlrb190cmFuc3BvcnQuYXV0aF9w
dWJsaWNrZXkodXNlcm5hbWUsIGtleSkKLSAgICAgICAgICAgIHJldHVybiBUcnVlCi0gICAgICAg
IGV4Y2VwdCBwYXJhbWlrby5TU0hFeGNlcHRpb246Ci0gICAgICAgICAgICBtdXR0ZXIoJ1NTSCBh
dXRoZW50aWNhdGlvbiB2aWEgJXMga2V5IGZhaWxlZC4nICUgKG9zLnBhdGguYmFzZW5hbWUoZmls
ZW5hbWUpLCkpCi0gICAgZXhjZXB0IHBhcmFtaWtvLlNTSEV4Y2VwdGlvbjoKLSAgICAgICAgbXV0
dGVyKCdTU0ggYXV0aGVudGljYXRpb24gdmlhICVzIGtleSBmYWlsZWQuJyAlIChvcy5wYXRoLmJh
c2VuYW1lKGZpbGVuYW1lKSwpKQotICAgIGV4Y2VwdCBJT0Vycm9yOgotICAgICAgICBwYXNzCi0g
ICAgcmV0dXJuIEZhbHNlCi0KLWRlZiBfcGFyYW1pa29fYXV0aCh1c2VybmFtZSwgcGFzc3dvcmQs
IGhvc3QsIHBhcmFtaWtvX3RyYW5zcG9ydCk6Ci0gICAgIyBwYXJhbWlrbyByZXF1aXJlcyBhIHVz
ZXJuYW1lLCBidXQgaXQgbWlnaHQgYmUgbm9uZSBpZiBub3RoaW5nIHdhcyBzdXBwbGllZAotICAg
ICMgdXNlIHRoZSBsb2NhbCB1c2VybmFtZSwganVzdCBpbiBjYXNlLgotICAgICMgV2UgZG9uJ3Qg
b3ZlcnJpZGUgdXNlcm5hbWUsIGJlY2F1c2UgaWYgd2UgYXJlbid0IHVzaW5nIHBhcmFtaWtvLAot
ICAgICMgdGhlIHVzZXJuYW1lIG1pZ2h0IGJlIHNwZWNpZmllZCBpbiB+Ly5zc2gvY29uZmlnIGFu
ZCB3ZSBkb24ndCB3YW50IHRvCi0gICAgIyBmb3JjZSBpdCB0byBzb21ldGhpbmcgZWxzZQotICAg
ICMgQWxzbywgaXQgd291bGQgbWVzcyB1cCB0aGUgc2VsZi5yZWxwYXRoKCkgZnVuY3Rpb25hbGl0
eQotICAgIHVzZXJuYW1lID0gdXNlcm5hbWUgb3IgZ2V0cGFzcy5nZXR1c2VyKCkKLQotICAgIGlm
IF91c2Vfc3NoX2FnZW50OgotICAgICAgICBhZ2VudCA9IHBhcmFtaWtvLkFnZW50KCkKLSAgICAg
ICAgZm9yIGtleSBpbiBhZ2VudC5nZXRfa2V5cygpOgotICAgICAgICAgICAgbXV0dGVyKCdUcnlp
bmcgU1NIIGFnZW50IGtleSAlcycgJSBwYXJhbWlrby51dGlsLmhleGlmeShrZXkuZ2V0X2Zpbmdl
cnByaW50KCkpKQotICAgICAgICAgICAgdHJ5OgotICAgICAgICAgICAgICAgIHBhcmFtaWtvX3Ry
YW5zcG9ydC5hdXRoX3B1YmxpY2tleSh1c2VybmFtZSwga2V5KQotICAgICAgICAgICAgICAgIHJl
dHVybgotICAgICAgICAgICAgZXhjZXB0IHBhcmFtaWtvLlNTSEV4Y2VwdGlvbiwgZToKLSAgICAg
ICAgICAgICAgICBwYXNzCi0gICAgCi0gICAgIyBva2F5LCB0cnkgZmluZGluZyBpZF9yc2Egb3Ig
aWRfZHNzPyAgKHBvc2l4IG9ubHkpCi0gICAgaWYgX3RyeV9wa2V5X2F1dGgocGFyYW1pa29fdHJh
bnNwb3J0LCBwYXJhbWlrby5SU0FLZXksIHVzZXJuYW1lLCAnaWRfcnNhJyk6Ci0gICAgICAgIHJl
dHVybgotICAgIGlmIF90cnlfcGtleV9hdXRoKHBhcmFtaWtvX3RyYW5zcG9ydCwgcGFyYW1pa28u
RFNTS2V5LCB1c2VybmFtZSwgJ2lkX2RzYScpOgotICAgICAgICByZXR1cm4KLQotICAgIGlmIHBh
c3N3b3JkOgotICAgICAgICB0cnk6Ci0gICAgICAgICAgICBwYXJhbWlrb190cmFuc3BvcnQuYXV0
aF9wYXNzd29yZCh1c2VybmFtZSwgcGFzc3dvcmQpCi0gICAgICAgICAgICByZXR1cm4KLSAgICAg
ICAgZXhjZXB0IHBhcmFtaWtvLlNTSEV4Y2VwdGlvbiwgZToKLSAgICAgICAgICAgIHBhc3MKLQot
ICAgICMgZ2l2ZSB1cCBhbmQgYXNrIGZvciBhIHBhc3N3b3JkCi0gICAgcGFzc3dvcmQgPSBienJs
aWIudWkudWlfZmFjdG9yeS5nZXRfcGFzc3dvcmQoCi0gICAgICAgICAgICBwcm9tcHQ9J1NTSCAl
KHVzZXIpc0AlKGhvc3QpcyBwYXNzd29yZCcsCi0gICAgICAgICAgICB1c2VyPXVzZXJuYW1lLCBo
b3N0PWhvc3QpCi0gICAgdHJ5OgotICAgICAgICBwYXJhbWlrb190cmFuc3BvcnQuYXV0aF9wYXNz
d29yZCh1c2VybmFtZSwgcGFzc3dvcmQpCi0gICAgZXhjZXB0IHBhcmFtaWtvLlNTSEV4Y2VwdGlv
biwgZToKLSAgICAgICAgcmFpc2UgQ29ubmVjdGlvbkVycm9yKCdVbmFibGUgdG8gYXV0aGVudGlj
YXRlIHRvIFNTSCBob3N0IGFzICVzQCVzJyAlCi0gICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAodXNlcm5hbWUsIGhvc3QpLCBlKQotCi0KLWRlZiBfcGFyYW1pa29fY29ubmVjdCh1c2VybmFt
ZSwgcGFzc3dvcmQsIGhvc3QsIHBvcnQpOgotICAgIGdsb2JhbCBTWVNURU1fSE9TVEtFWVMsIEJa
Ul9IT1NUS0VZUwotICAgIAotICAgIGxvYWRfaG9zdF9rZXlzKCkKLQotICAgIHRyeToKLSAgICAg
ICAgdCA9IHBhcmFtaWtvLlRyYW5zcG9ydCgoaG9zdCwgcG9ydCBvciAyMikpCi0gICAgICAgIHQu
c2V0X2xvZ19jaGFubmVsKCdienIucGFyYW1pa28nKQotICAgICAgICB0LnN0YXJ0X2NsaWVudCgp
Ci0gICAgZXhjZXB0IChwYXJhbWlrby5TU0hFeGNlcHRpb24sIHNvY2tldC5lcnJvciksIGU6Ci0g
ICAgICAgIHJhaXNlIENvbm5lY3Rpb25FcnJvcignVW5hYmxlIHRvIHJlYWNoIFNTSCBob3N0ICVz
OiVzOiAlcycgCi0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAlIChob3N0LCBwb3J0LCBl
KSkKLSAgICAgICAgCi0gICAgc2VydmVyX2tleSA9IHQuZ2V0X3JlbW90ZV9zZXJ2ZXJfa2V5KCkK
LSAgICBzZXJ2ZXJfa2V5X2hleCA9IHBhcmFtaWtvLnV0aWwuaGV4aWZ5KHNlcnZlcl9rZXkuZ2V0
X2ZpbmdlcnByaW50KCkpCi0gICAga2V5dHlwZSA9IHNlcnZlcl9rZXkuZ2V0X25hbWUoKQotICAg
IGlmIFNZU1RFTV9IT1NUS0VZUy5oYXNfa2V5KGhvc3QpIGFuZCBTWVNURU1fSE9TVEtFWVNbaG9z
dF0uaGFzX2tleShrZXl0eXBlKToKLSAgICAgICAgb3VyX3NlcnZlcl9rZXkgPSBTWVNURU1fSE9T
VEtFWVNbaG9zdF1ba2V5dHlwZV0KLSAgICAgICAgb3VyX3NlcnZlcl9rZXlfaGV4ID0gcGFyYW1p
a28udXRpbC5oZXhpZnkob3VyX3NlcnZlcl9rZXkuZ2V0X2ZpbmdlcnByaW50KCkpCi0gICAgZWxp
ZiBCWlJfSE9TVEtFWVMuaGFzX2tleShob3N0KSBhbmQgQlpSX0hPU1RLRVlTW2hvc3RdLmhhc19r
ZXkoa2V5dHlwZSk6Ci0gICAgICAgIG91cl9zZXJ2ZXJfa2V5ID0gQlpSX0hPU1RLRVlTW2hvc3Rd
W2tleXR5cGVdCi0gICAgICAgIG91cl9zZXJ2ZXJfa2V5X2hleCA9IHBhcmFtaWtvLnV0aWwuaGV4
aWZ5KG91cl9zZXJ2ZXJfa2V5LmdldF9maW5nZXJwcmludCgpKQotICAgIGVsc2U6Ci0gICAgICAg
IHdhcm5pbmcoJ0FkZGluZyAlcyBob3N0IGtleSBmb3IgJXM6ICVzJyAlIChrZXl0eXBlLCBob3N0
LCBzZXJ2ZXJfa2V5X2hleCkpCi0gICAgICAgIGlmIG5vdCBCWlJfSE9TVEtFWVMuaGFzX2tleSho
b3N0KToKLSAgICAgICAgICAgIEJaUl9IT1NUS0VZU1tob3N0XSA9IHt9Ci0gICAgICAgIEJaUl9I
T1NUS0VZU1tob3N0XVtrZXl0eXBlXSA9IHNlcnZlcl9rZXkKLSAgICAgICAgb3VyX3NlcnZlcl9r
ZXkgPSBzZXJ2ZXJfa2V5Ci0gICAgICAgIG91cl9zZXJ2ZXJfa2V5X2hleCA9IHBhcmFtaWtvLnV0
aWwuaGV4aWZ5KG91cl9zZXJ2ZXJfa2V5LmdldF9maW5nZXJwcmludCgpKQotICAgICAgICBzYXZl
X2hvc3Rfa2V5cygpCi0gICAgaWYgc2VydmVyX2tleSAhPSBvdXJfc2VydmVyX2tleToKLSAgICAg
ICAgZmlsZW5hbWUxID0gb3MucGF0aC5leHBhbmR1c2VyKCd+Ly5zc2gva25vd25faG9zdHMnKQot
ICAgICAgICBmaWxlbmFtZTIgPSBwYXRoam9pbihjb25maWdfZGlyKCksICdzc2hfaG9zdF9rZXlz
JykKLSAgICAgICAgcmFpc2UgVHJhbnNwb3J0RXJyb3IoJ0hvc3Qga2V5cyBmb3IgJXMgZG8gbm90
IG1hdGNoISAgJXMgIT0gJXMnICUgXAotICAgICAgICAgICAgKGhvc3QsIG91cl9zZXJ2ZXJfa2V5
X2hleCwgc2VydmVyX2tleV9oZXgpLAotICAgICAgICAgICAgWydUcnkgZWRpdGluZyAlcyBvciAl
cycgJSAoZmlsZW5hbWUxLCBmaWxlbmFtZTIpXSkKLQotICAgIF9wYXJhbWlrb19hdXRoKHVzZXJu
YW1lLCBwYXNzd29yZCwgaG9zdCwgdCkKLSAgICAKLSAgICB0cnk6Ci0gICAgICAgIHNmdHAgPSB0
Lm9wZW5fc2Z0cF9jbGllbnQoKQotICAgIGV4Y2VwdCBwYXJhbWlrby5TU0hFeGNlcHRpb24sIGU6
Ci0gICAgICAgIHJhaXNlIENvbm5lY3Rpb25FcnJvcignVW5hYmxlIHRvIHN0YXJ0IHNmdHAgY2xp
ZW50ICVzOiVkJyAlCi0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoaG9zdCwgcG9ydCks
IGUpCi0gICAgcmV0dXJuIHNmdHAKKyAgICAgICAgc2Z0cCA9IHNzaC5QYXJhbWlrb1ZlbmRvcigp
LmNvbm5lY3Rfc2Z0cCh1c2VybmFtZSwgcGFzc3dvcmQsIGhvc3QsIHBvcnQpCisgICAgZWxzZToK
KyAgICAgICAgc2Z0cCA9IF9zdWJwcm9jZXNzX2Nvbm5lY3Rfc2Z0cCh1c2VybmFtZSwgcGFzc3dv
cmQsIGhvc3QsIHBvcnQsIHZlbmRvcikKKyAgICByZXR1cm4gc2Z0cAorCitkZWYgX3N1YnByb2Nl
c3NfY29ubmVjdF9zZnRwKHVzZXJuYW1lLCBwYXNzd29yZCwgaG9zdCwgcG9ydCwgdmVuZG9yKToK
KyAgICB0cnk6CisgICAgICAgIHNvY2sgPSBTRlRQU3VicHJvY2Vzcyhob3N0LCB2ZW5kb3IsIHBv
cnQsIHVzZXJuYW1lKQorICAgICAgICBzZnRwID0gU0ZUUENsaWVudChzb2NrKQorICAgIGV4Y2Vw
dCAoRU9GRXJyb3IsIHBhcmFtaWtvLlNTSEV4Y2VwdGlvbiksIGU6CisgICAgICAgIHJhaXNlIENv
bm5lY3Rpb25FcnJvcignVW5hYmxlIHRvIGNvbm5lY3QgdG8gU1NIIGhvc3QgJXM6JXM6ICVzJwor
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJSAoaG9zdCwgcG9ydCwgZSkpCisgICAgZXhj
ZXB0IChPU0Vycm9yLCBJT0Vycm9yKSwgZToKKyAgICAgICAgIyBJZiB0aGUgbWFjaGluZSBpcyBm
YXN0IGVub3VnaCwgc3NoIGNhbiBhY3R1YWxseSBleGl0CisgICAgICAgICMgYmVmb3JlIHdlIHRy
eSBhbmQgc2VuZCBpdCB0aGUgc2Z0cCByZXF1ZXN0LCB3aGljaAorICAgICAgICAjIHJhaXNlcyBh
IEJyb2tlbiBQaXBlCisgICAgICAgIGlmIGUuZXJybm8gbm90IGluIChlcnJuby5FUElQRSwpOgor
ICAgICAgICAgICAgcmFpc2UKKyAgICAgICAgcmFpc2UgQ29ubmVjdGlvbkVycm9yKCdVbmFibGUg
dG8gY29ubmVjdCB0byBTU0ggaG9zdCAlczolczogJXMnCisgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAlIChob3N0LCBwb3J0LCBlKSkKKyAgICByZXR1cm4gc2Z0cAorCisKIAogCiBkZWYg
Z2V0X3Rlc3RfcGVybXV0YXRpb25zKCk6Cgo=
# revision id: andrew.bennetts at canonical.com-20060824042240-58a184f25a126261
# sha1: 46d30215a97afa4fd65069fbb90c47534e04d4a9
# inventory sha1: 2655cbeba83ed5b16aa118919e7a245d421b9c14
# parent ids:
# andrew.bennetts at canonical.com-20060824033831-b68b13229677e409
# properties:
# branch-nick: sftp refactoring 2
# message:
# Move paramiko connection code out of SFTPTransport.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Thu 2006-08-24 13:38:31.109999895 +1000
=== modified file bzrlib/transport/sftp.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc2Z0cC5weQorKysgYnpybGliL3RyYW5zcG9ydC9zZnRwLnB5
CkBAIC04MTIsMTU2ICs4MTIsOCBAQAogCiAgICAgICAgIFRPRE86IFJhaXNlIGEgbW9yZSByZWFz
b25hYmxlIENvbm5lY3Rpb25GYWlsZWQgZXhjZXB0aW9uCiAgICAgICAgICIiIgotICAgICAgICBn
bG9iYWwgX2Nvbm5lY3RlZF9ob3N0cwotCi0gICAgICAgIGlkeCA9IChzZWxmLl9ob3N0LCBzZWxm
Ll9wb3J0LCBzZWxmLl91c2VybmFtZSkKLSAgICAgICAgdHJ5OgotICAgICAgICAgICAgc2VsZi5f
c2Z0cCA9IF9jb25uZWN0ZWRfaG9zdHNbaWR4XQotICAgICAgICAgICAgcmV0dXJuCi0gICAgICAg
IGV4Y2VwdCBLZXlFcnJvcjoKLSAgICAgICAgICAgIHBhc3MKLSAgICAgICAgCi0gICAgICAgIHZl
bmRvciA9IF9nZXRfc3NoX3ZlbmRvcigpCi0gICAgICAgIGlmIHZlbmRvciA9PSAnbG9vcGJhY2sn
OgotICAgICAgICAgICAgc29jayA9IHNvY2tldC5zb2NrZXQoKQotICAgICAgICAgICAgdHJ5Ogot
ICAgICAgICAgICAgICAgIHNvY2suY29ubmVjdCgoc2VsZi5faG9zdCwgc2VsZi5fcG9ydCkpCi0g
ICAgICAgICAgICBleGNlcHQgc29ja2V0LmVycm9yLCBlOgotICAgICAgICAgICAgICAgIHJhaXNl
IENvbm5lY3Rpb25FcnJvcignVW5hYmxlIHRvIGNvbm5lY3QgdG8gU1NIIGhvc3QgJXM6JXM6ICVz
JwotICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAlIChzZWxmLl9ob3N0LCBz
ZWxmLl9wb3J0LCBlKSkKLSAgICAgICAgICAgIHNlbGYuX3NmdHAgPSBTRlRQQ2xpZW50KExvb3Bi
YWNrU0ZUUChzb2NrKSkKLSAgICAgICAgZWxpZiB2ZW5kb3IgIT0gJ25vbmUnOgotICAgICAgICAg
ICAgdHJ5OgotICAgICAgICAgICAgICAgIHNvY2sgPSBTRlRQU3VicHJvY2VzcyhzZWxmLl9ob3N0
LCB2ZW5kb3IsIHNlbGYuX3BvcnQsCi0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIHNlbGYuX3VzZXJuYW1lKQotICAgICAgICAgICAgICAgIHNlbGYuX3NmdHAgPSBTRlRQQ2xp
ZW50KHNvY2spCi0gICAgICAgICAgICBleGNlcHQgKEVPRkVycm9yLCBwYXJhbWlrby5TU0hFeGNl
cHRpb24pLCBlOgotICAgICAgICAgICAgICAgIHJhaXNlIENvbm5lY3Rpb25FcnJvcignVW5hYmxl
IHRvIGNvbm5lY3QgdG8gU1NIIGhvc3QgJXM6JXM6ICVzJwotICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAlIChzZWxmLl9ob3N0LCBzZWxmLl9wb3J0LCBlKSkKLSAgICAgICAg
ICAgIGV4Y2VwdCAoT1NFcnJvciwgSU9FcnJvciksIGU6Ci0gICAgICAgICAgICAgICAgIyBJZiB0
aGUgbWFjaGluZSBpcyBmYXN0IGVub3VnaCwgc3NoIGNhbiBhY3R1YWxseSBleGl0Ci0gICAgICAg
ICAgICAgICAgIyBiZWZvcmUgd2UgdHJ5IGFuZCBzZW5kIGl0IHRoZSBzZnRwIHJlcXVlc3QsIHdo
aWNoCi0gICAgICAgICAgICAgICAgIyByYWlzZXMgYSBCcm9rZW4gUGlwZQotICAgICAgICAgICAg
ICAgIGlmIGUuZXJybm8gbm90IGluIChlcnJuby5FUElQRSwpOgotICAgICAgICAgICAgICAgICAg
ICByYWlzZQotICAgICAgICAgICAgICAgIHJhaXNlIENvbm5lY3Rpb25FcnJvcignVW5hYmxlIHRv
IGNvbm5lY3QgdG8gU1NIIGhvc3QgJXM6JXM6ICVzJwotICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAlIChzZWxmLl9ob3N0LCBzZWxmLl9wb3J0LCBlKSkKLSAgICAgICAgZWxz
ZToKLSAgICAgICAgICAgIHNlbGYuX3BhcmFtaWtvX2Nvbm5lY3QoKQotCi0gICAgICAgIF9jb25u
ZWN0ZWRfaG9zdHNbaWR4XSA9IHNlbGYuX3NmdHAKLQotICAgIGRlZiBfcGFyYW1pa29fY29ubmVj
dChzZWxmKToKLSAgICAgICAgZ2xvYmFsIFNZU1RFTV9IT1NUS0VZUywgQlpSX0hPU1RLRVlTCi0g
ICAgICAgIAotICAgICAgICBsb2FkX2hvc3Rfa2V5cygpCi0KLSAgICAgICAgdHJ5OgotICAgICAg
ICAgICAgdCA9IHBhcmFtaWtvLlRyYW5zcG9ydCgoc2VsZi5faG9zdCwgc2VsZi5fcG9ydCBvciAy
MikpCi0gICAgICAgICAgICB0LnNldF9sb2dfY2hhbm5lbCgnYnpyLnBhcmFtaWtvJykKLSAgICAg
ICAgICAgIHQuc3RhcnRfY2xpZW50KCkKLSAgICAgICAgZXhjZXB0IChwYXJhbWlrby5TU0hFeGNl
cHRpb24sIHNvY2tldC5lcnJvciksIGU6Ci0gICAgICAgICAgICByYWlzZSBDb25uZWN0aW9uRXJy
b3IoJ1VuYWJsZSB0byByZWFjaCBTU0ggaG9zdCAlczolczogJXMnIAotICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICUgKHNlbGYuX2hvc3QsIHNlbGYuX3BvcnQsIGUpKQotICAgICAg
ICAgICAgCi0gICAgICAgIHNlcnZlcl9rZXkgPSB0LmdldF9yZW1vdGVfc2VydmVyX2tleSgpCi0g
ICAgICAgIHNlcnZlcl9rZXlfaGV4ID0gcGFyYW1pa28udXRpbC5oZXhpZnkoc2VydmVyX2tleS5n
ZXRfZmluZ2VycHJpbnQoKSkKLSAgICAgICAga2V5dHlwZSA9IHNlcnZlcl9rZXkuZ2V0X25hbWUo
KQotICAgICAgICBpZiBTWVNURU1fSE9TVEtFWVMuaGFzX2tleShzZWxmLl9ob3N0KSBhbmQgU1lT
VEVNX0hPU1RLRVlTW3NlbGYuX2hvc3RdLmhhc19rZXkoa2V5dHlwZSk6Ci0gICAgICAgICAgICBv
dXJfc2VydmVyX2tleSA9IFNZU1RFTV9IT1NUS0VZU1tzZWxmLl9ob3N0XVtrZXl0eXBlXQotICAg
ICAgICAgICAgb3VyX3NlcnZlcl9rZXlfaGV4ID0gcGFyYW1pa28udXRpbC5oZXhpZnkob3VyX3Nl
cnZlcl9rZXkuZ2V0X2ZpbmdlcnByaW50KCkpCi0gICAgICAgIGVsaWYgQlpSX0hPU1RLRVlTLmhh
c19rZXkoc2VsZi5faG9zdCkgYW5kIEJaUl9IT1NUS0VZU1tzZWxmLl9ob3N0XS5oYXNfa2V5KGtl
eXR5cGUpOgotICAgICAgICAgICAgb3VyX3NlcnZlcl9rZXkgPSBCWlJfSE9TVEtFWVNbc2VsZi5f
aG9zdF1ba2V5dHlwZV0KLSAgICAgICAgICAgIG91cl9zZXJ2ZXJfa2V5X2hleCA9IHBhcmFtaWtv
LnV0aWwuaGV4aWZ5KG91cl9zZXJ2ZXJfa2V5LmdldF9maW5nZXJwcmludCgpKQotICAgICAgICBl
bHNlOgotICAgICAgICAgICAgd2FybmluZygnQWRkaW5nICVzIGhvc3Qga2V5IGZvciAlczogJXMn
ICUgKGtleXR5cGUsIHNlbGYuX2hvc3QsIHNlcnZlcl9rZXlfaGV4KSkKLSAgICAgICAgICAgIGlm
IG5vdCBCWlJfSE9TVEtFWVMuaGFzX2tleShzZWxmLl9ob3N0KToKLSAgICAgICAgICAgICAgICBC
WlJfSE9TVEtFWVNbc2VsZi5faG9zdF0gPSB7fQotICAgICAgICAgICAgQlpSX0hPU1RLRVlTW3Nl
bGYuX2hvc3RdW2tleXR5cGVdID0gc2VydmVyX2tleQotICAgICAgICAgICAgb3VyX3NlcnZlcl9r
ZXkgPSBzZXJ2ZXJfa2V5Ci0gICAgICAgICAgICBvdXJfc2VydmVyX2tleV9oZXggPSBwYXJhbWlr
by51dGlsLmhleGlmeShvdXJfc2VydmVyX2tleS5nZXRfZmluZ2VycHJpbnQoKSkKLSAgICAgICAg
ICAgIHNhdmVfaG9zdF9rZXlzKCkKLSAgICAgICAgaWYgc2VydmVyX2tleSAhPSBvdXJfc2VydmVy
X2tleToKLSAgICAgICAgICAgIGZpbGVuYW1lMSA9IG9zLnBhdGguZXhwYW5kdXNlcignfi8uc3No
L2tub3duX2hvc3RzJykKLSAgICAgICAgICAgIGZpbGVuYW1lMiA9IHBhdGhqb2luKGNvbmZpZ19k
aXIoKSwgJ3NzaF9ob3N0X2tleXMnKQotICAgICAgICAgICAgcmFpc2UgVHJhbnNwb3J0RXJyb3Io
J0hvc3Qga2V5cyBmb3IgJXMgZG8gbm90IG1hdGNoISAgJXMgIT0gJXMnICUgXAotICAgICAgICAg
ICAgICAgIChzZWxmLl9ob3N0LCBvdXJfc2VydmVyX2tleV9oZXgsIHNlcnZlcl9rZXlfaGV4KSwK
LSAgICAgICAgICAgICAgICBbJ1RyeSBlZGl0aW5nICVzIG9yICVzJyAlIChmaWxlbmFtZTEsIGZp
bGVuYW1lMildKQotCi0gICAgICAgIHNlbGYuX3NmdHBfYXV0aCh0KQotICAgICAgICAKLSAgICAg
ICAgdHJ5OgotICAgICAgICAgICAgc2VsZi5fc2Z0cCA9IHQub3Blbl9zZnRwX2NsaWVudCgpCi0g
ICAgICAgIGV4Y2VwdCBwYXJhbWlrby5TU0hFeGNlcHRpb24sIGU6Ci0gICAgICAgICAgICByYWlz
ZSBDb25uZWN0aW9uRXJyb3IoJ1VuYWJsZSB0byBzdGFydCBzZnRwIGNsaWVudCAlczolZCcgJQot
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZWxmLl9ob3N0LCBzZWxmLl9wb3J0
KSwgZSkKLQotICAgIGRlZiBfc2Z0cF9hdXRoKHNlbGYsIHRyYW5zcG9ydCk6Ci0gICAgICAgICMg
cGFyYW1pa28gcmVxdWlyZXMgYSB1c2VybmFtZSwgYnV0IGl0IG1pZ2h0IGJlIG5vbmUgaWYgbm90
aGluZyB3YXMgc3VwcGxpZWQKLSAgICAgICAgIyB1c2UgdGhlIGxvY2FsIHVzZXJuYW1lLCBqdXN0
IGluIGNhc2UuCi0gICAgICAgICMgV2UgZG9uJ3Qgb3ZlcnJpZGUgc2VsZi5fdXNlcm5hbWUsIGJl
Y2F1c2UgaWYgd2UgYXJlbid0IHVzaW5nIHBhcmFtaWtvLAotICAgICAgICAjIHRoZSB1c2VybmFt
ZSBtaWdodCBiZSBzcGVjaWZpZWQgaW4gfi8uc3NoL2NvbmZpZyBhbmQgd2UgZG9uJ3Qgd2FudCB0
bwotICAgICAgICAjIGZvcmNlIGl0IHRvIHNvbWV0aGluZyBlbHNlCi0gICAgICAgICMgQWxzbywg
aXQgd291bGQgbWVzcyB1cCB0aGUgc2VsZi5yZWxwYXRoKCkgZnVuY3Rpb25hbGl0eQotICAgICAg
ICB1c2VybmFtZSA9IHNlbGYuX3VzZXJuYW1lIG9yIGdldHBhc3MuZ2V0dXNlcigpCi0KLSAgICAg
ICAgaWYgX3VzZV9zc2hfYWdlbnQ6Ci0gICAgICAgICAgICBhZ2VudCA9IHBhcmFtaWtvLkFnZW50
KCkKLSAgICAgICAgICAgIGZvciBrZXkgaW4gYWdlbnQuZ2V0X2tleXMoKToKLSAgICAgICAgICAg
ICAgICBtdXR0ZXIoJ1RyeWluZyBTU0ggYWdlbnQga2V5ICVzJyAlIHBhcmFtaWtvLnV0aWwuaGV4
aWZ5KGtleS5nZXRfZmluZ2VycHJpbnQoKSkpCi0gICAgICAgICAgICAgICAgdHJ5OgotICAgICAg
ICAgICAgICAgICAgICB0cmFuc3BvcnQuYXV0aF9wdWJsaWNrZXkodXNlcm5hbWUsIGtleSkKLSAg
ICAgICAgICAgICAgICAgICAgcmV0dXJuCi0gICAgICAgICAgICAgICAgZXhjZXB0IHBhcmFtaWtv
LlNTSEV4Y2VwdGlvbiwgZToKLSAgICAgICAgICAgICAgICAgICAgcGFzcwotICAgICAgICAKLSAg
ICAgICAgIyBva2F5LCB0cnkgZmluZGluZyBpZF9yc2Egb3IgaWRfZHNzPyAgKHBvc2l4IG9ubHkp
Ci0gICAgICAgIGlmIHNlbGYuX3RyeV9wa2V5X2F1dGgodHJhbnNwb3J0LCBwYXJhbWlrby5SU0FL
ZXksIHVzZXJuYW1lLCAnaWRfcnNhJyk6Ci0gICAgICAgICAgICByZXR1cm4KLSAgICAgICAgaWYg
c2VsZi5fdHJ5X3BrZXlfYXV0aCh0cmFuc3BvcnQsIHBhcmFtaWtvLkRTU0tleSwgdXNlcm5hbWUs
ICdpZF9kc2EnKToKLSAgICAgICAgICAgIHJldHVybgotCi0gICAgICAgIGlmIHNlbGYuX3Bhc3N3
b3JkOgotICAgICAgICAgICAgdHJ5OgotICAgICAgICAgICAgICAgIHRyYW5zcG9ydC5hdXRoX3Bh
c3N3b3JkKHVzZXJuYW1lLCBzZWxmLl9wYXNzd29yZCkKLSAgICAgICAgICAgICAgICByZXR1cm4K
LSAgICAgICAgICAgIGV4Y2VwdCBwYXJhbWlrby5TU0hFeGNlcHRpb24sIGU6Ci0gICAgICAgICAg
ICAgICAgcGFzcwotCi0gICAgICAgICAgICAjIEZJWE1FOiBEb24ndCBrZWVwIGEgcGFzc3dvcmQg
aGVsZCBpbiBtZW1vcnkgaWYgeW91IGNhbiBoZWxwIGl0Ci0gICAgICAgICAgICAjc2VsZi5fcGFz
c3dvcmQgPSBOb25lCi0KLSAgICAgICAgIyBnaXZlIHVwIGFuZCBhc2sgZm9yIGEgcGFzc3dvcmQK
LSAgICAgICAgcGFzc3dvcmQgPSBienJsaWIudWkudWlfZmFjdG9yeS5nZXRfcGFzc3dvcmQoCi0g
ICAgICAgICAgICAgICAgcHJvbXB0PSdTU0ggJSh1c2VyKXNAJShob3N0KXMgcGFzc3dvcmQnLAot
ICAgICAgICAgICAgICAgIHVzZXI9dXNlcm5hbWUsIGhvc3Q9c2VsZi5faG9zdCkKLSAgICAgICAg
dHJ5OgotICAgICAgICAgICAgdHJhbnNwb3J0LmF1dGhfcGFzc3dvcmQodXNlcm5hbWUsIHBhc3N3
b3JkKQotICAgICAgICBleGNlcHQgcGFyYW1pa28uU1NIRXhjZXB0aW9uLCBlOgotICAgICAgICAg
ICAgcmFpc2UgQ29ubmVjdGlvbkVycm9yKCdVbmFibGUgdG8gYXV0aGVudGljYXRlIHRvIFNTSCBo
b3N0IGFzICVzQCVzJyAlCi0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHVzZXJu
YW1lLCBzZWxmLl9ob3N0KSwgZSkKLQotICAgIGRlZiBfdHJ5X3BrZXlfYXV0aChzZWxmLCB0cmFu
c3BvcnQsIHBrZXlfY2xhc3MsIHVzZXJuYW1lLCBmaWxlbmFtZSk6Ci0gICAgICAgIGZpbGVuYW1l
ID0gb3MucGF0aC5leHBhbmR1c2VyKCd+Ly5zc2gvJyArIGZpbGVuYW1lKQotICAgICAgICB0cnk6
Ci0gICAgICAgICAgICBrZXkgPSBwa2V5X2NsYXNzLmZyb21fcHJpdmF0ZV9rZXlfZmlsZShmaWxl
bmFtZSkKLSAgICAgICAgICAgIHRyYW5zcG9ydC5hdXRoX3B1YmxpY2tleSh1c2VybmFtZSwga2V5
KQotICAgICAgICAgICAgcmV0dXJuIFRydWUKLSAgICAgICAgZXhjZXB0IHBhcmFtaWtvLlBhc3N3
b3JkUmVxdWlyZWRFeGNlcHRpb246Ci0gICAgICAgICAgICBwYXNzd29yZCA9IGJ6cmxpYi51aS51
aV9mYWN0b3J5LmdldF9wYXNzd29yZCgKLSAgICAgICAgICAgICAgICAgICAgcHJvbXB0PSdTU0gg
JShmaWxlbmFtZSlzIHBhc3N3b3JkJywKLSAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWU9Zmls
ZW5hbWUpCi0gICAgICAgICAgICB0cnk6Ci0gICAgICAgICAgICAgICAga2V5ID0gcGtleV9jbGFz
cy5mcm9tX3ByaXZhdGVfa2V5X2ZpbGUoZmlsZW5hbWUsIHBhc3N3b3JkKQotICAgICAgICAgICAg
ICAgIHRyYW5zcG9ydC5hdXRoX3B1YmxpY2tleSh1c2VybmFtZSwga2V5KQotICAgICAgICAgICAg
ICAgIHJldHVybiBUcnVlCi0gICAgICAgICAgICBleGNlcHQgcGFyYW1pa28uU1NIRXhjZXB0aW9u
OgotICAgICAgICAgICAgICAgIG11dHRlcignU1NIIGF1dGhlbnRpY2F0aW9uIHZpYSAlcyBrZXkg
ZmFpbGVkLicgJSAob3MucGF0aC5iYXNlbmFtZShmaWxlbmFtZSksKSkKLSAgICAgICAgZXhjZXB0
IHBhcmFtaWtvLlNTSEV4Y2VwdGlvbjoKLSAgICAgICAgICAgIG11dHRlcignU1NIIGF1dGhlbnRp
Y2F0aW9uIHZpYSAlcyBrZXkgZmFpbGVkLicgJSAob3MucGF0aC5iYXNlbmFtZShmaWxlbmFtZSks
KSkKLSAgICAgICAgZXhjZXB0IElPRXJyb3I6Ci0gICAgICAgICAgICBwYXNzCi0gICAgICAgIHJl
dHVybiBGYWxzZQorICAgICAgICBzZWxmLl9zZnRwID0gX3NmdHBfY29ubmVjdChzZWxmLl9ob3N0
LCBzZWxmLl9wb3J0LCBzZWxmLl91c2VybmFtZSwKKyAgICAgICAgICAgICAgICBzZWxmLl9wYXNz
d29yZCkKIAogICAgIGRlZiBfc2Z0cF9vcGVuX2V4Y2x1c2l2ZShzZWxmLCBhYnNwYXRoLCBtb2Rl
PU5vbmUpOgogICAgICAgICAiIiJPcGVuIGEgcmVtb3RlIHBhdGggZXhjbHVzaXZlbHkuCkBAIC0x
Mjk0LDYgKzExNDYsMTY2IEBACiAgICAgICAgIHN1cGVyKFNGVFBTaWJsaW5nQWJzb2x1dGVTZXJ2
ZXIsIHNlbGYpLnNldFVwKCkKIAogCitkZWYgX3NmdHBfY29ubmVjdChob3N0LCBwb3J0LCB1c2Vy
bmFtZSwgcGFzc3dvcmQpOgorICAgICIiIkNvbm5lY3QgdG8gdGhlIHJlbW90ZSBzZnRwIHNlcnZl
ci4KKworICAgIDpyYWlzZXM6IGEgVHJhbnNwb3J0RXJyb3IgJ2NvdWxkIG5vdCBjb25uZWN0Jy4K
KworICAgIDpyZXR1cm5zOiBhbiBTRlRQQ2xpZW50CisKKyAgICBUT0RPOiBSYWlzZSBhIG1vcmUg
cmVhc29uYWJsZSBDb25uZWN0aW9uRmFpbGVkIGV4Y2VwdGlvbgorICAgICIiIgorICAgIGdsb2Jh
bCBfY29ubmVjdGVkX2hvc3RzCisKKyAgICBpZHggPSAoaG9zdCwgcG9ydCwgdXNlcm5hbWUpCisg
ICAgdHJ5OgorICAgICAgICByZXR1cm4gX2Nvbm5lY3RlZF9ob3N0c1tpZHhdCisgICAgZXhjZXB0
IEtleUVycm9yOgorICAgICAgICBwYXNzCisgICAgCisgICAgdmVuZG9yID0gX2dldF9zc2hfdmVu
ZG9yKCkKKyAgICBpZiB2ZW5kb3IgPT0gJ2xvb3BiYWNrJzoKKyAgICAgICAgc29jayA9IHNvY2tl
dC5zb2NrZXQoKQorICAgICAgICB0cnk6CisgICAgICAgICAgICBzb2NrLmNvbm5lY3QoKGhvc3Qs
IHBvcnQpKQorICAgICAgICBleGNlcHQgc29ja2V0LmVycm9yLCBlOgorICAgICAgICAgICAgcmFp
c2UgQ29ubmVjdGlvbkVycm9yKCdVbmFibGUgdG8gY29ubmVjdCB0byBTU0ggaG9zdCAlczolczog
JXMnCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJSAoaG9zdCwgcG9ydCwgZSkp
CisgICAgICAgIHNmdHAgPSBTRlRQQ2xpZW50KExvb3BiYWNrU0ZUUChzb2NrKSkKKyAgICBlbGlm
IHZlbmRvciA9PSAnbm9uZSc6CisgICAgICAgIHNmdHAgPSBfcGFyYW1pa29fY29ubmVjdCh1c2Vy
bmFtZSwgcGFzc3dvcmQsIGhvc3QsIHBvcnQpCisgICAgZWxzZToKKyAgICAgICAgdHJ5OgorICAg
ICAgICAgICAgc29jayA9IFNGVFBTdWJwcm9jZXNzKGhvc3QsIHZlbmRvciwgcG9ydCwgdXNlcm5h
bWUpCisgICAgICAgICAgICBzZnRwID0gU0ZUUENsaWVudChzb2NrKQorICAgICAgICBleGNlcHQg
KEVPRkVycm9yLCBwYXJhbWlrby5TU0hFeGNlcHRpb24pLCBlOgorICAgICAgICAgICAgcmFpc2Ug
Q29ubmVjdGlvbkVycm9yKCdVbmFibGUgdG8gY29ubmVjdCB0byBTU0ggaG9zdCAlczolczogJXMn
CisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJSAoaG9zdCwgcG9ydCwgZSkpCisg
ICAgICAgIGV4Y2VwdCAoT1NFcnJvciwgSU9FcnJvciksIGU6CisgICAgICAgICAgICAjIElmIHRo
ZSBtYWNoaW5lIGlzIGZhc3QgZW5vdWdoLCBzc2ggY2FuIGFjdHVhbGx5IGV4aXQKKyAgICAgICAg
ICAgICMgYmVmb3JlIHdlIHRyeSBhbmQgc2VuZCBpdCB0aGUgc2Z0cCByZXF1ZXN0LCB3aGljaAor
ICAgICAgICAgICAgIyByYWlzZXMgYSBCcm9rZW4gUGlwZQorICAgICAgICAgICAgaWYgZS5lcnJu
byBub3QgaW4gKGVycm5vLkVQSVBFLCk6CisgICAgICAgICAgICAgICAgcmFpc2UKKyAgICAgICAg
ICAgIHJhaXNlIENvbm5lY3Rpb25FcnJvcignVW5hYmxlIHRvIGNvbm5lY3QgdG8gU1NIIGhvc3Qg
JXM6JXM6ICVzJworICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICUgKGhvc3QsIHBv
cnQsIGUpKQorCisgICAgX2Nvbm5lY3RlZF9ob3N0c1tpZHhdID0gc2Z0cAorICAgIHJldHVybiBz
ZnRwCisKKworZGVmIF90cnlfcGtleV9hdXRoKHBhcmFtaWtvX3RyYW5zcG9ydCwgcGtleV9jbGFz
cywgdXNlcm5hbWUsIGZpbGVuYW1lKToKKyAgICBmaWxlbmFtZSA9IG9zLnBhdGguZXhwYW5kdXNl
cignfi8uc3NoLycgKyBmaWxlbmFtZSkKKyAgICB0cnk6CisgICAgICAgIGtleSA9IHBrZXlfY2xh
c3MuZnJvbV9wcml2YXRlX2tleV9maWxlKGZpbGVuYW1lKQorICAgICAgICBwYXJhbWlrb190cmFu
c3BvcnQuYXV0aF9wdWJsaWNrZXkodXNlcm5hbWUsIGtleSkKKyAgICAgICAgcmV0dXJuIFRydWUK
KyAgICBleGNlcHQgcGFyYW1pa28uUGFzc3dvcmRSZXF1aXJlZEV4Y2VwdGlvbjoKKyAgICAgICAg
cGFzc3dvcmQgPSBienJsaWIudWkudWlfZmFjdG9yeS5nZXRfcGFzc3dvcmQoCisgICAgICAgICAg
ICAgICAgcHJvbXB0PSdTU0ggJShmaWxlbmFtZSlzIHBhc3N3b3JkJywKKyAgICAgICAgICAgICAg
ICBmaWxlbmFtZT1maWxlbmFtZSkKKyAgICAgICAgdHJ5OgorICAgICAgICAgICAga2V5ID0gcGtl
eV9jbGFzcy5mcm9tX3ByaXZhdGVfa2V5X2ZpbGUoZmlsZW5hbWUsIHBhc3N3b3JkKQorICAgICAg
ICAgICAgcGFyYW1pa29fdHJhbnNwb3J0LmF1dGhfcHVibGlja2V5KHVzZXJuYW1lLCBrZXkpCisg
ICAgICAgICAgICByZXR1cm4gVHJ1ZQorICAgICAgICBleGNlcHQgcGFyYW1pa28uU1NIRXhjZXB0
aW9uOgorICAgICAgICAgICAgbXV0dGVyKCdTU0ggYXV0aGVudGljYXRpb24gdmlhICVzIGtleSBm
YWlsZWQuJyAlIChvcy5wYXRoLmJhc2VuYW1lKGZpbGVuYW1lKSwpKQorICAgIGV4Y2VwdCBwYXJh
bWlrby5TU0hFeGNlcHRpb246CisgICAgICAgIG11dHRlcignU1NIIGF1dGhlbnRpY2F0aW9uIHZp
YSAlcyBrZXkgZmFpbGVkLicgJSAob3MucGF0aC5iYXNlbmFtZShmaWxlbmFtZSksKSkKKyAgICBl
eGNlcHQgSU9FcnJvcjoKKyAgICAgICAgcGFzcworICAgIHJldHVybiBGYWxzZQorCitkZWYgX3Bh
cmFtaWtvX2F1dGgodXNlcm5hbWUsIHBhc3N3b3JkLCBob3N0LCBwYXJhbWlrb190cmFuc3BvcnQp
OgorICAgICMgcGFyYW1pa28gcmVxdWlyZXMgYSB1c2VybmFtZSwgYnV0IGl0IG1pZ2h0IGJlIG5v
bmUgaWYgbm90aGluZyB3YXMgc3VwcGxpZWQKKyAgICAjIHVzZSB0aGUgbG9jYWwgdXNlcm5hbWUs
IGp1c3QgaW4gY2FzZS4KKyAgICAjIFdlIGRvbid0IG92ZXJyaWRlIHVzZXJuYW1lLCBiZWNhdXNl
IGlmIHdlIGFyZW4ndCB1c2luZyBwYXJhbWlrbywKKyAgICAjIHRoZSB1c2VybmFtZSBtaWdodCBi
ZSBzcGVjaWZpZWQgaW4gfi8uc3NoL2NvbmZpZyBhbmQgd2UgZG9uJ3Qgd2FudCB0bworICAgICMg
Zm9yY2UgaXQgdG8gc29tZXRoaW5nIGVsc2UKKyAgICAjIEFsc28sIGl0IHdvdWxkIG1lc3MgdXAg
dGhlIHNlbGYucmVscGF0aCgpIGZ1bmN0aW9uYWxpdHkKKyAgICB1c2VybmFtZSA9IHVzZXJuYW1l
IG9yIGdldHBhc3MuZ2V0dXNlcigpCisKKyAgICBpZiBfdXNlX3NzaF9hZ2VudDoKKyAgICAgICAg
YWdlbnQgPSBwYXJhbWlrby5BZ2VudCgpCisgICAgICAgIGZvciBrZXkgaW4gYWdlbnQuZ2V0X2tl
eXMoKToKKyAgICAgICAgICAgIG11dHRlcignVHJ5aW5nIFNTSCBhZ2VudCBrZXkgJXMnICUgcGFy
YW1pa28udXRpbC5oZXhpZnkoa2V5LmdldF9maW5nZXJwcmludCgpKSkKKyAgICAgICAgICAgIHRy
eToKKyAgICAgICAgICAgICAgICBwYXJhbWlrb190cmFuc3BvcnQuYXV0aF9wdWJsaWNrZXkodXNl
cm5hbWUsIGtleSkKKyAgICAgICAgICAgICAgICByZXR1cm4KKyAgICAgICAgICAgIGV4Y2VwdCBw
YXJhbWlrby5TU0hFeGNlcHRpb24sIGU6CisgICAgICAgICAgICAgICAgcGFzcworICAgIAorICAg
ICMgb2theSwgdHJ5IGZpbmRpbmcgaWRfcnNhIG9yIGlkX2Rzcz8gIChwb3NpeCBvbmx5KQorICAg
IGlmIF90cnlfcGtleV9hdXRoKHBhcmFtaWtvX3RyYW5zcG9ydCwgcGFyYW1pa28uUlNBS2V5LCB1
c2VybmFtZSwgJ2lkX3JzYScpOgorICAgICAgICByZXR1cm4KKyAgICBpZiBfdHJ5X3BrZXlfYXV0
aChwYXJhbWlrb190cmFuc3BvcnQsIHBhcmFtaWtvLkRTU0tleSwgdXNlcm5hbWUsICdpZF9kc2En
KToKKyAgICAgICAgcmV0dXJuCisKKyAgICBpZiBwYXNzd29yZDoKKyAgICAgICAgdHJ5OgorICAg
ICAgICAgICAgcGFyYW1pa29fdHJhbnNwb3J0LmF1dGhfcGFzc3dvcmQodXNlcm5hbWUsIHBhc3N3
b3JkKQorICAgICAgICAgICAgcmV0dXJuCisgICAgICAgIGV4Y2VwdCBwYXJhbWlrby5TU0hFeGNl
cHRpb24sIGU6CisgICAgICAgICAgICBwYXNzCisKKyAgICAjIGdpdmUgdXAgYW5kIGFzayBmb3Ig
YSBwYXNzd29yZAorICAgIHBhc3N3b3JkID0gYnpybGliLnVpLnVpX2ZhY3RvcnkuZ2V0X3Bhc3N3
b3JkKAorICAgICAgICAgICAgcHJvbXB0PSdTU0ggJSh1c2VyKXNAJShob3N0KXMgcGFzc3dvcmQn
LAorICAgICAgICAgICAgdXNlcj11c2VybmFtZSwgaG9zdD1ob3N0KQorICAgIHRyeToKKyAgICAg
ICAgcGFyYW1pa29fdHJhbnNwb3J0LmF1dGhfcGFzc3dvcmQodXNlcm5hbWUsIHBhc3N3b3JkKQor
ICAgIGV4Y2VwdCBwYXJhbWlrby5TU0hFeGNlcHRpb24sIGU6CisgICAgICAgIHJhaXNlIENvbm5l
Y3Rpb25FcnJvcignVW5hYmxlIHRvIGF1dGhlbnRpY2F0ZSB0byBTU0ggaG9zdCBhcyAlc0Alcycg
JQorICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHVzZXJuYW1lLCBob3N0KSwgZSkKKwor
CitkZWYgX3BhcmFtaWtvX2Nvbm5lY3QodXNlcm5hbWUsIHBhc3N3b3JkLCBob3N0LCBwb3J0KToK
KyAgICBnbG9iYWwgU1lTVEVNX0hPU1RLRVlTLCBCWlJfSE9TVEtFWVMKKyAgICAKKyAgICBsb2Fk
X2hvc3Rfa2V5cygpCisKKyAgICB0cnk6CisgICAgICAgIHQgPSBwYXJhbWlrby5UcmFuc3BvcnQo
KGhvc3QsIHBvcnQgb3IgMjIpKQorICAgICAgICB0LnNldF9sb2dfY2hhbm5lbCgnYnpyLnBhcmFt
aWtvJykKKyAgICAgICAgdC5zdGFydF9jbGllbnQoKQorICAgIGV4Y2VwdCAocGFyYW1pa28uU1NI
RXhjZXB0aW9uLCBzb2NrZXQuZXJyb3IpLCBlOgorICAgICAgICByYWlzZSBDb25uZWN0aW9uRXJy
b3IoJ1VuYWJsZSB0byByZWFjaCBTU0ggaG9zdCAlczolczogJXMnIAorICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgJSAoaG9zdCwgcG9ydCwgZSkpCisgICAgICAgIAorICAgIHNlcnZlcl9r
ZXkgPSB0LmdldF9yZW1vdGVfc2VydmVyX2tleSgpCisgICAgc2VydmVyX2tleV9oZXggPSBwYXJh
bWlrby51dGlsLmhleGlmeShzZXJ2ZXJfa2V5LmdldF9maW5nZXJwcmludCgpKQorICAgIGtleXR5
cGUgPSBzZXJ2ZXJfa2V5LmdldF9uYW1lKCkKKyAgICBpZiBTWVNURU1fSE9TVEtFWVMuaGFzX2tl
eShob3N0KSBhbmQgU1lTVEVNX0hPU1RLRVlTW2hvc3RdLmhhc19rZXkoa2V5dHlwZSk6CisgICAg
ICAgIG91cl9zZXJ2ZXJfa2V5ID0gU1lTVEVNX0hPU1RLRVlTW2hvc3RdW2tleXR5cGVdCisgICAg
ICAgIG91cl9zZXJ2ZXJfa2V5X2hleCA9IHBhcmFtaWtvLnV0aWwuaGV4aWZ5KG91cl9zZXJ2ZXJf
a2V5LmdldF9maW5nZXJwcmludCgpKQorICAgIGVsaWYgQlpSX0hPU1RLRVlTLmhhc19rZXkoaG9z
dCkgYW5kIEJaUl9IT1NUS0VZU1tob3N0XS5oYXNfa2V5KGtleXR5cGUpOgorICAgICAgICBvdXJf
c2VydmVyX2tleSA9IEJaUl9IT1NUS0VZU1tob3N0XVtrZXl0eXBlXQorICAgICAgICBvdXJfc2Vy
dmVyX2tleV9oZXggPSBwYXJhbWlrby51dGlsLmhleGlmeShvdXJfc2VydmVyX2tleS5nZXRfZmlu
Z2VycHJpbnQoKSkKKyAgICBlbHNlOgorICAgICAgICB3YXJuaW5nKCdBZGRpbmcgJXMgaG9zdCBr
ZXkgZm9yICVzOiAlcycgJSAoa2V5dHlwZSwgaG9zdCwgc2VydmVyX2tleV9oZXgpKQorICAgICAg
ICBpZiBub3QgQlpSX0hPU1RLRVlTLmhhc19rZXkoaG9zdCk6CisgICAgICAgICAgICBCWlJfSE9T
VEtFWVNbaG9zdF0gPSB7fQorICAgICAgICBCWlJfSE9TVEtFWVNbaG9zdF1ba2V5dHlwZV0gPSBz
ZXJ2ZXJfa2V5CisgICAgICAgIG91cl9zZXJ2ZXJfa2V5ID0gc2VydmVyX2tleQorICAgICAgICBv
dXJfc2VydmVyX2tleV9oZXggPSBwYXJhbWlrby51dGlsLmhleGlmeShvdXJfc2VydmVyX2tleS5n
ZXRfZmluZ2VycHJpbnQoKSkKKyAgICAgICAgc2F2ZV9ob3N0X2tleXMoKQorICAgIGlmIHNlcnZl
cl9rZXkgIT0gb3VyX3NlcnZlcl9rZXk6CisgICAgICAgIGZpbGVuYW1lMSA9IG9zLnBhdGguZXhw
YW5kdXNlcignfi8uc3NoL2tub3duX2hvc3RzJykKKyAgICAgICAgZmlsZW5hbWUyID0gcGF0aGpv
aW4oY29uZmlnX2RpcigpLCAnc3NoX2hvc3Rfa2V5cycpCisgICAgICAgIHJhaXNlIFRyYW5zcG9y
dEVycm9yKCdIb3N0IGtleXMgZm9yICVzIGRvIG5vdCBtYXRjaCEgICVzICE9ICVzJyAlIFwKKyAg
ICAgICAgICAgIChob3N0LCBvdXJfc2VydmVyX2tleV9oZXgsIHNlcnZlcl9rZXlfaGV4KSwKKyAg
ICAgICAgICAgIFsnVHJ5IGVkaXRpbmcgJXMgb3IgJXMnICUgKGZpbGVuYW1lMSwgZmlsZW5hbWUy
KV0pCisKKyAgICBfcGFyYW1pa29fYXV0aCh1c2VybmFtZSwgcGFzc3dvcmQsIGhvc3QsIHQpCisg
ICAgCisgICAgdHJ5OgorICAgICAgICBzZnRwID0gdC5vcGVuX3NmdHBfY2xpZW50KCkKKyAgICBl
eGNlcHQgcGFyYW1pa28uU1NIRXhjZXB0aW9uLCBlOgorICAgICAgICByYWlzZSBDb25uZWN0aW9u
RXJyb3IoJ1VuYWJsZSB0byBzdGFydCBzZnRwIGNsaWVudCAlczolZCcgJQorICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgKGhvc3QsIHBvcnQpLCBlKQorICAgIHJldHVybiBzZnRwCisKKwog
ZGVmIGdldF90ZXN0X3Blcm11dGF0aW9ucygpOgogICAgICIiIlJldHVybiB0aGUgcGVybXV0YXRp
b25zIHRvIGJlIHVzZWQgaW4gdGVzdGluZy4iIiIKICAgICByZXR1cm4gWyhTRlRQVHJhbnNwb3J0
LCBTRlRQQWJzb2x1dGVTZXJ2ZXIpLAoK
# revision id: andrew.bennetts at canonical.com-20060824033831-b68b13229677e409
# sha1: e4a813d908594eca97877054540082888ef133d1
# inventory sha1: f9afddb1f4da7e6064b1be803d6ff85f81e3b66e
# parent ids:
# andrew.bennetts at canonical.com-20060823035252-470ec76fa9d07b15
# properties:
# branch-nick: sftp refactoring 2
More information about the bazaar
mailing list