#!/usr/bin/env python
# +--------------------------------------------------------------------------+
# | Endian Firewall                                                          |
# +--------------------------------------------------------------------------+
# | Copyright (c) 2016 Endian S.p.A. <info@endian.com>                       |
# |         Endian S.p.A.                                                    |
# |         via Pillhof 47                                                   |
# |         39057 Appiano (BZ)                                               |
# |         Italy                                                            |
# |                                                                          |
# | 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.,  |
# | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              |
# +--------------------------------------------------------------------------+

import re
import sys
import base64
import urllib2
import hashlib
import urlparse
import argparse
import subprocess
from endian.core.version import get_product_version
from endian.data.ds import DataSource

DEFAULT_PASSWORD = 'community'

re_mac = re.compile(r'link/ether ((?:[0-9a-f]{2}[:-]){5}(?:[0-9a-f]{2}))', re.I)

ds = DataSource()


def file_content(file_name, default=''):
    """Return the content of a file.

    :param file_name: name of the file to read
    :type file_name: str

    :param default: default content if the file can't be read
    :type default: str

    :returns: content of the file
    :rtype: str"""
    content = default
    try:
        fd = open(file_name, 'r')
        content = fd.read().strip()
        fd.close()
    except:
        pass
    return content


def iface_mac(iface):
    """Return the MAC address of an interface.

    :param iface: interface to read
    :type iface: str

    :returns: MAC address of the interface, or None
    :rtype: str or None"""
    try:
        output = subprocess.check_output(['ip', 'link', 'show', 'dev', iface])
    except subprocess.CalledProcessError:
        return None
    match = re_mac.search(output)
    if match:
        return match.group(1)


def collect_info():
    """Build a dictionary with all the information to send.

    :returns: information about this system.
    :rtype: dict"""
    info = {
        'version': get_product_version(),
        'uuid': file_content('/etc/uuid'),
    }
    mac = iface_mac('eth0')
    if mac:
        mac_hash = hashlib.sha1()
        mac_hash.update(mac)
        info['mac_hash'] = mac_hash.hexdigest()
    else:
        info['mac_hash'] = ''
    info['product_id'] = ds.product.settings.product_id
    try:
        info['community_username'] = ds.main.settings.community_username or ''
    except AttributeError:
        info['community_username'] = ''
    return info


def build_url(info):
    """Generate the URL for the request.
    :returns: url to get
    :rtype: str
    """
    if info['community_username']:
        server = ds.product.settings.version_server
    else:
        server = ds.product.settings.unregistered_version_server
    info['uuid_machash'] = '%(uuid)s-%(mac_hash)s' % info
    path = '%(version)s/%(product_id)s/%(uuid_machash)s' % info
    return urlparse.urljoin(server, path)


def version_check(url, info):
    """Check version info with remote server.

    :param url: url to get
    :type url: str
    :param info: information about this system
    :type info: dict

    :returns: tuple with status code and content
    :rtype: tuple"""
    headers = {'User-Agent': '%(product_id)s/%(version)s' % info}
    if info['community_username']:
        raw = '%s:%s' % (info['community_username'], DEFAULT_PASSWORD)
        auth = 'Basic %s' % base64.b64encode(raw).strip()
        headers['Authorization'] = auth
    req = urllib2.Request(url, headers=headers)
    res = urllib2.urlopen(req)
    ret = res.read()
    res.close()
    return res.getcode(), ret


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--print', help='Do not check version, just print the url to stdout',
                        action='store_true', dest='print_')
    args = parser.parse_args()
    info = collect_info()
    url = build_url(info)
    if args.print_:
        print url
        sys.exit(0)
    else:
        version_check(url, info)
