You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2019/10/17 06:02:46 UTC

[mina-sshd] 06/06: [SSHD-914] Added Python 3 script based on Paramiko package to interact with MINA SSHD as an SFTP client

This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 77859da20def8127c2a9c2350f46435a8db68fba
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Wed Oct 16 14:17:46 2019 +0300

    [SSHD-914] Added Python 3 script based on Paramiko package to interact with MINA SSHD as an SFTP client
---
 .gitignore                                         |   3 +
 pom.xml                                            |   3 +
 sshd-sources/python/sftpclient.py                  | 406 +++++++++++++++++++++
 .../tomcat-apr-5.5.23-sources/META-INF/INDEX.LIST  |   0
 .../tomcat-apr-5.5.23-sources/META-INF/MANIFEST.MF |   0
 .../tomcat-apr-5.5.23-sources/README.txt           |   0
 .../org/apache/tomcat/jni/Address.java             |   0
 .../org/apache/tomcat/jni/BIOCallback.java         |   0
 .../org/apache/tomcat/jni/Directory.java           |   0
 .../org/apache/tomcat/jni/Error.java               |   0
 .../org/apache/tomcat/jni/File.java                |   0
 .../org/apache/tomcat/jni/FileInfo.java            |   0
 .../org/apache/tomcat/jni/Global.java              |   0
 .../org/apache/tomcat/jni/Library.java             |   0
 .../org/apache/tomcat/jni/Local.java               |   0
 .../org/apache/tomcat/jni/Lock.java                |   0
 .../org/apache/tomcat/jni/Mmap.java                |   0
 .../org/apache/tomcat/jni/Multicast.java           |   0
 .../org/apache/tomcat/jni/OS.java                  |   0
 .../org/apache/tomcat/jni/PasswordCallback.java    |   0
 .../org/apache/tomcat/jni/Poll.java                |   0
 .../org/apache/tomcat/jni/Pool.java                |   0
 .../org/apache/tomcat/jni/PoolCallback.java        |   0
 .../org/apache/tomcat/jni/Proc.java                |   0
 .../org/apache/tomcat/jni/ProcErrorCallback.java   |   0
 .../org/apache/tomcat/jni/Procattr.java            |   0
 .../org/apache/tomcat/jni/Registry.java            |   0
 .../org/apache/tomcat/jni/SSL.java                 |   0
 .../org/apache/tomcat/jni/SSLContext.java          |   0
 .../org/apache/tomcat/jni/SSLSocket.java           |   0
 .../org/apache/tomcat/jni/Shm.java                 |   0
 .../org/apache/tomcat/jni/Sockaddr.java            |   0
 .../org/apache/tomcat/jni/Socket.java              |   0
 .../org/apache/tomcat/jni/Status.java              |   0
 .../org/apache/tomcat/jni/Stdlib.java              |   0
 .../org/apache/tomcat/jni/Thread.java              |   0
 .../org/apache/tomcat/jni/Time.java                |   0
 .../org/apache/tomcat/jni/User.java                |   0
 38 files changed, 412 insertions(+)

diff --git a/.gitignore b/.gitignore
index 485a2b4..39cdffd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,9 @@ Servers/
 RemoteSystemsTempFiles/
 .classpath
 .project
+# Puthon related files
+.pydevproject
+*.pyc
 .checkstyle
 .eclipse-pmd
 .pmd
diff --git a/pom.xml b/pom.xml
index dc7b41f..14cf8e9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -637,6 +637,7 @@
                         <excludes>
                             <exclude>*.md</exclude>
                             <exclude>docs/**</exclude>
+                            <exclude>sshd-sources/**</exclude>
                             <exclude>src/test/resources/**</exclude>
                             <exclude>**/stty-output-*.txt</exclude>
                             <exclude>**/target/**</exclude>
@@ -659,6 +660,8 @@
                             <exclude>.project</exclude>
                             <exclude>.classpath</exclude>
                             <exclude>.springBeans</exclude>
+                            <exclude>.pydevproject</exclude>
+                            <exclude>*.pyc</exclude>
                             <exclude>.settings/**</exclude>
                             <exclude>.repository/**</exclude>
                             <exclude>.gitignore</exclude>
diff --git a/sshd-sources/python/sftpclient.py b/sshd-sources/python/sftpclient.py
new file mode 100644
index 0000000..f8df143
--- /dev/null
+++ b/sshd-sources/python/sftpclient.py
@@ -0,0 +1,406 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+'''
+Simple wrapper for Paramiko SFTP client (see http://www.paramiko.org/)
+'''
+
+import getpass
+import json
+import os
+import signal
+import sys
+
+import paramiko
+
+
+VERSION='1.0'
+
+# -----------------------------------------------------------------------------------------
+
+def die(msg=None,rc=1):
+    """
+    Cleanly exits the program with an error message
+    """
+
+    if msg:
+        print(msg)
+
+    sys.exit(rc)
+
+# ----------------------------------------------------------------------------
+
+def isEmpty(s):
+    if (s is None) or (len(s) <= 0):
+        return True
+    else:
+        return False
+
+# ----------------------------------------------------------------------------
+
+def isNumberString(value):
+    """
+    Checks if value is a string that has only digits - possibly with leading '+' or '-'
+    """
+    if not value:
+        return False
+
+    sign = value[0]
+    if (sign == '+') or (sign == '-'):
+        if len(value) <= 1:
+            return False
+
+        absValue = value[1:]
+        return absValue.isdigit()
+    else:
+        if len(value) <= 0:
+            return False
+        else:
+            return value.isdigit()
+
+def isNumberValue(value):
+    return isinstance(value, (int, float))
+
+# ----------------------------------------------------------------------------
+
+def isFloatingPointString(value):
+    """
+    Checks if value is a string that has only digits - possibly with leading '+' or '-' - AND a single dot
+    """
+    if isEmpty(value):
+        return False
+
+    sign = value[0]
+    if (sign == '+') or (sign == '-'):
+        if len(value) <= 1:
+            return False
+
+        absValue = value[1:]
+    else:
+        absValue = value
+
+    dotPos = absValue.find('.')
+    # Must have a dot and it cannot be the last character
+    if (dotPos < 0) or (dotPos == (len(absValue) - 1)):
+        return False
+
+    # Must have EXACTLY one dot
+    dotCount = absValue.count('.')
+    if dotCount != 1:
+        return False
+
+    # Make sure both sides of the dot are integer numbers
+    intPart = absValue[0:dotPos]
+    if not isNumberString(intPart):
+        return False
+
+    facPart = absValue[dotPos + 1:]
+    # Do not allow 123.-5
+    sign = facPart[0]
+    if (sign == '+') or (sign == '-'):
+        return False
+
+    if not isNumberString(facPart):
+        return False
+
+    return True
+
+# ----------------------------------------------------------------------------
+
+def normalizeValue(value):
+    """
+    Checks if value is 'True', 'False' or all numeric and converts it accordingly
+    Otherwise it just returns it
+
+    Args:
+        value (str) - String value
+    """
+
+    if not value:
+        return value
+
+    loCase = value.lower()
+    if loCase == "none":
+        return None
+    elif loCase == "true":
+        return True
+    elif loCase == "false":
+        return False
+    elif isNumberString(loCase):
+        return int(loCase)
+    else:
+        return value
+
+# ----------------------------------------------------------------------------
+
+def parseCommandLineArguments(args):
+    """
+    Parses an array of arguments having the format: --name=value. If
+    only --name is provided then it is assumed to a TRUE boolean value.
+    If the value is all digits, then it is assumed to be a number.
+
+    If the same key is specified more than once, then a list of
+    the accumulated values is created. The result is a dictionary
+    with the names as the keys and value as their mapped values
+
+    Args:
+        args (str[]) - The command line arguments to parse
+    """
+
+    valsMap = {}
+    if len(args) <= 0:
+        return valsMap
+
+    for item in args:
+        if not item.startswith("--"):
+            raise Exception("Missing option identifier: %s" % item)
+
+        propPair = item[2:]     # strip the prefix
+        sepPos = propPair.find('=')
+
+        if sepPos == 0:
+            raise Exception("Missing name: %s" % item)
+        if sepPos >= (len(propPair) - 1):
+            raise Exception("Missing value: %s" % item)
+
+        propName = propPair
+        propValue = None
+        if sepPos < 0:
+            propValue = True
+        else:
+            propName = propPair[0:sepPos]
+            propValue = normalizeValue(propPair[sepPos + 1:])
+
+        if propName in valsMap:
+            curValue = valsMap[propName]
+            if not isinstance(curValue, list):
+                curValue = [ curValue ]
+            curValue.append(propValue)
+            valsMap[propName] = curValue
+        else:
+            valsMap[propName] = propValue
+
+    return valsMap
+
+# ----------------------------------------------------------------------------
+
+def resolvePathVariables(path):
+    """
+    Expands ~/xxx and ${XXX} variables
+    """
+    if isEmpty(path):
+        return path
+
+    path = os.path.expanduser(path)
+    path = os.path.expandvars(path)
+    return path
+
+# ----------------------------------------------------------------------------
+
+def _decode_list(data):
+    # can happen for internal sub-lists of objects
+    if isinstance(data, dict):
+        return _decode_dict(data)
+
+    rv = []
+    for item in data:
+        if isinstance(item, list):
+            item = _decode_list(item)
+        elif isinstance(item, dict):
+            item = _decode_dict(item)
+        rv.append(item)
+    return rv
+
+# ----------------------------------------------------------------------------
+
+def _decode_dict(data):
+    # can happen for internal sub-lists of objects
+    if isinstance(data, list):
+        return _decode_list(data)
+
+    rv = {}
+    for key, value in data.items():
+        if isinstance(value, list):
+            value = _decode_list(value)
+        elif isinstance(value, dict):
+            value = _decode_dict(value)
+        rv[key] = value
+
+    return rv
+
+# ----------------------------------------------------------------------------
+
+def loadJsonFile(configFile):
+    if isEmpty(configFile):
+        return {}
+
+    with open(configFile) as config_file:
+        return json.load(config_file, object_hook=_decode_dict);
+
+# ----------------------------------------------------------------------------
+
+def createSftpClient(args):
+    host = args.get("host", "localhost")
+    port = args.get("port", 22)
+    username = args.get("username", None)
+    if isEmpty(username):
+        username = getpass.getuser()
+    password = args.get("password", None)
+    keyfile = args.get("keyFile", None)
+    keytype = args.get("keyType", "RSA")
+
+    sftp = None
+    transport = None
+    try:
+        key = None
+        if keyfile is not None:
+            # Get private key used to authenticate user.
+            if keytype == 'DSA':
+                # The private key is a DSA type key.
+                key = paramiko.DSSKey.from_private_key_file(keyfile)
+            else:
+                # The private key is a RSA type key.
+                key = paramiko.RSAKey.from_private_key(keyfile)
+
+        # Create Transport object using supplied method of authentication.
+        transport = paramiko.Transport((host, port))
+        transport.connect(None, username, password, key)
+ 
+        sftp = paramiko.SFTPClient.from_transport(transport)
+        return sftp
+    except Exception as e:
+        print('An error occurred creating SFTP client: %s: %s' % (e.__class__, e))
+
+        if sftp is not None:
+            try:
+                sftp.close()
+            except Exception as err:
+                print('Failed to close SFTP client: %s: %s' % (err.__class__, err))
+
+        if transport is not None:
+            try:
+                transport.close()
+            except Exception as err:
+                print('Failed to close transport: %s: %s' % (err.__class__, err))
+
+        raise e
+    
+# =========================================================================================
+
+def doList(sftp, curdir, argsList):
+    dirPath = curdir;
+    if not isEmpty(argsList):
+        dirPath = argsList.pop(0)
+        dirPath = dirPath.strip()
+        dirPath = os.path.join(curdir, dirPath)
+
+    # Also available: listdir_attr, listdir
+    dirlist = sftp.listdir_iter(path=dirPath)
+    for row in dirlist:
+        # see https://docs.paramiko.org/en/2.6/api/sftp.html#paramiko.sftp_attr.SFTPAttributes
+        print("    %s" % str(row))
+
+def doChdir(sftp, homedir, curdir, argsList):
+    dirPath = homedir
+    if not isEmpty(argsList):
+        dirPath = argsList.pop(0)
+        dirPath = dirPath.strip()
+        dirPath = os.path.join(curdir, dirPath)
+    sftp.chdir(dirPath)
+
+# ----------------------------------------------------------------------------
+
+# see https://github.com/paramiko/paramiko/blob/master/demos/demo_sftp.py
+# see https://docs.paramiko.org/en/2.6/api/sftp.html
+def doSftp(sftp):
+    homedir = sftp.normalize('.')
+    sftp.chdir(homedir)
+    
+    while True:
+        curdir = sftp.getcwd()
+        sys.stdout.write("%s > " % curdir)
+        l = sys.stdin.readline()
+        l = l.strip()
+    
+        if isEmpty(l):
+            continue
+        
+        argsList = l.split(' ')
+        op = argsList.pop(0)
+        
+        if (op == "quit") or (op == "exit") or (op == "bye"):
+            break
+        elif (op == "ls") or (op == "list"):
+            doList(sftp, curdir, argsList)
+        elif (op == "cd"):
+            doChdir(sftp, homedir, curdir, argsList)
+        # TODO get_channel()
+        #    show info using get_transport() on it
+        #    get_security_options() on transport
+        else:
+            print("Unknown command: %s" % l)
+
+def doMain(args):
+    sftp = createSftpClient(args)
+    try:
+        doSftp(sftp);
+    except Exception as e:
+        print('An error occurred using the SFTP client: %s: %s' % (e.__class__, e))
+        raise e
+    finally:
+        sftp.close()
+
+#
+# Usage: python3 sftpclient.py --arg1=value1 --arg2=value2 ...
+#
+# Where available arguments are:
+#
+#    * host - default=localhost
+#    * port - default=22
+#    * username - the login user - default=currently logged in user
+#    * password - the password - can be omitted if key file used
+#    * keyFile - path to key file
+#    * keyType - type of key in file (RSA/DSA) - default=RSA
+def main(args):
+    if len(args) > 0:
+        subArgs = parseCommandLineArguments(args)
+    else:
+        subArgs = {}
+    doMain(subArgs)
+    sys.exit(0)
+    
+# ----------------------------------------------------------------------------
+
+def signal_handler(signal, frame):
+    die('Exit due to Control+C')
+
+if __name__ == "__main__":
+    pyVersion = sys.version_info
+    if pyVersion.major != 3:
+        die("Major Python version must be 3.x: %s" % str(pyVersion))
+    if pyVersion.minor < 0:
+        print("Warning: minor Python version %s should be at least 3.0+" % str(pyVersion))
+
+    signal.signal(signal.SIGINT, signal_handler)
+    if os.name == 'nt':
+        print("Use Ctrl+Break to stop the script")
+    else:
+        print("Use Ctrl+C to stop the script")
+    main(sys.argv[1:])
\ No newline at end of file
diff --git a/src/tomcat-apr-5.5.23-sources/META-INF/INDEX.LIST b/sshd-sources/tomcat-apr-5.5.23-sources/META-INF/INDEX.LIST
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/META-INF/INDEX.LIST
rename to sshd-sources/tomcat-apr-5.5.23-sources/META-INF/INDEX.LIST
diff --git a/src/tomcat-apr-5.5.23-sources/META-INF/MANIFEST.MF b/sshd-sources/tomcat-apr-5.5.23-sources/META-INF/MANIFEST.MF
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/META-INF/MANIFEST.MF
rename to sshd-sources/tomcat-apr-5.5.23-sources/META-INF/MANIFEST.MF
diff --git a/src/tomcat-apr-5.5.23-sources/README.txt b/sshd-sources/tomcat-apr-5.5.23-sources/README.txt
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/README.txt
rename to sshd-sources/tomcat-apr-5.5.23-sources/README.txt
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Address.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Address.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Address.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Address.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/BIOCallback.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/BIOCallback.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/BIOCallback.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/BIOCallback.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Directory.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Directory.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Directory.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Directory.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Error.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Error.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Error.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Error.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/File.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/File.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/File.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/File.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/FileInfo.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/FileInfo.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/FileInfo.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/FileInfo.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Global.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Global.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Global.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Global.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Library.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Library.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Library.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Library.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Local.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Local.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Local.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Local.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Lock.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Lock.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Lock.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Lock.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Mmap.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Mmap.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Mmap.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Mmap.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Multicast.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Multicast.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Multicast.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Multicast.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/OS.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/OS.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/OS.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/OS.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/PasswordCallback.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/PasswordCallback.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/PasswordCallback.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/PasswordCallback.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Poll.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Poll.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Poll.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Poll.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Pool.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Pool.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Pool.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Pool.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/PoolCallback.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/PoolCallback.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/PoolCallback.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/PoolCallback.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Proc.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Proc.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Proc.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Proc.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/ProcErrorCallback.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/ProcErrorCallback.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/ProcErrorCallback.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/ProcErrorCallback.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Procattr.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Procattr.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Procattr.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Procattr.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Registry.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Registry.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Registry.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Registry.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSL.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSL.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSL.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSL.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSLContext.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSLContext.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSLContext.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSLContext.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSLSocket.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSLSocket.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSLSocket.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/SSLSocket.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Shm.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Shm.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Shm.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Shm.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Sockaddr.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Sockaddr.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Sockaddr.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Sockaddr.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Socket.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Socket.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Socket.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Socket.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Status.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Status.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Status.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Status.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Stdlib.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Stdlib.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Stdlib.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Stdlib.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Thread.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Thread.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Thread.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Thread.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Time.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Time.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Time.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/Time.java
diff --git a/src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/User.java b/sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/User.java
similarity index 100%
rename from src/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/User.java
rename to sshd-sources/tomcat-apr-5.5.23-sources/org/apache/tomcat/jni/User.java