import os, sys, pymongo, configparser, urllib.parse
import urllib.request as req

class Configuration(): 
    ConfigParser = configparser.ConfigParser()
    # Open configuration file
    ConfigParser.read("/etc/ivulncheck/ivulncheck-api.ini")
    
    default = {'mongoHost': 'localhost', 'mongoPort': 27017,
               # GAT
               'mongoVulnDB': "vulndb",
               'mongoHostDB': "hostdb",
               'mongoFixDB': "fixdb",
               'testmongoDB': "testdb",
               'mongoUsername': '', 'mongoPassword': '', 'mongoAuthSource': 'admin',
               'nbProcesses': 0,
               'uctBranch': "lp:~ubuntu-security/ubuntu-cve-tracker/master",
               'uctConfFile': "/etc/ivulncheck/ubuntu-cve-tracker.conf",
               'uctPath': "/var/lib/ivulncheck-api/ubuntu-cve-tracker",
               'fakeReposPath': "/var/lib/ivulncheck-api/fake-repos",
               'debianArchiveURL': "http://ftp.debian.org/debian/dists/",
               'debianSecurityArchiveURL': "http://security.debian.org/debian-security/dists/",
               'ubuntuArchiveURL': "http://fr.archive.ubuntu.com/ubuntu/dists/",
               'flaskDebug': True,       'pageLength': 50,
               'logging': True,           'logfile': "/var/log/ivulncheck/ivulncheck-api.log",
               'maxLogSize': '100MB',     'backlog': 5,
               'url': "https://security-tracker.debian.org/tracker/debsecan/release/1/",
               'backup_file_path': "/var/lib/ivulncheck-api/debsecan",
               'cvesearchAPIHost': "127.0.0.1",
               'cvesearchAPIPort': 5000,
               'rulesFile': "/etc/ivulncheck/hosts_stats_rules.json"
               }

    @classmethod
    def readSetting(cls, section, item, default):
        result = default
        try:
            if type(default) == bool:
                result = cls.ConfigParser.getboolean(section, item)
            elif type(default) == int:
                result = cls.ConfigParser.getint(section, item)
            else:
                result = cls.ConfigParser.get(section, item)
        except:
            pass
        return result

    # Mongo
    @classmethod
    def getVulnDB(cls):
        mongoHost = cls.readSetting("Mongo", "Host", cls.default['mongoHost'])
        mongoPort = cls.readSetting("Mongo", "Port", cls.default['mongoPort'])
        mongoDB = cls.readSetting("Mongo", "VulnDB", cls.default['mongoVulnDB'])
        mongoUsername = cls.readSetting("Mongo", "Username", cls.default['mongoUsername'])
        mongoPassword = cls.readSetting("Mongo", "Password", cls.default['mongoPassword'])
        mongoAuthSource = cls.readSetting("Mongo", "AuthSource", cls.default['mongoAuthSource'])

        mongoUsername = urllib.parse.quote( mongoUsername )
        mongoPassword = urllib.parse.quote( mongoPassword )
        
        if mongoUsername and mongoPassword:
            mongoURI = "mongodb://{username}:{password}@{host}:{port}/{db}?authSource={authsource}".format(
                username = mongoUsername, password = mongoPassword,
                host = mongoHost, port = mongoPort,
                db = mongoDB, authsource = mongoAuthSource
            )
            connect = pymongo.MongoClient(mongoURI, connect=False, serverSelectionTimeoutMS=10000)
            # To ensure that MongoServer is reachable an raise Exception if not
            connect.server_info()
        else:
            connect = pymongo.MongoClient(mongoHost, mongoPort, connect=False, serverSelectionTimeoutMS=10000)
            # To ensure that MongoServer is reachable an raise Exception if not
            connect.server_info()
    
        return connect[mongoDB]
        
    @classmethod
    def getHostDB(cls):
        mongoHost = cls.readSetting("Mongo", "Host", cls.default['mongoHost'])
        mongoPort = cls.readSetting("Mongo", "Port", cls.default['mongoPort'])
        mongoDB = cls.readSetting("Mongo", "HostDB", cls.default['mongoHostDB'])
        mongoUsername = cls.readSetting("Mongo", "Username", cls.default['mongoUsername'])
        mongoPassword = cls.readSetting("Mongo", "Password", cls.default['mongoPassword'])
        mongoAuthSource = cls.readSetting("Mongo", "AuthSource", cls.default['mongoAuthSource'])

        mongoUsername = urllib.parse.quote( mongoUsername )
        mongoPassword = urllib.parse.quote( mongoPassword )
    
        if mongoUsername and mongoPassword:
            mongoURI = "mongodb://{username}:{password}@{host}:{port}/{db}?authSource={authsource}".format(
                username = mongoUsername, password = mongoPassword,
                host = mongoHost, port = mongoPort,
                db = mongoDB, authsource = mongoAuthSource
            )
            connect = pymongo.MongoClient(mongoURI, connect=False, serverSelectionTimeoutMS=10000)
            # To ensure that MongoServer is reachable an raise Exception if not
            connect.server_info()
        else:
            connect = pymongo.MongoClient(mongoHost, mongoPort, connect=False, serverSelectionTimeoutMS=10000)
            # To ensure that MongoServer is reachable an raise Exception if not
            connect.server_info()
        return connect[mongoDB]
        
    @classmethod
    def getFixDB(cls):
        mongoHost = cls.readSetting("Mongo", "Host", cls.default['mongoHost'])
        mongoPort = cls.readSetting("Mongo", "Port", cls.default['mongoPort'])
        mongoDB = cls.readSetting("Mongo", "FixDB", cls.default['mongoFixDB'])
        mongoUsername = cls.readSetting("Mongo", "Username", cls.default['mongoUsername'])
        mongoPassword = cls.readSetting("Mongo", "Password", cls.default['mongoPassword'])
        mongoAuthSource = cls.readSetting("Mongo", "AuthSource", cls.default['mongoAuthSource'])

        mongoUsername = urllib.parse.quote( mongoUsername )
        mongoPassword = urllib.parse.quote( mongoPassword )
        if mongoUsername and mongoPassword:
            mongoURI = "mongodb://{username}:{password}@{host}:{port}/{db}?authSource={authsource}".format(
                username = mongoUsername, password = mongoPassword,
                host = mongoHost, port = mongoPort,
                db = mongoDB, authsource = mongoAuthSource
            )
            connect = pymongo.MongoClient(mongoURI, connect=False, serverSelectionTimeoutMS=10000)
            # To ensure that MongoServer is reachable an raise Exception if not
            connect.server_info()
        else:
            connect = pymongo.MongoClient(mongoHost, mongoPort, connect=False, serverSelectionTimeoutMS=10000)
            # To ensure that MongoServer is reachable an raise Exception if not
            connect.server_info()
        return connect[mongoDB]
        
    # MongoTest
    @classmethod
    def getTestDB(cls):
        mongoHost = cls.readSetting("MongoTest", "Host", cls.default['mongoHost'])
        mongoPort = cls.readSetting("MongoTest", "Port", cls.default['mongoPort'])
        mongoDB = cls.readSetting("MongoTest", "testDB", cls.default['testmongoDB'])
        mongoUsername = cls.readSetting("MongoTest", "Username", cls.default['mongoUsername'])
        mongoPassword = cls.readSetting("MongoTest", "Password", cls.default['mongoPassword'])
        mongoAuthSource = cls.readSetting("MongoTest", "AuthSource", cls.default['mongoAuthSource'])

        mongoUsername = urllib.parse.quote( mongoUsername )
        mongoPassword = urllib.parse.quote( mongoPassword )
        if mongoUsername and mongoPassword:
            mongoURI = "mongodb://{username}:{password}@{host}:{port}/{db}?authSource={authsource}".format(
                username = mongoUsername, password = mongoPassword,
                host = mongoHost, port = mongoPort,
                db = mongoDB, authsource = mongoAuthSource
            )
            connect = pymongo.MongoClient(mongoURI, connect=False, serverSelectionTimeoutMS=10000)
            # To ensure that MongoServer is reachable an raise Exception if not
            connect.server_info()
            
        else:
            connect = pymongo.MongoClient(mongoHost, mongoPort, connect=False, serverSelectionTimeoutMS=10000)
            # To ensure that MongoServer is reachable an raise Exception if not
            connect.server_info()
        return connect[mongoDB]


     # Webserver
    @classmethod
    def getPageLength(cls):
        return cls.readSetting("Webserver", "PageLength", cls.default['pageLength'])

    # Debsecan
    @classmethod
    def getDebsecanConf(cls):
        url = cls.readSetting("Debsecan", "url", cls.default['url']) 
        backup_file_path = cls.readSetting("Debsecan", "backup_file_path", cls.default['backup_file_path'])
        return (url, backup_file_path)

    # Ubuntu
    @classmethod
    def getUCTBranch(cls):
        return cls.readSetting("Ubuntu", "UCTBranch", cls.default['uctBranch'])
        
    @classmethod
    def getUCTConfFile(cls):
        return cls.readSetting("Ubuntu", "UCTConfFile", cls.default['uctConfFile'])
        
    @classmethod
    def getUCTPath(cls):
        return cls.readSetting("Ubuntu", "UCTPath", cls.default['uctPath'])
        
    # Madison
    @classmethod
    def getFakeReposPath(cls):
        return cls.readSetting("Madison", "FakeReposPath", cls.default['fakeReposPath'])
    
    @classmethod
    def getDebianArchiveURL(cls):
        return cls.readSetting("Madison", "DebianArchiveURL", cls.default['debianArchiveURL'])
        
    @classmethod
    def getDebianSecurityArchiveURL(cls):
        return cls.readSetting("Madison", "DebianSecurityArchiveURL", cls.default['debianSecurityArchiveURL'])
        
    @classmethod
    def getUbuntuArchiveURL(cls):
        return cls.readSetting("Madison", "UbuntuArchiveURL", cls.default['ubuntuArchiveURL'])
    

    # CVESearchAPI
    @classmethod
    def getCVESearchAPIHost(cls):
        return cls.readSetting("CVESearchAPI", "Host", cls.default['cvesearchAPIHost'])

    @classmethod
    def getCVESearchAPIPort(cls):
        return cls.readSetting("CVESearchAPI", "Port", cls.default['cvesearchAPIPort'])
    
    # IvulncheckAPI
    @classmethod
    def getRulesFile(cls):
        return cls.readSetting("IvulncheckAPI", "RulesFile", cls.default['rulesFile'])

    # Logging
    @classmethod
    def getLogfile(cls):
        return cls.readSetting("Logging", "Logfile", cls.default['logfile'])


class ConfigReader():
    def __init__(self, file):
        self.ConfigParser = configparser.ConfigParser()
        self.ConfigParser.read(file)

    def read(self, section, item, default):
        result = default
        try:
            if type(default) == bool:
                result = self.ConfigParser.getboolean(section, item)
            elif type(default) == int:
                result = self.ConfigParser.getint(section, item)
            else:
                result = self.ConfigParser.get(section, item)
        except:
            pass
        return result
