# Path: txircd/modbase.py
# class Command(object):
#     def hook(self, base):
#         self.ircd = base
#         return self
#     def onUse(self, user, data):
#         pass
#     def processParams(self, user, params):
#         return {
#             "user": user,
#             "params": params
#         }
#     def updateActivity(self, user):
#         user.lastactivity = now()
# 
# Path: txircd/utils.py
# def crypt(word, salt=None, iterations=1000, algorithm="sha256", bytes=24):
#     """PBKDF2-based unix crypt(3) replacement.
# 
#     The number of iterations specified in the salt overrides the 'iterations'
#     parameter.
#     """
#     
#     # Reserve algorithms
#     algos = {
#         "md5": md5,
#         "sha1": sha1,
#         "sha224": sha224,
#         "sha256": sha256,
#         "sha384": sha384,
#         "sha512": sha512
#     }
#     
#     # Generate a (pseudo-)random salt if the user hasn't provided one.
#     if salt is None:
#         salt = _makesalt()
# 
#     # salt must be a string or the us-ascii subset of unicode
#     if isunicode(salt):
#         salt = salt.encode('us-ascii').decode('us-ascii')
#     elif isbytes(salt):
#         salt = salt.decode('us-ascii')
#     else:
#         raise TypeError("salt must be a string")
# 
#     # word must be a string or unicode (in the latter case, we convert to UTF-8)
#     if isunicode(word):
#         word = word.encode("UTF-8")
#     elif not isbytes(word):
#         raise TypeError("word must be a string or unicode")
# 
#     # Try to extract the real salt and iteration count from the salt
#     if ":" in salt:
#         (algorithm, iterations, salt, oldhash) = salt.split(":")
#         if iterations != "":
#             iterations = int(iterations)
#             if iterations < 1:
#                 raise ValueError("Invalid salt")
#         bytes = len(b64decode(oldhash))
# 
#     # Make sure the salt matches the allowed character set
#     allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/="
#     for ch in salt:
#         if ch not in allowed:
#             raise ValueError("Illegal character {!r} in salt".format(ch))
#     
#     if algorithm not in algos:
#         raise ValueError("Invalid algorithm: {}".format(algorithm))
# 
#     hash = b64encode(PBKDF2(word, salt, iterations, algos[algorithm]).read(bytes))
#     return "{}:{!s}:{}:{}".format(algorithm, iterations, salt, hash)


from twisted.words.protocols import irc
from txircd.modbase import Command
from txircd.utils import crypt

class OperCommand(Command):
    def onUse(self, user, data):
        if data["username"] not in self.ircd.servconfig["oper_logins"]:
            user.sendMessage(irc.ERR_PASSWDMISMATCH, ":Password incorrect")
            if "sendservernotice" in self.ircd.module_data_cache:
                self.ircd.module_data_cache["sendservernotice"]("oper", "Failed OPER attempt from {} (bad username)".format(user.nickname))
        elif self.ircd.servconfig["oper_logins"][data["username"]] != crypt(data["password"], self.ircd.servconfig["oper_logins"][data["username"]]):
            user.sendMessage(irc.ERR_PASSWDMISMATCH, ":Password incorrect")
            if "sendservernotice" in self.ircd.module_data_cache:
                self.ircd.module_data_cache["sendservernotice"]("oper", "Failed OPER attempt from {} (bad password)".format(user.nickname))
        else:
            user.setMode(None, "+o", [])

# Path: txircd/modbase.py
# class Command(object):
#     def hook(self, base):
#         self.ircd = base
#         return self
#     def onUse(self, user, data):
#         pass
#     def processParams(self, user, params):
#         return {
#             "user": user,
#             "params": params
#         }
#     def updateActivity(self, user):
#         user.lastactivity = now()
# 
# Path: txircd/utils.py
# def crypt(word, salt=None, iterations=1000, algorithm="sha256", bytes=24):
#     """PBKDF2-based unix crypt(3) replacement.
# 
#     The number of iterations specified in the salt overrides the 'iterations'
#     parameter.
#     """
#     
#     # Reserve algorithms
#     algos = {
#         "md5": md5,
#         "sha1": sha1,
#         "sha224": sha224,
#         "sha256": sha256,
#         "sha384": sha384,
#         "sha512": sha512
#     }
#     
#     # Generate a (pseudo-)random salt if the user hasn't provided one.
#     if salt is None:
#         salt = _makesalt()
# 
#     # salt must be a string or the us-ascii subset of unicode
#     if isunicode(salt):
#         salt = salt.encode('us-ascii').decode('us-ascii')
#     elif isbytes(salt):
#         salt = salt.decode('us-ascii')
#     else:
#         raise TypeError("salt must be a string")
# 
#     # word must be a string or unicode (in the latter case, we convert to UTF-8)
#     if isunicode(word):
#         word = word.encode("UTF-8")
#     elif not isbytes(word):
#         raise TypeError("word must be a string or unicode")
# 
#     # Try to extract the real salt and iteration count from the salt
#     if ":" in salt:
#         (algorithm, iterations, salt, oldhash) = salt.split(":")
#         if iterations != "":
#             iterations = int(iterations)
#             if iterations < 1:
#                 raise ValueError("Invalid salt")
#         bytes = len(b64decode(oldhash))
# 
#     # Make sure the salt matches the allowed character set
#     allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/="
#     for ch in salt:
#         if ch not in allowed:
#             raise ValueError("Illegal character {!r} in salt".format(ch))
#     
#     if algorithm not in algos:
#         raise ValueError("Invalid algorithm: {}".format(algorithm))
# 
#     hash = b64encode(PBKDF2(word, salt, iterations, algos[algorithm]).read(bytes))
#     return "{}:{!s}:{}:{}".format(algorithm, iterations, salt, hash)


# Path: txircd/modules/cmd_oper.py
from twisted.words.protocols import irc
from txircd.modbase import Command
from txircd.utils import crypt


class OperCommand(Command):
    def onUse(self, user, data):
        if data["username"] not in self.ircd.servconfig["oper_logins"]:
            user.sendMessage(irc.ERR_PASSWDMISMATCH, ":Password incorrect")
            if "sendservernotice" in self.ircd.module_data_cache:
                self.ircd.module_data_cache["sendservernotice"]("oper", "Failed OPER attempt from {} (bad username)".format(user.nickname))
        elif self.ircd.servconfig["oper_logins"][data["username"]] != crypt(data["password"], self.ircd.servconfig["oper_logins"][data["username"]]):
            user.sendMessage(irc.ERR_PASSWDMISMATCH, ":Password incorrect")
            if "sendservernotice" in self.ircd.module_data_cache:
                self.ircd.module_data_cache["sendservernotice"]("oper", "Failed OPER attempt from {} (bad password)".format(user.nickname))
        else:
            user.setMode(None, "+o", [])

            user.sendMessage(irc.RPL_YOUREOPER, ":You are now an IRC operator")