#!/usr/bin/env python

# This file is part of Window-Switch.
# Copyright (c) 2009-2013 Antoine Martin <antoine@nagafix.co.uk>
# Window-Switch is released under the terms of the GNU GPL v3

import sys
import os

from winswitch.util.simple_logger import Logger
from winswitch.util.common import is_valid_file


SSH_SHARING = "--no-ssh-sharing" not in sys.argv

logger=Logger("ssh_util", log_colour=Logger.CYAN)

def client_is_plink(ssh):
	return (ssh is not None) and ssh.lower().find("plink")>=0

def _ssh_port_switch(ssh_command):
	if client_is_plink(ssh_command):
		return	"-P"
	else:
		return	"-p"


def	get_tunnel_command(ssh_cmd, server, command_to_run=None, interactive=False, compression=False,
						from_port=None, to_host=None, to_port=None, reversed_fwd=False,
						X_forwarding=False, host_key_file=None,
						master=False, control_path=None):
	forwards = []
	if from_port and to_host and to_port:
		forwards.append((from_port, to_host, to_port, reversed_fwd))
	return	get_tunnels_command(ssh_cmd, server, command_to_run=command_to_run, interactive=interactive, compression=compression,
								forwards=forwards,
								X_forwarding=X_forwarding, host_key_file=host_key_file,
								master=master, control_path=control_path)

def	get_tunnels_command(ssh_cmd, server, command_to_run=None, interactive=False, compression=False,
						forwards=None,
						X_forwarding=False, host_key_file=None, strict_keys=None,
						master=False, control_path=None):
	return	do_get_tunnel_command(ssh_cmd, server.host, server.port, server.username, server.password, server.ssh_keyfile,
								command_to_run=command_to_run, interactive=interactive, compression=compression,
								forwards=forwards,
								X_forwarding=X_forwarding, host_key_file=host_key_file,
								strict_keys=False,
								master=master, control_path=control_path)

def	do_get_tunnel_command(ssh_cmd, host, port, username, password, keyfile, command_to_run=None, interactive=False,
							compression=False,
							forwards=None,
							X_forwarding=False,
							host_key_file=None,
							strict_keys=None,
							master=False, control_path=None):
	cmd = [ssh_cmd]
	# port switch (-p or -P)
	if port!=22:
		cmd += [_ssh_port_switch(ssh_cmd), str(port)]
	# plink tweaks
	if client_is_plink(ssh_cmd):
		is_sun_ssh = False
		#if not interactive:
		cmd += ["-batch"]
		if len(password) > 0:
			cmd += ["-pw", password]
	else:
		is_sun_ssh = sys.platform.startswith("sun")	#FIXME: should test when SSH_CMD is changed and set flag then. openssh can be installed on solaris - and often is...
		if not interactive:
			cmd += ["-n"]
			cmd += ["-o", "BatchMode=yes"]
		#cmd += ["-o", "ChallengeResponseAuthentication=no"]
		#cmd += ["-o", "NumberOfPasswordPrompts=0"]
		#cmd += ["-o", "PasswordAuthentication=no"]
		#cmd += ["-o", "KbdInteractiveAuthentication=no"]
		if host_key_file and is_valid_file(host_key_file):
			cmd += ["-o", "HashKnownHosts=no"]
			cmd += ["-o", "UserKnownHostsFile=%s" % host_key_file]

		if not is_sun_ssh:
			cmd += ["-o", "ExitOnForwardFailure=yes"]
		cmd += ["-o", "ServerAliveInterval=30"]
		if not X_forwarding:
			cmd += ["-o", "ForwardX11=no"]
			cmd += ["-o", "ForwardX11Trusted=no"]
		if not is_sun_ssh:
			if SSH_SHARING and master is not False:
				if master==True:
					cmd += ["-o", "ControlMaster=yes"]
				else:
					cmd += ["-o", "ControlMaster=%s" % master]		#ie: auto
			else:
				cmd += ["-o", "ControlMaster=no"]
			if SSH_SHARING and control_path:
				cmd += ["-o", "ControlPath=%s" % control_path]

		if strict_keys is False:
			cmd += ["-o", "StrictHostKeyChecking=no"]
		if strict_keys is True:
			cmd += ["-o", "StrictHostKeyChecking=yes"]

	if X_forwarding:
		cmd += ["-X"]	#works for plink too!

	if not interactive:
		cmd += ["-T"]			#no TTY
		if not command_to_run:
			cmd += ["-N"]		#no shell since no command
	# keyfile:
	if keyfile and len(keyfile) > 0:
		if keyfile.startswith("~"):
			keyfile = os.path.expanduser(keyfile)
		if keyfile.startswith("."):
			keyfile = os.path.expanduser("~/"+keyfile)
		if os.path.exists(keyfile):
			cmd += ["-i", keyfile]
	# user@host + cmd
	cmd += [username+"@"+host]
	if compression is not None:
		comp = int(compression)
		if comp>0:
			cmd += ["-C"]
			if not is_sun_ssh:
				cmd += ["-o", "CompressionLevel=%s" % comp]
	if forwards:
		for forward in forwards:
			(from_port, to_host, to_port, reversed_fwd) = forward
			if reversed_fwd:
				cmd += ["-R", "%i:%s:%i" % (to_port, to_host, from_port)]
			else:
				cmd += ["-L", "%i:%s:%i" % (from_port, to_host, to_port)]
	if command_to_run:
		cmd += [command_to_run]
	return	cmd

