From 3bb1a893cc83b6c36365734a073057ace0823796 Mon Sep 17 00:00:00 2001 From: jcc6611 Date: Sat, 8 Feb 2020 17:07:04 -0500 Subject: [PATCH] Implemented local port forwarding (closes #15) --- src/forwarding.py | 158 +++++++++++++++++++++++++++++++++++++++++++ src/portforwards.txt | 0 src/utils/module.py | 40 +++++++---- 3 files changed, 183 insertions(+), 15 deletions(-) create mode 100644 src/forwarding.py create mode 100644 src/portforwards.txt diff --git a/src/forwarding.py b/src/forwarding.py new file mode 100644 index 0000000..4f21c9a --- /dev/null +++ b/src/forwarding.py @@ -0,0 +1,158 @@ +""" +Author: Jason Cheung +Date: 2/8/2020 + +Description: This is a manager for easily performing SHH port forwards +""" + +import subprocess +import collections + +from utils import module +import configuration + +# INPUT_FILE = configuration.get_config()["portforwards"] +INPUT_FILE = "./portforwards.txt" +Computer = collections.namedtuple("Computer", ('user', 'user_num')) +WELCOME_MESSAGE = "**************************************" + + +def main(): + """ + This function inputs all the available hosts from a text file and + prompts the user to connect to them + :return: + """ + file = module.input_file(INPUT_FILE) + + cmp = [] + count = 1 + + for line in file: + cmp.append(Computer(line, count)) + count += 1 + menu = [] + + for c in cmp: + menu.append(str(c.user_num) + ") " + "".join(c.user)) + menu.append("A) Exit") + menu.append("B) Manager tools") + + module.print_menu("SSH forwarding manager V 1.0", menu) + + i = input("Enter Option:") + + if i == '' or i == 'A' or i == 'a': + exit_program() + elif i == 'B' or i == 'b': + sub_menu() + else: + for c in cmp: + if int(i) == c.user_num: + subprocess.call( + ["ssh", "-L", c.user.split(":")[2] + ":localhost:" + + c.user.split(":")[2], c.user.split(":")[1]]) + exit_program() + + +def print_sub_menu(): + """ + prints out a sub help menu for other options + :return: None + """ + module.print_menu("Options", ["1) Add Host", + "2) Remove host name", + "3) Return to ssh forwarding", + "4) Manage Configuration and Bash", + "5) Exit"]) + + +def sub_menu(): + """ + calls printSubMenu and then gets input from user to + make appropriate function calls + :return: None + """ + print_sub_menu() + i = input("Enter selection:") + + if i != '' and int(i) in {1, 2, 3, 4, 5}: + options = {1: add_host, + 2: remove_host, + 3: main, + 4: configuration.main, + 5: exit_program + } + options[int(i)]() + else: + print("Invalid selection!") + + sub_menu() + + +def print_red(prt): return "\033[91m {}\033[00m".format(prt) + + +def exit_program(): + """ + Exits the program and clears the screen + :return: None + """ + subprocess.call(["clear"]) + exit() + + +def add_host(): + """ + appends an inputted host name to servers.txt + :return: None + """ + host = input("Enter 'user@host' or -1 to exit:") + if host != '-1': + name = input("Name: ") + port = input("Port: ") + module.append_file(INPUT_FILE, name + ":" + host + ":" + port) + + +def remove_host(): + """ + Removes a host name from servers.txt + :return: None + """ + padding_star = "*" * 5 + max_len = 0 + file = module.input_file(INPUT_FILE) + for line in file: + temp = len(line) + if max_len < temp: + max_len = temp + TOP_BAR = padding_star + "*" * max_len + padding_star + cmp = [] + count = 1 + print(print_red("*" * len(TOP_BAR) + "*")) + for line in file: + cmp.append(Computer(line, count)) + count += 1 + for c in cmp: + space = " " * (len(TOP_BAR) - 3 - + len(str(c.user_num) + ") " + c.user)) + print(print_red("*") + " " + str(c.user_num) + ") " + + c.user + space + print_red("*")) + + print(print_red("*" * len(TOP_BAR) + '*')) + + host = input("Enter number of host -1 to exit:") + if host != '-1': + for c in cmp: + if c.user_num == int(host): + module.remove_line_from_file(INPUT_FILE, c.user) + + +""" +Makes sure that other programs don't execute the main +""" +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + exit_program() diff --git a/src/portforwards.txt b/src/portforwards.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/module.py b/src/utils/module.py index dbbfd1f..29cce2d 100644 --- a/src/utils/module.py +++ b/src/utils/module.py @@ -74,26 +74,27 @@ def create_empty_file(file_name): subprocess.call(['touch', file_name]) -TOP_BAR = "**************************************" +# TOP_BAR = "********************************************" +# TOP_BAR = -def print_magenta(prt): return"\033[95m {}\033[00m" .format(prt) +def print_magenta(prt): return "\033[95m {}\033[00m".format(prt) -def print_green(prt): return "\033[92m {}\033[00m" .format(prt) +def print_green(prt): return "\033[92m {}\033[00m".format(prt) -def print_red(prt): return "\033[91m {}\033[00m" .format(prt) +def print_red(prt): return "\033[91m {}\033[00m".format(prt) -def print_menu_option(s): +def print_menu_option(s, top_bar_length): """ Prints each host option :param s: :return: """ - space = " " * (len(TOP_BAR) - 4 - len(s)) - print(print_magenta("* ") + s + space + print_magenta("*")) + space = " " * (top_bar_length - 4 - len(s)) + print(print_magenta("* ") + s + space + print_magenta("*")) def print_menu(name, lines): @@ -111,18 +112,27 @@ def print_menu(name, lines): ************************************** """ + padding_star = "*" * 5 + temp = 0 + max_len = 0 + for s in lines: + temp = len(s) + if max_len < temp: + max_len = temp + TOP_BAR = padding_star + "*" * max_len + padding_star if not len(name) % 2 == 0: - name = name + " " + name = name + " " + name = name + " " spaces = len(TOP_BAR) - 4 - len(name) print(print_magenta(TOP_BAR)) - print(print_magenta("*") + - (int(spaces/2) * " ") + - print_green(name) + - (int(spaces/2) * " ") + - print_magenta("*")) + print(print_magenta("*") + + (int(spaces / 2) * " ") + + print_green(name) + + (int(spaces / 2) * " ") + + print_magenta("*")) for s in lines: - print_menu_option(s) - print(print_magenta(TOP_BAR)) \ No newline at end of file + print_menu_option(s, len(TOP_BAR)) + print(print_magenta(TOP_BAR))