#!/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 re

from winswitch.util.simple_logger import Logger
from winswitch.util.common import csv_list
from winswitch.objects.mount_point import MountPoint
from winswitch.util.commands_util import SMBCLIENT_COMMAND
from winswitch.util.process_util import get_output
from winswitch.globals import USERNAME, WIN32
from winswitch.consts import LOCALHOST

logger=Logger("smb_parse", log_colour=Logger.HIGHLIGHTED_BLUE)

PARSE_ENABLED = False			#can cause some systems to block waiting for "smbclient" to do its stuff..
DEBUG = True

DOMAIN_RE = re.compile(r"^Domain=\[(\w+)\]")
SHARE_RE = re.compile(r"^\s*Sharename\s+Type\s+Comment\s*$")
SERVER_RE = re.compile(r"^\s*Server\s+Comment\s*$")
SECTION_HEADER = re.compile(r"^\s+-*\s-+\s-+\s*$")
DATA_LINE = re.compile(r"^\s+")
SHARE_DATA = re.compile(r"^\s+([\w\$\-]+)\s+(\w+)\s+(.*)$")

def parse(username=None, password=None, host=LOCALHOST, port=139, ignoreIPC=True):
	if not SMBCLIENT_COMMAND:
		logger.serror("smbclient not found, cannot detect smb shares!", username, "...", host, port, ignoreIPC)
		return	[]
	cmd = [SMBCLIENT_COMMAND]
	if password:
		cmd.append(password)
	else:
		cmd.append("-N")
	cmd.append("-p")
	cmd.append(str(port))
	if username:
		cmd.append("-U")
		cmd.append(username)
	cmd.append("-L")
	cmd.append(host)
	if DEBUG:
		logger.slog("cmd=%s" % cmd, username, password, host, port)

	try:
		code, out, _ = get_output(cmd)
		if code!=0:
			return	[]
	except Exception, e:
		logger.serr("failed to run '%s'" % cmd, e, username, "...", host, port, ignoreIPC)
		return	[]

	mount_points = []

	share_section = False
	domain = None
	l = 0
	for line in out.split("\n"):
		#print("%s: %s" % (l, line))
		l += 1
		match = DOMAIN_RE.match(line)
		if match:
			domain = match.group(1)
			if DEBUG:
				logger.sdebug("domain=%s" % domain, username, "...", host, port)
			continue
		if SHARE_RE.match(line):
			if DEBUG:
				logger.sdebug("found share section=%s" % line, username, "...", host, port)
			share_section = True
			continue
		if SERVER_RE.match(line):
			if DEBUG:
				logger.sdebug("found server section=%s" % line, username, "...", host, port)
			share_section = False
			continue
		if SECTION_HEADER.match(line):
			continue
		if not DATA_LINE.match(line) and share_section:
			share_section = False
			continue
		if share_section:
			match = SHARE_DATA.match(line)
			if match:
				share_name = match.group(1)
				if ignoreIPC and share_name=="IPC$":
					continue
				share_type = match.group(2)
				comment = match.group(3)
				if share_type not in [MountPoint.PRINTER, MountPoint.DISK]:
					logger.serror("unknown share type '%s' for %s:%s" % (share_type, share_name, comment), username, "...", host, port)
					continue

				if DEBUG:
					logger.sdebug("found share: %s:%s:%s" % (share_name, share_type, comment), username, "...", host, port)
				auth_mode = ""
				if username:
					auth_mode = MountPoint.LOGIN
				mount = MountPoint(MountPoint.SMB, domain, host, port, share_name, share_type, auth_mode, username, "...", comment, {})
				mount_points.append(mount)
	return mount_points


def get_default_exports():
	"""
	Returns the mount points that can be exported,
	adding the home directory to what we find via parse()
	"""
	#should check if it is really available (hidden with samba...)
	password = None
	home_dir = MountPoint(MountPoint.SMB, None, LOCALHOST, 139, USERNAME, MountPoint.DISK, MountPoint.LOGIN, USERNAME, password, "Home directory", {})
	exports = [home_dir]
	if PARSE_ENABLED and not WIN32:
		mount_points = parse(USERNAME)
		for mp in mount_points:
			exports.append(mp)
	return exports


def test_parse(username=None, password=None, host="localhost"):
	mount_points = parse(username, password, host)
	logger.slog("mount_points=%s" % csv_list(mount_points), username, host)
	logger.slog("mount points names=%s" % csv_list(get_default_exports()), username, host)


def main():
	test_parse()
	test_parse("antoine")

if __name__ == "__main__":
	main()
