Example #1
0
    def __init__(self, headers):
        self.expires = None
        self.mtime = None
        self.length = 0
        self.start = 0
        self.size = 0
        self.mimeType = None

        headers = InsensitiveDict(headers)

        encoding = headers.get("Transfer-Encoding", None)
        if encoding == 'chunked':
            raise errors.FlumotionError("Chunked transfer not supported")

        expires = headers.get("Expires", None)
        if expires is not None:
            try:
                self.expires = http.stringToDatetime(expires)
            except:
                self.expires = 0

        lastmod = headers.get("Last-Modified", None)
        if lastmod is not None:
            self.mtime = http.stringToDatetime(lastmod)

        range = headers.get("Content-Range", None)
        length = headers.get("Content-Length", None)
        if range is not None:
            start, end, total = http.parseContentRange(range)
            self.start = start
            self.length = total
            if length is not None:
                self.size = int(length)
            else:
                self.size = end - start
        elif length is not None:
            self.length = int(length)
            self.size = int(length)
        else:
            raise errors.FlumotionError("Can't get length/size from headers",
                                        headers)

        ctype = headers.get("Content-Type", None)
        if ctype is not None:
            self.mimeType, _pdict = cgi.parse_header(ctype)
Example #2
0
    def __init__(self, headers):
        self.expires = None
        self.mtime = None
        self.length = 0
        self.start = 0
        self.size = 0
        self.mimeType = None

        headers = InsensitiveDict(headers)

        encoding = headers.get("Transfer-Encoding", None)
        if encoding == 'chunked':
            raise errors.FlumotionError("Chunked transfer not supported")

        expires = headers.get("Expires", None)
        if expires is not None:
            try:
                self.expires = http.stringToDatetime(expires)
            except:
                self.expires = 0

        lastmod = headers.get("Last-Modified", None)
        if lastmod is not None:
            self.mtime = http.stringToDatetime(lastmod)

        range = headers.get("Content-Range", None)
        length = headers.get("Content-Length", None)
        if range is not None:
            start, end, total = http.parseContentRange(range)
            self.start = start
            self.length = total
            if length is not None:
                self.size = int(length)
            else:
                self.size = end - start
        elif length is not None:
            self.length = int(length)
            self.size = int(length)
        else:
            raise errors.FlumotionError("Can't get length/size from headers",
                                        headers)

        ctype = headers.get("Content-Type", None)
        if ctype is not None:
            self.mimeType, _pdict = cgi.parse_header(ctype)
Example #3
0
class IRCBot(irc.IRCClient):
    sasl_buffer = ""
    sasl_result = None
    sasl_login = None

    def __init__(self, factory, plugin):
        self.factory = factory
        self.nickname = plugin.nickname.encode('ascii')
        self.realname = plugin.realname.encode('ascii')
        self.username = plugin.ident.encode('ascii')
        self.ns_username = plugin.username
        self.ns_password = plugin.password
        self.password = plugin.server_password.encode('ascii')
        self.channel = plugin.channel.encode('ascii')
        self.key = plugin.key.encode('ascii')
        self.console = plugin.console
        self.irc_message = plugin.irc_message
        self.irc_action = plugin.irc_action
        self.irc_chat_status = plugin.irc_chat_status
        self.mangle_username = plugin.mangle_username

        self.users = InsensitiveDict()
        self.cap_requests = set()

    def register(self, nickname, hostname="foo", servername="bar"):
        self.sendLine("CAP LS")
        return irc.IRCClient.register(self, nickname, hostname, servername)

    def sendLine(self, line):
        irc.IRCClient.sendLine(self, line.encode('ascii', 'replace'))

    def _parse_cap(self, cap):
        mod = ''
        while cap[0] in "-~=":
            mod, cap = mod + cap[0], cap[1:]
        if '/' in cap:
            vendor, cap = cap.split('/', 1)
        else:
            vendor = None
        return (cap, mod, vendor)

    def request_cap(self, *caps):
        self.cap_requests |= set(caps)
        self.sendLine("CAP REQ :{}".format(' '.join(caps)))

    @defer.inlineCallbacks
    def end_cap(self):
        if self.sasl_result:
            yield self.sasl_result
        self.sendLine("CAP END")

    def irc_CAP(self, prefix, params):
        self.supports_cap = True
        identifier, subcommand, args = params
        args = args.split(' ')
        if subcommand == "LS":
            self.sasl_start(args)
            if not self.cap_requests:
                self.sendLine("CAP END")
        elif subcommand == "ACK":
            ack = []
            for cap in args:
                if not cap:
                    continue
                cap, mod, vendor = self._parse_cap(cap)
                if '-' in mod:
                    if cap in self.capabilities:
                        del self.capabilities[cap]
                    continue
                self.cap_requests.remove(cap)
                if cap == 'sasl':
                    self.sasl_next()
            if ack:
                self.sendLine("CAP ACK :{}".format(' '.join(ack)))
            if not self.cap_requests:
                self.end_cap()
        elif subcommand == "NAK":
            # this implementation is probably not compliant but it will have to do for now
            for cap in args:
                self.cap_requests.remove(cap)
            if not self.cap_requests:
                self.end_cap()

    def signedOn(self):
        if ISSLTransport.providedBy(self.transport):
            cert = self.transport.getPeerCertificate()
            fp = cert.digest("sha1")
            verified = "verified" if self.factory.parent.server_fingerprint else "unverified"
            self.console(
                "irc: connected securely. server fingerprint: {} ({})".format(
                    fp, verified))
        else:
            self.console("irc: connected")

        if self.ns_username and self.ns_password and not self.sasl_login:
            self.msg(
                'NickServ', 'IDENTIFY {} {}'.format(self.ns_username,
                                                    self.ns_password))

        self.join(self.channel, self.key)

    def irc_JOIN(self, prefix, params):
        nick = prefix.split('!')[0]
        channel = params[-1]
        if nick == self.nickname:
            self.joined(channel)
        else:
            self.userJoined(prefix, channel)

    def joined(self, channel):
        self.console('irc: joined channel')
        self.factory.client = self

        def who(a):
            self.sendLine("WHO " + channel)

        self.factory.parent.repeating_task(who, 30, now=True)

    def isupport(self, args):
        self.compute_prefix_names()

    def compute_prefix_names(self):
        KNOWN_NAMES = {"o": "op", "h": "halfop", "v": "voice"}
        prefixdata = self.supported.getFeature("PREFIX", {
            "o": ("@", 0),
            "v": ("+", 1)
        }).items()
        op_priority = ([
            priority for mode, (prefix, priority) in prefixdata if mode == "o"
        ] + [None])[0]
        self.prefixes, self.statuses, self.priority = {}, {}, {}

        for mode, (prefix, priority) in prefixdata:
            name = "?"
            if mode in KNOWN_NAMES:
                name = KNOWN_NAMES[mode]
            elif priority == 0:
                if op_priority == 2:
                    name = "owner"
                else:
                    name = "admin"
            else:
                name = "+" + mode
            self.prefixes[mode] = prefix
            self.statuses[prefix] = name
            self.priority[name] = priority
            self.priority[mode] = priority
            self.priority[prefix] = priority

    def parse_prefixes(self, user, nick, prefixes=''):
        status = []
        prefixdata = self.supported.getFeature("PREFIX", {
            "o": ("@", 0),
            "v": ("+", 1)
        }).items()
        for mode, (prefix, priority) in prefixdata:
            if prefix in prefixes + nick:
                nick = nick.replace(prefix, '')
                status.append((prefix, priority))
        if nick == self.nickname:
            return
        user.status = ''.join(t[0] for t in sorted(status, key=lambda t: t[1]))

    def irc_RPL_WHOREPLY(self, prefix, params):
        _, channel, username, host, server, nick, status, hg = params
        if nick == self.nickname:
            return
        hops, gecos = hg.split(' ', 1)
        user = IRCUser(self, nick)
        user.username = username
        user.hostname = host
        user.oper = '*' in status
        user.away = status[0] == 'G'
        self.users[nick] = user
        self.parse_prefixes(user, nick, status[1:].replace('*', ''))

    def modeChanged(self, user, channel, _set, modes, args):
        args = list(args)
        if channel.lower() != self.channel.lower():
            return
        for m, arg in zip(modes, args):
            if m in self.prefixes and arg != self.nickname:
                u = self.users.get(arg, None)
                if u:
                    u.status = u.status.replace(self.prefixes[m], '')
                    if _set:
                        u.status = ''.join(
                            sorted(list(u.status + self.prefixes[m]),
                                   key=lambda k: self.priority[k]))

    def has_status(self, nick, status):
        if status != 0 and not status:
            return True
        if status not in self.priority:
            return False
        priority = self.priority[status]
        u = self.users.get(nick, None)
        return u and (u.priority is not None) and u.priority <= priority

    def userJoined(self, user, channel):
        nick = user.split('!')[0]
        user = IRCUser(self, nick)
        self.users[nick] = user

    def userRenamed(self, oldname, newname):
        if oldname not in self.users:
            return
        u = self.users[oldname]
        u.nick = newname
        self.users[newname] = u
        del self.users[oldname]

    def userLeft(self, user, channel):
        if user not in self.users:
            return
        del self.users[user]

    def userKicked(self, kickee, channel, kicker, message):
        if kickee not in self.users:
            return
        del self.users[kickee]

    def userQuit(self, user, quitMessage):
        if user not in self.users:
            return
        del self.users[user]

    def privmsg(self, user, channel, msg):
        if channel != self.channel:
            return
        if '!' not in user:
            return
        nick = user.split('!')[0]
        p = self.factory.parent

        if not self.has_status(nick, self.irc_chat_status):
            return

        if p.irc_players_enabled and msg.lower(
        ) == p.irc_command_prefix + "players":
            self.say(
                self.channel,
                p.irc_players_format.format(
                    players=', '.join(map(self.mangle_username, p.players))))

        elif p.irc_command_prefix and msg.startswith(
                p.irc_command_prefix
        ) and p.irc_command_status and self.has_status(nick,
                                                       p.irc_command_status):
            argv = msg[len(p.irc_command_prefix):].split(' ')
            command = argv[0]
            if command.startswith('~'):
                if p.irc_command_mark2 and (
                        command.lower()
                        in p.irc_command_allow.lower().split(',')
                        or p.irc_command_allow == '*'):
                    p.dispatch(Hook(line=' '.join(argv)))
            else:
                if command.lower() in p.irc_command_allow.lower().split(
                        ',') or p.irc_command_allow == '*':
                    p.send(' '.join(argv))

        else:
            self.irc_message(nick, msg)

    def action(self, user, channel, msg):
        self.console("%s %s %s" % (user, channel, msg))
        if channel != self.channel:
            return
        if '!' not in user:
            return
        nick = user.split('!')[0]

        if self.has_status(nick, self.irc_chat_status):
            self.irc_action(nick, msg)

    def irc_AUTHENTICATE(self, prefix, params):
        self.sasl_continue(params[0])

    def sasl_send(self, data):
        while data and len(data) >= 400:
            en, data = data[:400].encode('base64').replace('\n',
                                                           ''), data[400:]
            self.sendLine("AUTHENTICATE " + en)
        if data:
            self.sendLine("AUTHENTICATE " +
                          data.encode('base64').replace('\n', ''))
        else:
            self.sendLine("AUTHENTICATE +")

    def sasl_start(self, cap_list):
        if 'sasl' not in cap_list:
            print(cap_list)
            return
        self.request_cap('sasl')
        self.sasl_result = defer.Deferred()
        self.sasl_mechanisms = list(SASL_MECHANISMS)

    def sasl_next(self):
        mech = None
        while not mech or not mech.is_valid():
            if not self.sasl_mechanisms:
                return False
            self.sasl_auth = mech = self.sasl_mechanisms.pop(0)(
                self.ns_username, self.ns_password)
        self.sendLine("AUTHENTICATE " + self.sasl_auth.name)
        return True

    def sasl_continue(self, data):
        if data == '+':
            data = ''
        else:
            data = data.decode('base64')
        if len(data) == 400:
            self.sasl_buffer += data
        else:
            response = self.sasl_auth.respond(self.sasl_buffer + data)
            if response is False:  # abort
                self.sendLine("AUTHENTICATE *")
            else:
                self.sasl_send(response)
            self.sasl_buffer = ""

    def sasl_finish(self):
        if self.sasl_result:
            self.sasl_result.callback(True)
            self.sasl_result = None

    def sasl_failed(self, whine=True):
        if self.sasl_login is False:
            return
        if self.sasl_next():
            return
        self.sasl_login = False
        self.sendLine("AUTHENTICATE *")
        self.sasl_finish()
        if whine:
            self.console("irc: failed to log in.")

    def irc_904(self, prefix, params):
        print(params)
        self.sasl_failed()

    def irc_905(self, prefix, params):
        print(params)
        self.sasl_failed()

    def irc_906(self, prefix, params):
        self.sasl_failed(False)

    def irc_907(self, prefix, params):
        self.sasl_failed(False)

    def irc_900(self, prefix, params):
        self.sasl_login = params[2]
        self.console("irc: logged in as '{}' (using {})".format(
            self.sasl_login, self.sasl_auth.name))

    def irc_903(self, prefix, params):
        self.sasl_finish()

    def alterCollidedNick(self, nickname):
        return nickname + '_'

    def irc_relay(self, message):
        self.say(self.channel, message.encode('utf8'))
Example #4
0
class Element(Node):

    preserveCase = 0
    caseInsensitive = 1
    nsprefixes = None
    namespace = ''

    def __init__(self, tagName, attributes=None, parentNode=None,
                        filename=None, markpos=None,
                        caseInsensitive=1, preserveCase=0,
                 namespace=''):
        Node.__init__(self, parentNode)
        self.preserveCase = preserveCase or not caseInsensitive
        self.caseInsensitive = caseInsensitive
        if not preserveCase:
            tagName = tagName.lower()
        if attributes is None:
            self.attributes = {}
        else:
            self.attributes = attributes
            for k, v in self.attributes.items():
                self.attributes[k] = unescape(v)

        if caseInsensitive:
            self.attributes = InsensitiveDict(self.attributes, 
                                              preserve=preserveCase)

        self.endTagName = self.nodeName = self.tagName = tagName
        self._filename = filename
        self._markpos = markpos
        self.namespace = namespace

    def addPrefixes(self, pfxs):
        if self.nsprefixes is None:
            self.nsprefixes = pfxs
        else:
            self.nsprefixes.update(pfxs)

    def endTag(self, endTagName):
        if not self.preserveCase:
            endTagName = endTagName.lower()
        self.endTagName = endTagName

    def isEqualToElement(self, n):
        if self.caseInsensitive:
            return (self.attributes == n.attributes) and (self.nodeName.lower() == n.nodeName.lower())
        return (self.attributes == n.attributes) and (self.nodeName == n.nodeName)

    def cloneNode(self, deep=0, parent=None):
        clone = Element(
            self.tagName, parentNode=parent, namespace=self.namespace,
            preserveCase=self.preserveCase, caseInsensitive=self.caseInsensitive)
        clone.attributes.update(self.attributes)
        if deep:
            clone.childNodes = [child.cloneNode(1, clone) for child in self.childNodes]
        else:
            clone.childNodes = []
        return clone

    def getElementsByTagName(self, name):
        if self.caseInsensitive:
            return getElementsByTagNameNoCase(self, name)
        return getElementsByTagName(self, name)

    def hasAttributes(self):
        return 1

    def getAttribute(self, name, default=None):
        return self.attributes.get(name, default)

    def getAttributeNS(self, ns, name, default=None):
        nsk = (ns, name)
        if self.attributes.has_key(nsk):
            return self.attributes[nsk]
        if ns == self.namespace:
            return self.attributes.get(name, default)
        return default

    def getAttributeNode(self, name):
        return _Attr(self.getAttribute(name), self)

    def setAttribute(self, name, attr):
        self.attributes[name] = attr

    def removeAttribute(self, name):
        if name in self.attributes:
            del self.attributes[name]

    def removeAttribute_has_key(self, name):
        if self.attributes.has_key(name):
            del self.attributes[name]

    def hasAttribute(self, name):
        return name in self.attributes

    def hasAttribute_has_key(self, name):
        return self.attributes.has_key(name)

    if dictsAreNotSequences:
        hasAttribute = hasAttribute_has_key
        removeAttribute = removeAttribute_has_key

    def writexml(self, stream, indent='', addindent='', newl='', strip=0, nsprefixes={}, namespace=''):
        # write beginning
        ALLOWSINGLETON = ('img', 'br', 'hr', 'base', 'meta', 'link', 'param',
                          'area', 'input', 'col', 'basefont', 'isindex',
                          'frame')
        BLOCKELEMENTS = ('html', 'head', 'body', 'noscript', 'ins', 'del',
                         'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'script',
                         'ul', 'ol', 'dl', 'pre', 'hr', 'blockquote',
                         'address', 'p', 'div', 'fieldset', 'table', 'tr',
                         'form', 'object', 'fieldset', 'applet', 'map')
        FORMATNICELY = ('tr', 'ul', 'ol', 'head')

        # this should never be necessary unless people start
        # changing .tagName on the fly(?)
        if not self.preserveCase:
            self.endTagName = self.tagName
        w = stream.write
        if self.nsprefixes:
            newprefixes = self.nsprefixes.copy()
            for ns in nsprefixes.keys():
                del newprefixes[ns]
        else:
             newprefixes = {}

        begin = ['<']
        if self.tagName in BLOCKELEMENTS:
            begin = [newl, indent] + begin
        bext = begin.extend
        writeattr = lambda _atr, _val: bext((' ', _atr, '="', escape(_val), '"'))
        if namespace != self.namespace and self.namespace:
            if nsprefixes.has_key(self.namespace):
                prefix = nsprefixes[self.namespace]
                bext(prefix+':'+self.tagName)
            else:
                bext(self.tagName)
                writeattr("xmlns", self.namespace)
        else:
            bext(self.tagName)
        j = ''.join
        for attr, val in self.attributes.iteritems():
            if isinstance(attr, tuple):
                ns, key = attr
                if nsprefixes.has_key(ns):
                    prefix = nsprefixes[ns]
                else:
                    prefix = genprefix()
                    newprefixes[ns] = prefix
                assert val is not None
                writeattr(prefix+':'+key,val)
            else:
                assert val is not None
                writeattr(attr, val)
        if newprefixes:
            for ns, prefix in newprefixes.iteritems():
                if prefix:
                    writeattr('xmlns:'+prefix, ns)
            newprefixes.update(nsprefixes)
            downprefixes = newprefixes
        else:
            downprefixes = nsprefixes
        w(j(begin))
        if self.childNodes:
            w(">")
            newindent = indent + addindent
            for child in self.childNodes:
                if self.tagName in BLOCKELEMENTS and \
                   self.tagName in FORMATNICELY:
                    w(j((newl, newindent)))
                child.writexml(stream, newindent, addindent, newl, strip, downprefixes, self.namespace)
            if self.tagName in BLOCKELEMENTS:
                w(j((newl, indent)))
            w(j(("</", self.endTagName, '>')))
            
        elif self.tagName.lower() not in ALLOWSINGLETON:
            w(j(('></', self.endTagName, '>')))
        else:
            w(" />")

    def __repr__(self):
        rep = "Element(%s" % repr(self.nodeName)
        if self.attributes:
            rep += ", attributes=%r" % (self.attributes,)
        if self._filename:
            rep += ", filename=%r" % (self._filename,)
        if self._markpos:
            rep += ", markpos=%r" % (self._markpos,)
        return rep + ')'

    def __str__(self):
        rep = "<" + self.nodeName
        if self._filename or self._markpos:
            rep += " ("
        if self._filename:
            rep += repr(self._filename)
        if self._markpos:
            rep += " line %s column %s" % self._markpos
        if self._filename or self._markpos:
            rep += ")"
        for item in self.attributes.items():
            rep += " %s=%r" % item
        if self.hasChildNodes():
            rep += " >...</%s>" % self.nodeName
        else:
            rep += " />"
        return rep
Example #5
0
class Element(Node):

    preserveCase = 0
    caseInsensitive = 1
    nsprefixes = None

    def __init__(self,
                 tagName,
                 attributes=None,
                 parentNode=None,
                 filename=None,
                 markpos=None,
                 caseInsensitive=1,
                 preserveCase=0,
                 namespace=None):
        Node.__init__(self, parentNode)
        self.preserveCase = preserveCase or not caseInsensitive
        self.caseInsensitive = caseInsensitive
        if not preserveCase:
            tagName = tagName.lower()
        if attributes is None:
            self.attributes = {}
        else:
            self.attributes = attributes
            for k, v in self.attributes.items():
                self.attributes[k] = unescape(v)

        if caseInsensitive:
            self.attributes = InsensitiveDict(self.attributes,
                                              preserve=preserveCase)

        self.endTagName = self.nodeName = self.tagName = tagName
        self._filename = filename
        self._markpos = markpos
        self.namespace = namespace

    def addPrefixes(self, pfxs):
        if self.nsprefixes is None:
            self.nsprefixes = pfxs
        else:
            self.nsprefixes.update(pfxs)

    def endTag(self, endTagName):
        if not self.preserveCase:
            endTagName = endTagName.lower()
        self.endTagName = endTagName

    def isEqualToElement(self, n):
        if self.caseInsensitive:
            return ((self.attributes == n.attributes)
                    and (self.nodeName.lower() == n.nodeName.lower()))
        return (self.attributes == n.attributes) and (self.nodeName
                                                      == n.nodeName)

    def isEqualToNode(self, other):
        """
        Compare this element to C{other}.  If the C{nodeName}, C{namespace},
        C{attributes}, and C{childNodes} are all the same, return C{True},
        otherwise return C{False}.
        """
        return (self.nodeName.lower() == other.nodeName.lower()
                and self.namespace == other.namespace
                and self.attributes == other.attributes
                and Node.isEqualToNode(self, other))

    def cloneNode(self, deep=0, parent=None):
        clone = Element(self.tagName,
                        parentNode=parent,
                        namespace=self.namespace,
                        preserveCase=self.preserveCase,
                        caseInsensitive=self.caseInsensitive)
        clone.attributes.update(self.attributes)
        if deep:
            clone.childNodes = [
                child.cloneNode(1, clone) for child in self.childNodes
            ]
        else:
            clone.childNodes = []
        return clone

    def getElementsByTagName(self, name):
        if self.caseInsensitive:
            return getElementsByTagNameNoCase(self, name)
        return getElementsByTagName(self, name)

    def hasAttributes(self):
        return 1

    def getAttribute(self, name, default=None):
        return self.attributes.get(name, default)

    def getAttributeNS(self, ns, name, default=None):
        nsk = (ns, name)
        if nsk in self.attributes:
            return self.attributes[nsk]
        if ns == self.namespace:
            return self.attributes.get(name, default)
        return default

    def getAttributeNode(self, name):
        return _Attr(self.getAttribute(name), self)

    def setAttribute(self, name, attr):
        self.attributes[name] = attr

    def removeAttribute(self, name):
        if name in self.attributes:
            del self.attributes[name]

    def hasAttribute(self, name):
        return name in self.attributes

    def writexml(self,
                 stream,
                 indent='',
                 addindent='',
                 newl='',
                 strip=0,
                 nsprefixes={},
                 namespace=''):
        """
        Serialize this L{Element} to the given stream.

        @param stream: A file-like object to which this L{Element} will be
            written.

        @param nsprefixes: A C{dict} mapping namespace URIs as C{str} to
            prefixes as C{str}.  This defines the prefixes which are already in
            scope in the document at the point at which this L{Element} exists.
            This is essentially an implementation detail for namespace support.
            Applications should not try to use it.

        @param namespace: The namespace URI as a C{str} which is the default at
            the point in the document at which this L{Element} exists.  This is
            essentially an implementation detail for namespace support.
            Applications should not try to use it.
        """
        # write beginning
        ALLOWSINGLETON = ('img', 'br', 'hr', 'base', 'meta', 'link', 'param',
                          'area', 'input', 'col', 'basefont', 'isindex',
                          'frame')
        BLOCKELEMENTS = ('html', 'head', 'body', 'noscript', 'ins', 'del',
                         'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'script', 'ul',
                         'ol', 'dl', 'pre', 'hr', 'blockquote', 'address', 'p',
                         'div', 'fieldset', 'table', 'tr', 'form', 'object',
                         'fieldset', 'applet', 'map')
        FORMATNICELY = ('tr', 'ul', 'ol', 'head')

        # this should never be necessary unless people start
        # changing .tagName on the fly(?)
        if not self.preserveCase:
            self.endTagName = self.tagName
        w = stream.write
        if self.nsprefixes:
            newprefixes = self.nsprefixes.copy()
            for ns in nsprefixes.keys():
                if ns in newprefixes:
                    del newprefixes[ns]
        else:
            newprefixes = {}

        begin = ['<']
        if self.tagName in BLOCKELEMENTS:
            begin = [newl, indent] + begin
        bext = begin.extend
        writeattr = lambda _atr, _val: bext(
            (' ', _atr, '="', escape(_val), '"'))

        # Make a local for tracking what end tag will be used.  If namespace
        # prefixes are involved, this will be changed to account for that
        # before it's actually used.
        endTagName = self.endTagName

        if namespace != self.namespace and self.namespace is not None:
            # If the current default namespace is not the namespace of this tag
            # (and this tag has a namespace at all) then we'll write out
            # something related to namespaces.
            if self.namespace in nsprefixes:
                # This tag's namespace already has a prefix bound to it.  Use
                # that prefix.
                prefix = nsprefixes[self.namespace]
                bext(prefix + ':' + self.tagName)
                # Also make sure we use it for the end tag.
                endTagName = prefix + ':' + self.endTagName
            else:
                # This tag's namespace has no prefix bound to it.  Change the
                # default namespace to this tag's namespace so we don't need
                # prefixes.  Alternatively, we could add a new prefix binding.
                # I'm not sure why the code was written one way rather than the
                # other. -exarkun
                bext(self.tagName)
                writeattr("xmlns", self.namespace)
                # The default namespace just changed.  Make sure any children
                # know about this.
                namespace = self.namespace
        else:
            # This tag has no namespace or its namespace is already the default
            # namespace.  Nothing extra to do here.
            bext(self.tagName)

        j = ''.join
        for attr, val in sorted(self.attributes.items()):
            if isinstance(attr, tuple):
                ns, key = attr
                if ns in nsprefixes:
                    prefix = nsprefixes[ns]
                else:
                    prefix = genprefix()
                    newprefixes[ns] = prefix
                assert val is not None
                writeattr(prefix + ':' + key, val)
            else:
                assert val is not None
                writeattr(attr, val)
        if newprefixes:
            for ns, prefix in newprefixes.iteritems():
                if prefix:
                    writeattr('xmlns:' + prefix, ns)
            newprefixes.update(nsprefixes)
            downprefixes = newprefixes
        else:
            downprefixes = nsprefixes
        w(j(begin))
        if self.childNodes:
            w(">")
            newindent = indent + addindent
            for child in self.childNodes:
                if self.tagName in BLOCKELEMENTS and \
                   self.tagName in FORMATNICELY:
                    w(j((newl, newindent)))
                child.writexml(stream, newindent, addindent, newl, strip,
                               downprefixes, namespace)
            if self.tagName in BLOCKELEMENTS:
                w(j((newl, indent)))
            w(j(('</', endTagName, '>')))
        elif self.tagName.lower() not in ALLOWSINGLETON:
            w(j(('></', endTagName, '>')))
        else:
            w(" />")

    def __repr__(self):
        rep = "Element(%s" % repr(self.nodeName)
        if self.attributes:
            rep += ", attributes=%r" % (self.attributes, )
        if self._filename:
            rep += ", filename=%r" % (self._filename, )
        if self._markpos:
            rep += ", markpos=%r" % (self._markpos, )
        return rep + ')'

    def __str__(self):
        rep = "<" + self.nodeName
        if self._filename or self._markpos:
            rep += " ("
        if self._filename:
            rep += repr(self._filename)
        if self._markpos:
            rep += " line %s column %s" % self._markpos
        if self._filename or self._markpos:
            rep += ")"
        for item in self.attributes.items():
            rep += " %s=%r" % item
        if self.hasChildNodes():
            rep += " >...</%s>" % self.nodeName
        else:
            rep += " />"
        return rep
Example #6
0
class Element(Node):

    preserveCase = 0
    caseInsensitive = 1
    nsprefixes = None

    def __init__(self,
                 tagName,
                 attributes=None,
                 parentNode=None,
                 filename=None,
                 markpos=None,
                 caseInsensitive=1,
                 preserveCase=0,
                 namespace=None):
        Node.__init__(self, parentNode)
        self.preserveCase = preserveCase or not caseInsensitive
        self.caseInsensitive = caseInsensitive
        if not preserveCase:
            tagName = tagName.lower()
        if attributes is None:
            self.attributes = {}
        else:
            self.attributes = attributes
            for k, v in self.attributes.items():
                self.attributes[k] = unescape(v)

        if caseInsensitive:
            self.attributes = InsensitiveDict(self.attributes,
                                              preserve=preserveCase)

        self.endTagName = self.nodeName = self.tagName = tagName
        self._filename = filename
        self._markpos = markpos
        self.namespace = namespace

    def addPrefixes(self, pfxs):
        if self.nsprefixes is None:
            self.nsprefixes = pfxs
        else:
            self.nsprefixes.update(pfxs)

    def endTag(self, endTagName):
        if not self.preserveCase:
            endTagName = endTagName.lower()
        self.endTagName = endTagName

    def isEqualToElement(self, n):
        if self.caseInsensitive:
            return ((self.attributes == n.attributes)
                    and (self.nodeName.lower() == n.nodeName.lower()))
        return (self.attributes == n.attributes) and (self.nodeName
                                                      == n.nodeName)

    def isEqualToNode(self, other):
        """
        Compare this element to C{other}.  If the C{nodeName}, C{namespace},
        C{attributes}, and C{childNodes} are all the same, return C{True},
        otherwise return C{False}.
        """
        return (self.nodeName.lower() == other.nodeName.lower()
                and self.namespace == other.namespace
                and self.attributes == other.attributes
                and Node.isEqualToNode(self, other))

    def cloneNode(self, deep=0, parent=None):
        clone = Element(self.tagName,
                        parentNode=parent,
                        namespace=self.namespace,
                        preserveCase=self.preserveCase,
                        caseInsensitive=self.caseInsensitive)
        clone.attributes.update(self.attributes)
        if deep:
            clone.childNodes = [
                child.cloneNode(1, clone) for child in self.childNodes
            ]
        else:
            clone.childNodes = []
        return clone

    def getElementsByTagName(self, name):
        if self.caseInsensitive:
            return getElementsByTagNameNoCase(self, name)
        return getElementsByTagName(self, name)

    def hasAttributes(self):
        return 1

    def getAttribute(self, name, default=None):
        return self.attributes.get(name, default)

    def getAttributeNS(self, ns, name, default=None):
        nsk = (ns, name)
        if self.attributes.has_key(nsk):
            return self.attributes[nsk]
        if ns == self.namespace:
            return self.attributes.get(name, default)
        return default

    def getAttributeNode(self, name):
        return _Attr(self.getAttribute(name), self)

    def setAttribute(self, name, attr):
        self.attributes[name] = attr

    def removeAttribute(self, name):
        if name in self.attributes:
            del self.attributes[name]

    def hasAttribute(self, name):
        return name in self.attributes

    def writexml(self,
                 stream,
                 indent='',
                 addindent='',
                 newl='',
                 strip=0,
                 nsprefixes={},
                 namespace=''):
        # write beginning
        ALLOWSINGLETON = ('img', 'br', 'hr', 'base', 'meta', 'link', 'param',
                          'area', 'input', 'col', 'basefont', 'isindex',
                          'frame')
        BLOCKELEMENTS = ('html', 'head', 'body', 'noscript', 'ins', 'del',
                         'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'script', 'ul',
                         'ol', 'dl', 'pre', 'hr', 'blockquote', 'address', 'p',
                         'div', 'fieldset', 'table', 'tr', 'form', 'object',
                         'fieldset', 'applet', 'map')
        FORMATNICELY = ('tr', 'ul', 'ol', 'head')

        # this should never be necessary unless people start
        # changing .tagName on the fly(?)
        if not self.preserveCase:
            self.endTagName = self.tagName
        w = stream.write
        if self.nsprefixes:
            newprefixes = self.nsprefixes.copy()
            for ns in nsprefixes.keys():
                if ns in newprefixes:
                    del newprefixes[ns]
        else:
            newprefixes = {}

        begin = ['<']
        if self.tagName in BLOCKELEMENTS:
            begin = [newl, indent] + begin
        bext = begin.extend
        writeattr = lambda _atr, _val: bext(
            (' ', _atr, '="', escape(_val), '"'))
        if namespace != self.namespace and self.namespace is not None:
            if nsprefixes.has_key(self.namespace):
                prefix = nsprefixes[self.namespace]
                bext(prefix + ':' + self.tagName)
            else:
                bext(self.tagName)
                writeattr("xmlns", self.namespace)
        else:
            bext(self.tagName)
        j = ''.join
        for attr, val in self.attributes.iteritems():
            if isinstance(attr, tuple):
                ns, key = attr
                if nsprefixes.has_key(ns):
                    prefix = nsprefixes[ns]
                else:
                    prefix = genprefix()
                    newprefixes[ns] = prefix
                assert val is not None
                writeattr(prefix + ':' + key, val)
            else:
                assert val is not None
                writeattr(attr, val)
        if newprefixes:
            for ns, prefix in newprefixes.iteritems():
                if prefix:
                    writeattr('xmlns:' + prefix, ns)
            newprefixes.update(nsprefixes)
            downprefixes = newprefixes
        else:
            downprefixes = nsprefixes
        w(j(begin))
        if self.childNodes:
            w(">")
            newindent = indent + addindent
            for child in self.childNodes:
                if self.tagName in BLOCKELEMENTS and \
                   self.tagName in FORMATNICELY:
                    w(j((newl, newindent)))
                child.writexml(stream, newindent, addindent, newl, strip,
                               downprefixes, self.namespace)
            if self.tagName in BLOCKELEMENTS:
                w(j((newl, indent)))
            w(j(("</", self.endTagName, '>')))

        elif self.tagName.lower() not in ALLOWSINGLETON:
            w(j(('></', self.endTagName, '>')))
        else:
            w(" />")

    def __repr__(self):
        rep = "Element(%s" % repr(self.nodeName)
        if self.attributes:
            rep += ", attributes=%r" % (self.attributes, )
        if self._filename:
            rep += ", filename=%r" % (self._filename, )
        if self._markpos:
            rep += ", markpos=%r" % (self._markpos, )
        return rep + ')'

    def __str__(self):
        rep = "<" + self.nodeName
        if self._filename or self._markpos:
            rep += " ("
        if self._filename:
            rep += repr(self._filename)
        if self._markpos:
            rep += " line %s column %s" % self._markpos
        if self._filename or self._markpos:
            rep += ")"
        for item in self.attributes.items():
            rep += " %s=%r" % item
        if self.hasChildNodes():
            rep += " >...</%s>" % self.nodeName
        else:
            rep += " />"
        return rep
Example #7
0
class Element(Node):

    preserveCase = 0
    caseInsensitive = 1
    nsprefixes = None

    def __init__(self, tagName, attributes=None, parentNode=None,
                 filename=None, markpos=None,
                 caseInsensitive=1, preserveCase=0,
                 namespace=None):
        Node.__init__(self, parentNode)
        self.preserveCase = preserveCase or not caseInsensitive
        self.caseInsensitive = caseInsensitive
        if not preserveCase:
            tagName = tagName.lower()
        if attributes is None:
            self.attributes = {}
        else:
            self.attributes = attributes
            for k, v in self.attributes.items():
                self.attributes[k] = unescape(v)

        if caseInsensitive:
            self.attributes = InsensitiveDict(self.attributes,
                                              preserve=preserveCase)

        self.endTagName = self.nodeName = self.tagName = tagName
        self._filename = filename
        self._markpos = markpos
        self.namespace = namespace

    def addPrefixes(self, pfxs):
        if self.nsprefixes is None:
            self.nsprefixes = pfxs
        else:
            self.nsprefixes.update(pfxs)

    def endTag(self, endTagName):
        if not self.preserveCase:
            endTagName = endTagName.lower()
        self.endTagName = endTagName

    def isEqualToElement(self, n):
        if self.caseInsensitive:
            return ((self.attributes == n.attributes)
                    and (self.nodeName.lower() == n.nodeName.lower()))
        return (self.attributes == n.attributes) and (self.nodeName == n.nodeName)


    def isEqualToNode(self, other):
        """
        Compare this element to C{other}.  If the C{nodeName}, C{namespace},
        C{attributes}, and C{childNodes} are all the same, return C{True},
        otherwise return C{False}.
        """
        return (
            self.nodeName.lower() == other.nodeName.lower() and
            self.namespace == other.namespace and
            self.attributes == other.attributes and
            Node.isEqualToNode(self, other))


    def cloneNode(self, deep=0, parent=None):
        clone = Element(
            self.tagName, parentNode=parent, namespace=self.namespace,
            preserveCase=self.preserveCase, caseInsensitive=self.caseInsensitive)
        clone.attributes.update(self.attributes)
        if deep:
            clone.childNodes = [child.cloneNode(1, clone) for child in self.childNodes]
        else:
            clone.childNodes = []
        return clone

    def getElementsByTagName(self, name):
        if self.caseInsensitive:
            return getElementsByTagNameNoCase(self, name)
        return getElementsByTagName(self, name)

    def hasAttributes(self):
        return 1

    def getAttribute(self, name, default=None):
        return self.attributes.get(name, default)

    def getAttributeNS(self, ns, name, default=None):
        nsk = (ns, name)
        if self.attributes.has_key(nsk):
            return self.attributes[nsk]
        if ns == self.namespace:
            return self.attributes.get(name, default)
        return default

    def getAttributeNode(self, name):
        return _Attr(self.getAttribute(name), self)

    def setAttribute(self, name, attr):
        self.attributes[name] = attr

    def removeAttribute(self, name):
        if name in self.attributes:
            del self.attributes[name]

    def hasAttribute(self, name):
        return name in self.attributes


    def writexml(self, stream, indent='', addindent='', newl='', strip=0,
                 nsprefixes={}, namespace=''):
        """
        Serialize this L{Element} to the given stream.

        @param stream: A file-like object to which this L{Element} will be
            written.

        @param nsprefixes: A C{dict} mapping namespace URIs as C{str} to
            prefixes as C{str}.  This defines the prefixes which are already in
            scope in the document at the point at which this L{Element} exists.
            This is essentially an implementation detail for namespace support.
            Applications should not try to use it.

        @param namespace: The namespace URI as a C{str} which is the default at
            the point in the document at which this L{Element} exists.  This is
            essentially an implementation detail for namespace support.
            Applications should not try to use it.
        """
        # write beginning
        ALLOWSINGLETON = ('img', 'br', 'hr', 'base', 'meta', 'link', 'param',
                          'area', 'input', 'col', 'basefont', 'isindex',
                          'frame')
        BLOCKELEMENTS = ('html', 'head', 'body', 'noscript', 'ins', 'del',
                         'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'script',
                         'ul', 'ol', 'dl', 'pre', 'hr', 'blockquote',
                         'address', 'p', 'div', 'fieldset', 'table', 'tr',
                         'form', 'object', 'fieldset', 'applet', 'map')
        FORMATNICELY = ('tr', 'ul', 'ol', 'head')

        # this should never be necessary unless people start
        # changing .tagName on the fly(?)
        if not self.preserveCase:
            self.endTagName = self.tagName
        w = stream.write
        if self.nsprefixes:
            newprefixes = self.nsprefixes.copy()
            for ns in nsprefixes.keys():
                if ns in newprefixes:
                    del newprefixes[ns]
        else:
             newprefixes = {}

        begin = ['<']
        if self.tagName in BLOCKELEMENTS:
            begin = [newl, indent] + begin
        bext = begin.extend
        writeattr = lambda _atr, _val: bext((' ', _atr, '="', escape(_val), '"'))

        # Make a local for tracking what end tag will be used.  If namespace
        # prefixes are involved, this will be changed to account for that
        # before it's actually used.
        endTagName = self.endTagName

        if namespace != self.namespace and self.namespace is not None:
            # If the current default namespace is not the namespace of this tag
            # (and this tag has a namespace at all) then we'll write out
            # something related to namespaces.
            if self.namespace in nsprefixes:
                # This tag's namespace already has a prefix bound to it.  Use
                # that prefix.
                prefix = nsprefixes[self.namespace]
                bext(prefix + ':' + self.tagName)
                # Also make sure we use it for the end tag.
                endTagName = prefix + ':' + self.endTagName
            else:
                # This tag's namespace has no prefix bound to it.  Change the
                # default namespace to this tag's namespace so we don't need
                # prefixes.  Alternatively, we could add a new prefix binding.
                # I'm not sure why the code was written one way rather than the
                # other. -exarkun
                bext(self.tagName)
                writeattr("xmlns", self.namespace)
                # The default namespace just changed.  Make sure any children
                # know about this.
                namespace = self.namespace
        else:
            # This tag has no namespace or its namespace is already the default
            # namespace.  Nothing extra to do here.
            bext(self.tagName)

        j = ''.join
        for attr, val in self.attributes.iteritems():
            if isinstance(attr, tuple):
                ns, key = attr
                if nsprefixes.has_key(ns):
                    prefix = nsprefixes[ns]
                else:
                    prefix = genprefix()
                    newprefixes[ns] = prefix
                assert val is not None
                writeattr(prefix+':'+key,val)
            else:
                assert val is not None
                writeattr(attr, val)
        if newprefixes:
            for ns, prefix in newprefixes.iteritems():
                if prefix:
                    writeattr('xmlns:'+prefix, ns)
            newprefixes.update(nsprefixes)
            downprefixes = newprefixes
        else:
            downprefixes = nsprefixes
        w(j(begin))
        if self.childNodes:
            w(">")
            newindent = indent + addindent
            for child in self.childNodes:
                if self.tagName in BLOCKELEMENTS and \
                   self.tagName in FORMATNICELY:
                    w(j((newl, newindent)))
                child.writexml(stream, newindent, addindent, newl, strip,
                               downprefixes, namespace)
            if self.tagName in BLOCKELEMENTS:
                w(j((newl, indent)))
            w(j(('</', endTagName, '>')))
        elif self.tagName.lower() not in ALLOWSINGLETON:
            w(j(('></', endTagName, '>')))
        else:
            w(" />")


    def __repr__(self):
        rep = "Element(%s" % repr(self.nodeName)
        if self.attributes:
            rep += ", attributes=%r" % (self.attributes,)
        if self._filename:
            rep += ", filename=%r" % (self._filename,)
        if self._markpos:
            rep += ", markpos=%r" % (self._markpos,)
        return rep + ')'

    def __str__(self):
        rep = "<" + self.nodeName
        if self._filename or self._markpos:
            rep += " ("
        if self._filename:
            rep += repr(self._filename)
        if self._markpos:
            rep += " line %s column %s" % self._markpos
        if self._filename or self._markpos:
            rep += ")"
        for item in self.attributes.items():
            rep += " %s=%r" % item
        if self.hasChildNodes():
            rep += " >...</%s>" % self.nodeName
        else:
            rep += " />"
        return rep
Example #8
0
class IRCBot(irc.IRCClient):
    sasl_buffer = ""
    sasl_result = None
    sasl_login = None

    def __init__(self, factory, plugin):
        self.factory     = factory
        self.nickname    = plugin.nickname.encode('ascii')
        self.realname    = plugin.realname.encode('ascii')
        self.username    = plugin.ident.encode('ascii')
        self.ns_username = plugin.username
        self.ns_password = plugin.password
        self.password    = plugin.server_password.encode('ascii')
        self.channel     = plugin.channel.encode('ascii')
        self.console     = plugin.console
        self.irc_message = plugin.irc_message

        self.users       = InsensitiveDict()
        self.cap_requests = set()

    def register(self, nickname, hostname="foo", servername="bar"):
        self.sendLine("CAP LS")
        return irc.IRCClient.register(self, nickname, hostname, servername)

    def _parse_cap(self, cap):
        mod = ''
        while cap[0] in "-~=":
            mod, cap = mod + cap[0], cap[1:]
        if '/' in cap:
            vendor, cap = cap.split('/', 1)
        else:
            vendor = None
        return (cap, mod, vendor)

    def request_cap(self, *caps):
        self.cap_requests |= set(caps)
        self.sendLine("CAP REQ :{0}".format(' '.join(caps)))

    @defer.inlineCallbacks
    def end_cap(self):
        if self.sasl_result:
            yield self.sasl_result
        self.sendLine("CAP END")

    def irc_CAP(self, prefix, params):
        self.supports_cap = True
        identifier, subcommand, args = params
        args = args.split(' ')
        if subcommand == "LS":
            self.sasl_start(args)
            if not self.cap_requests:
                self.sendLine("CAP END")
        elif subcommand == "ACK":
            ack = []
            for cap in args:
                if not cap:
                    continue
                cap, mod, vendor = self._parse_cap(cap)
                if '-' in mod:
                    if cap in self.capabilities:
                        del self.capabilities[cap]
                    continue
                self.cap_requests.remove(cap)
                if cap == 'sasl':
                    self.sasl_next()
            if ack:
                self.sendLine("CAP ACK :{0}".format(' '.join(ack)))
            if not self.cap_requests:
                self.end_cap()
        elif subcommand == "NAK":
            # this implementation is probably not compliant but it will have to do for now
            for cap in args:
                self.cap_requests.remove(cap)
            if not self.cap_requests:
                self.end_cap()

    def signedOn(self):
        if ISSLTransport.providedBy(self.transport):
            cert = self.transport.getPeerCertificate()
            fp = cert.digest("sha1")
            verified = "verified" if self.factory.parent.server_fingerprint else "unverified"
            self.console("irc: connected securely. server fingerprint: {0} ({1})".format(fp, verified))
        else:
            self.console("irc: connected")
        
        if self.ns_username and self.ns_password and not self.sasl_login:
            self.msg('NickServ', 'IDENTIFY {0} {1}'.format(self.ns_username, self.ns_password))
        
        self.join(self.channel)

    def irc_JOIN(self, prefix, params):
        nick = prefix.split('!')[0]
        channel = params[-1]
        if nick == self.nickname:
            self.joined(channel)
        else:
            self.userJoined(prefix, channel)

    def joined(self, channel):
        self.console('irc: joined channel')
        self.factory.client = self
        def who(a):
            self.sendLine("WHO " + channel)
        self.factory.parent.repeating_task(who, 30, now=True)
    
    def isupport(self, args):
        self.compute_prefix_names()
        
    def compute_prefix_names(self):
        KNOWN_NAMES = {"o": "op", "h": "halfop", "v": "voice"}
        prefixdata = self.supported.getFeature("PREFIX", {"o": ("@", 0), "v": ("+", 1)}).items()
        op_priority = ([priority for mode, (prefix, priority) in prefixdata if mode == "o"] + [None])[0]
        self.prefixes, self.statuses, self.priority = {}, {}, {}

        for mode, (prefix, priority) in prefixdata:
            name = "?"
            if mode in KNOWN_NAMES:
                name = KNOWN_NAMES[mode]
            elif priority == 0:
                if op_priority == 2:
                    name = "owner"
                else:
                    name = "admin"
            else:
                name = "+" + mode
            self.prefixes[mode] = prefix
            self.statuses[prefix] = name
            self.priority[name] = priority
            self.priority[mode] = priority
            self.priority[prefix] = priority

    def parse_prefixes(self, user, nick, prefixes=''):
        status = []
        prefixdata = self.supported.getFeature("PREFIX", {"o": ("@", 0), "v": ("+", 1)}).items()
        for mode, (prefix, priority) in prefixdata:
            if prefix in prefixes + nick:
                nick = nick.replace(prefix, '')
                status.append((prefix, priority))
        if nick == self.nickname:
            return
        user.status = ''.join(t[0] for t in sorted(status, key=lambda t: t[1]))
    
    def irc_RPL_WHOREPLY(self, prefix, params):
        _, channel, username, host, server, nick, status, hg = params
        if nick == self.nickname:
            return
        hops, gecos = hg.split(' ', 1)
        user = IRCUser(self, nick)
        user.username = username
        user.hostname = host
        user.oper = '*' in status
        user.away = status[0] == 'G'
        self.users[nick] = user
        self.parse_prefixes(user, nick, status[1:].replace('*', ''))
    
    def modeChanged(self, user, channel, _set, modes, args):
        args = list(args)
        if channel.lower() != self.channel.lower():
            return
        for m, arg in zip(modes, args):
            if m in self.prefixes and arg != self.nickname:
                u = self.users.get(arg, None)
                if u:
                    u.status = u.status.replace(self.prefixes[m], '')
                    if _set:
                        u.status = ''.join(sorted(list(u.status + self.prefixes[m]),
                                                  key=lambda k: self.priority[k]))

    def has_status(self, nick, status):
        if status != 0 and not status:
            return True
        if status not in self.priority:
            return False
        priority = self.priority[status]
        u = self.users.get(nick, None)
        return u and (u.priority is not None) and u.priority <= priority
    
    def userJoined(self, user, channel):
        nick = user.split('!')[0]
        user = IRCUser(self, nick)
        self.users[nick] = user
    
    def userRenamed(self, oldname, newname):
        if oldname not in self.users:
            return
        u = self.users[oldname]
        u.nick = newname
        self.users[newname] = u
        del self.users[oldname]
    
    def userLeft(self, user, channel):
        if user not in self.users:
            return
        del self.users[user]
    
    def userKicked(self, kickee, channel, kicker, message):
        if kickee not in self.users:
            return
        del self.users[kickee]
    
    def userQuit(self, user, quitMessage):
        if user not in self.users:
            return
        del self.users[user]

    def privmsg(self, user, channel, msg):
        if channel != self.channel:
            return
        if '!' not in user:
            return
        nick = user.split('!')[0]
        p = self.factory.parent
        
        if not self.has_status(nick, p.irc_chat_status):
            return

        if p.irc_players_enabled and msg.lower() == p.irc_command_prefix + "players":
            self.say(self.channel, p.irc_players_format.format(players=', '.join(p.players)))

        elif p.irc_command_prefix and msg.startswith(p.irc_command_prefix) and p.irc_command_status and self.has_status(nick, p.irc_command_status):
            argv = msg[len(p.irc_command_prefix):].split(' ')
            command = argv[0]
            if command.startswith('~'):
                if p.irc_command_mark2 and (command.lower() in p.irc_command_allow.lower().split(',') or p.irc_command_allow == '*'):
                    p.dispatch(Hook(line=' '.join(argv)))
            else:
                if command.lower() in p.irc_command_allow.lower().split(',') or p.irc_command_allow == '*':
                    p.send(' '.join(argv))

        else:
            p.irc_message(nick, msg)

    def irc_AUTHENTICATE(self, prefix, params):
        self.sasl_continue(params[0])

    def sasl_send(self, data):
        while data and len(data) >= 400:
            en, data = data[:400].encode('base64').replace('\n', ''), data[400:]
            self.sendLine("AUTHENTICATE " + en)
        if data:
            self.sendLine("AUTHENTICATE " + data.encode('base64').replace('\n', ''))
        else:
            self.sendLine("AUTHENTICATE +")

    def sasl_start(self, cap_list):
        if 'sasl' not in cap_list:
            print cap_list
            return
        self.request_cap('sasl')
        self.sasl_result = defer.Deferred()
        self.sasl_mechanisms = list(SASL_MECHANISMS)

    def sasl_next(self):
        mech = None
        while not mech or not mech.is_valid():
            if not self.sasl_mechanisms:
                return False
            self.sasl_auth = mech = self.sasl_mechanisms.pop(0)(self.ns_username, self.ns_password)
        self.sendLine("AUTHENTICATE " + self.sasl_auth.name)
        return True

    def sasl_continue(self, data):
        if data == '+':
            data = ''
        else:
            data = data.decode('base64')
        if len(data) == 400:
            self.sasl_buffer += data
        else:
            response = self.sasl_auth.respond(self.sasl_buffer + data)
            if response is False:  # abort
                self.sendLine("AUTHENTICATE *")
            else:
                self.sasl_send(response)
            self.sasl_buffer = ""

    def sasl_finish(self):
        if self.sasl_result:
            self.sasl_result.callback(True)
            self.sasl_result = None

    def sasl_failed(self, whine=True):
        if self.sasl_login is False:
            return
        if self.sasl_next():
            return
        self.sasl_login = False
        self.sendLine("AUTHENTICATE *")
        self.sasl_finish()
        if whine:
            self.console("irc: failed to log in.")

    def irc_904(self, prefix, params):
        print params
        self.sasl_failed()

    def irc_905(self, prefix, params):
        print params
        self.sasl_failed()

    def irc_906(self, prefix, params):
        self.sasl_failed(False)

    def irc_907(self, prefix, params):
        self.sasl_failed(False)

    def irc_900(self, prefix, params):
        self.sasl_login = params[2]
        self.console("irc: logged in as '{0}' (using {1})".format(self.sasl_login, self.sasl_auth.name))

    def irc_903(self, prefix, params):
        self.sasl_finish()

    def alterCollidedNick(self, nickname):
        return nickname + '_'

    def irc_relay(self, message):
        self.say(self.channel, message.encode('utf8'))
Example #9
0
class BaseLDAPEntry(WireStrAlias):
    dn = None
    _object_class_keys = set(get_strings('objectClass'))
    _object_class_lower_keys = set(get_strings('objectclass'))
    _user_password_keys = set(get_strings('userPassword'))

    def __init__(self, dn, attributes={}):
        """

        Initialize the object.

        @param dn: Distinguished Name of the object, as a string.

        @param attributes: Attributes of the object. A dictionary of
        attribute types to list of attribute values.

        """
        self._attributes = InsensitiveDict()
        self.dn = distinguishedname.DistinguishedName(dn)

        for k, vs in attributes.items():
            if k not in self._attributes:
                self._attributes[k] = []
            self._attributes[k].extend(vs)

        for k, vs in self._attributes.items():
            self._attributes[k] = self.buildAttributeSet(k, vs)

    def buildAttributeSet(self, key, values):
        return attributeset.LDAPAttributeSet(key, values)

    def __getitem__(self, key):
        for k in get_strings(key):
            if k in self._attributes:
                return self._attributes[k]
        raise KeyError(key)

    def get(self, key, default=None):
        for k in get_strings(key):
            if k in self._attributes:
                return self._attributes[k]
        return default

    def has_key(self, key):
        for k in get_strings(key):
            if k in self._attributes:
                return True
        return False

    def __contains__(self, key):
        return self.has_key(key)

    def __iter__(self):
        for key in self._attributes.iterkeys():
            yield key

    def keys(self):
        a = []
        for key in self._object_class_keys:
            if key in self._attributes:
                a.append(key)
        l = list(self._attributes.keys())
        l.sort(key=to_bytes)
        for key in l:
            if key.lower() not in self._object_class_lower_keys:
                a.append(key)
        return a

    def items(self):
        a = []

        for key in self._object_class_keys:
            objectClasses = list(self._attributes.get(key, []))
            objectClasses.sort(key=to_bytes)
            if objectClasses:
                a.append((key, objectClasses))

        l = list(self._attributes.items())
        l.sort(key=lambda x: to_bytes(x[0]))
        for key, values in l:
            if key.lower() not in self._object_class_lower_keys:
                vs = list(values)
                vs.sort()
                a.append((key, vs))

        return a

    def toWire(self):
        a = []

        for key in self._object_class_keys:
            objectClasses = list(self._attributes.get(key, []))
            objectClasses.sort(key=to_bytes)
            a.append((key, objectClasses))

        items_gen = ((key, self[key]) for key in self)
        items = sorted(items_gen, key=lambda x: to_bytes(x[0]))
        for key, values in items:
            if key.lower() not in self._object_class_lower_keys:
                vs = list(values)
                vs.sort()
                a.append((key, vs))
        return ldif.asLDIF(self.dn.getText(), a)

    def getLDIF(self):
        return self.toWire().decode('utf-8')

    def __eq__(self, other):
        if not isinstance(other, BaseLDAPEntry):
            return NotImplemented
        if self.dn != other.dn:
            return 0

        my = sorted((key for key in self), key=to_bytes)
        its = sorted((key for key in other), key=to_bytes)
        if my != its:
            return 0
        for key in my:
            myAttr = self[key]
            itsAttr = other[key]
            if myAttr != itsAttr:
                return 0
        return 1

    def __ne__(self, other):
        return not self == other

    def __len__(self):
        return len(self.keys())

    def __bool__(self):
        return True

    def __nonzero__(self):
        return self.__bool__()

    def __repr__(self):
        keys = sorted((key for key in self), key=to_bytes)
        a = []
        for key in keys:
            a.append('%s: %s' % (repr(key), repr(list(self[key]))))
        attributes = ', '.join(a)
        dn = to_bytes(self.dn.getText()) if six.PY2 else self.dn.getText()
        return '%s(%s, {%s})' % (self.__class__.__name__, repr(dn), attributes)

    def diff(self, other):
        """
        Compute differences between this and another LDAP entry.

        @param other: An LDAPEntry to compare to.

        @return: None if equal, otherwise a ModifyOp that would make
        this entry look like other.
        """
        assert self.dn == other.dn
        if self == other:
            return None

        r = []

        myKeys = set(key for key in self)
        otherKeys = set(key for key in other)

        addedKeys = list(otherKeys - myKeys)
        addedKeys.sort(key=to_bytes)  # for reproducability only
        for added in addedKeys:
            r.append(delta.Add(added, other[added]))

        deletedKeys = list(myKeys - otherKeys)
        deletedKeys.sort(key=to_bytes)  # for reproducability only
        for deleted in deletedKeys:
            r.append(delta.Delete(deleted, self[deleted]))

        sharedKeys = list(myKeys & otherKeys)
        sharedKeys.sort(key=to_bytes)  # for reproducability only
        for shared in sharedKeys:

            addedValues = list(other[shared] - self[shared])
            if addedValues:
                addedValues.sort(key=to_bytes)  # for reproducability only
                r.append(delta.Add(shared, addedValues))

            deletedValues = list(self[shared] - other[shared])
            if deletedValues:
                deletedValues.sort(key=to_bytes)  # for reproducability only
                r.append(delta.Delete(shared, deletedValues))

        return delta.ModifyOp(dn=self.dn, modifications=r)

    def bind(self, password):
        return defer.maybeDeferred(self._bind, password)

    def _bind(self, password):
        password = to_bytes(password)
        for key in self._user_password_keys:
            for digest in self.get(key, ()):
                digest = to_bytes(digest)
                if digest.startswith(b'{SSHA}'):
                    raw = base64.decodestring(digest[len(b'{SSHA}'):])
                    salt = raw[20:]
                    got = sshaDigest(password, salt)
                    if got == digest:
                        return self
                else:
                    # Plaintext
                    if digest == password:
                        return self
        raise ldaperrors.LDAPInvalidCredentials()

    def hasMember(self, dn):
        for memberDN in self.get('member', []):
            if memberDN == dn:
                return True
        return False

    def __hash__(self):
        # FIXME:https://github.com/twisted/ldaptor/issues/101
        # The hash should take into consideration any attribute used to
        # decide the equality.
        return hash(self.dn)
Example #10
0
class BaseLDAPEntry(object):
    implements(interfaces.ILDAPEntry)
    dn = None

    def __init__(self, dn, attributes={}):
        """

        Initialize the object.

        @param dn: Distinguished Name of the object, as a string.

        @param attributes: Attributes of the object. A dictionary of
        attribute types to list of attribute values.

        """
        self._attributes=InsensitiveDict()
        self.dn = distinguishedname.DistinguishedName(dn)

        for k,vs in attributes.items():
            if k not in self._attributes:
                self._attributes[k] = []
            self._attributes[k].extend(vs)

        for k,vs in self._attributes.items():
            self._attributes[k] = self.buildAttributeSet(k, vs)

    def buildAttributeSet(self, key, values):
        return attributeset.LDAPAttributeSet(key, values)

    def __getitem__(self, key):
        return self._attributes[key]

    def get(self, key, default=None):
        return self._attributes.get(key, default)

    def has_key(self, key):
        return key in self._attributes

    def __contains__(self, key):
        return self.has_key(key)

    def keys(self):
        return self._attributes.keys()

    def items(self):
        return self._attributes.items()

    def __str__(self):
        a=[]

        objectClasses = list(self.get('objectClass', []))
        objectClasses.sort()
        a.append(('objectClass', objectClasses))

        l=list(self.items())
        l.sort()
        for key, values in l:
            if key.lower() != 'objectclass':
                vs = list(values)
                vs.sort()
                a.append((key, vs))
        return ldif.asLDIF(self.dn, a)

    def __eq__(self, other):
        if not isinstance(other, BaseLDAPEntry):
            return 0
        if self.dn != other.dn:
            return 0

        my=self.keys()
        my.sort()
        its=other.keys()
        its.sort()
        if my!=its:
            return 0
        for key in my:
            myAttr=self[key]
            itsAttr=other[key]
            if myAttr!=itsAttr:
                return 0
        return 1

    def __ne__(self, other):
        return not self==other

    def __len__(self):
        return len(self.keys())

    def __nonzero__(self):
        return True

    def __repr__(self):
        x={}
        for key in self.keys():
            x[key]=self[key]
        keys=self.keys()
        keys.sort()
        a=[]
        for key in keys:
            a.append('%s: %s' % (repr(key), repr(list(self[key]))))
        attributes=', '.join(a)
        return '%s(%s, {%s})' % (
            self.__class__.__name__,
            repr(str(self.dn)),
            attributes)

    def diff(self, other):
        """
        Compute differences between this and another LDAP entry.

        @param other: An LDAPEntry to compare to.

        @return: None if equal, otherwise a ModifyOp that would make
        this entry look like other.
        """
        assert self.dn == other.dn
        if self == other:
            return None

        r = []

        myKeys = sets.Set(self.keys())
        otherKeys = sets.Set(other.keys())

        addedKeys = list(otherKeys - myKeys)
        addedKeys.sort() # for reproducability only
        for added in addedKeys:
            r.append(delta.Add(added, other[added]))

        deletedKeys = list(myKeys - otherKeys)
        deletedKeys.sort() # for reproducability only
        for deleted in deletedKeys:
            r.append(delta.Delete(deleted, self[deleted]))

        sharedKeys = list(myKeys & otherKeys)
        sharedKeys.sort() # for reproducability only
        for shared in sharedKeys:

            addedValues = list(other[shared] - self[shared])
            if addedValues:
                addedValues.sort() # for reproducability only
                r.append(delta.Add(shared, addedValues))

            deletedValues = list(self[shared] - other[shared])
            if deletedValues:
                deletedValues.sort() # for reproducability only
                r.append(delta.Delete(shared, deletedValues))

        return delta.ModifyOp(dn=self.dn, modifications=r)

    def bind(self, password):
        return defer.maybeDeferred(self._bind, password)

    def _bind(self, password):
        for digest in self.get('userPassword', ()):
            if digest.startswith('{SSHA}'):
                raw = base64.decodestring(digest[len('{SSHA}'):])
                salt = raw[20:]
                got = sshaDigest(password, salt)
                if got == digest:
                    return self
        raise ldaperrors.LDAPInvalidCredentials

    def hasMember(self, dn):
        for memberDN in self.get('member', []):
            if memberDN == dn:
                return True
        return False

    def __hash__(self):
        return hash(self.dn)
Example #11
0
class Element(Node):
    nsprefixes = None
    create_attr = lambda k, v: (' ', k, '="', escape(v), '"')

    SINGLETONS = (
        'img', 'br', 'hr', 'base', 'meta', 'link', 'param',
        'area', 'input', 'col', 'basefont', 'isindex', 'frame')

    BLOCKELEMENTS = (
        'html', 'head', 'body', 'noscript', 'ins', 'del',
        'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'script',
        'ul', 'ol', 'dl', 'pre', 'hr', 'blockquote',
        'address', 'p', 'div', 'fieldset', 'table', 'tr',
        'form', 'object', 'fieldset', 'applet', 'map')

    NICEFORMATS = ('tr', 'ul', 'ol', 'head')

    def __init__(
        self, tagName, attributes=None, parentNode=None, filename=None,
        markpos=None, case_insensitive=1, namespace=None
    ):
        Node.__init__(self, parentNode)
        preserve_case = not case_insensitive
        tagName = tagName if preserve_case else tagName.lower()
        unescaped = unescape_dict(attributes or {})

        if case_insensitive:
            self.attributes = InsensitiveDict(unescaped, preserve=preserve_case)
        else:
            self.attributes = unescaped

        self.preserve_case = not case_insensitive
        self.case_insensitive = case_insensitive
        self.endTagName = self.nodeName = self.tagName = tagName
        self._filename = filename
        self._markpos = markpos
        self.namespace = namespace
        self.tag_is_blockelement = tagName in self.BLOCKELEMENTS
        self.tag_is_nice_format = tagName in self.NICEFORMATS
        self.tag_is_singleton = tagName.lower() in self.SINGLETONS

    def addPrefixes(self, pfxs):
        if self.nsprefixes is None:
            self.nsprefixes = pfxs
        else:
            self.nsprefixes.update(pfxs)

    def endTag(self, endTagName):
        if self.case_insensitive:
            endTagName = endTagName.lower()

        self.endTagName = endTagName

    def isEqualToElement(self, n):
        same_attrs = self.attributes == n.attributes

        if self.case_insensitive:
            eq = same_attrs and (self.nodeName.lower() == n.nodeName.lower())
        else:
            eq = same_attrs and (self.nodeName == n.nodeName)

        return eq

    def isEqualToNode(self, other):
        """
        Compare this element to C{other}.  If the C{nodeName}, C{namespace},
        C{attributes}, and C{childNodes} are all the same, return C{True},
        otherwise return C{False}.
        """
        return (
            self.nodeName.lower() == other.nodeName.lower() and
            self.namespace == other.namespace and
            self.attributes == other.attributes and
            Node.isEqualToNode(self, other))

    def cloneNode(self, deep=0, parent=None):
        clone = Element(
            self.tagName, parentNode=parent, namespace=self.namespace,
            case_insensitive=self.case_insensitive)

        clone.attributes.update(self.attributes)

        if deep:
            clone.childNodes = [
                child.cloneNode(1, clone) for child in self.childNodes]
        else:
            clone.childNodes = []

        return clone

    def getElementsByTagName(self, name):
        icase = self.case_insensitive
        return getElementsByTagName(self.childNodes, name, icase)

    def hasAttributes(self):
        return 1

    def getAttribute(self, name, default=None):
        return self.attributes.get(name, default)

    def getAttributeNS(self, ns, name, default=None):
        nsk = (ns, name)

        if nsk in self.attributes:
            return self.attributes[nsk]

        if ns == self.namespace:
            return self.attributes.get(name, default)

        return default

    def getAttributeNode(self, name):
        return _Attr(self.getAttribute(name), self)

    def setAttribute(self, name, attr):
        self.attributes[name] = attr

    def removeAttribute(self, name):
        if name in self.attributes:
            del self.attributes[name]

    def hasAttribute(self, name):
        return name in self.attributes

    def gen_prefixes(self, nsprefixes):
        for k, v in self.nsprefixes.items():
            if k not in nsprefixes:
                yield (k, v)

    def _writexml(self, namespace, nsprefixes, newl, indent):
        newprefixes = dict(self.gen_prefixes(nsprefixes))
        begin = [newl, indent, '<'] if self.tag_is_blockelement else ['<']
        is_same_namespace = self.namespace and namespace == self.namespace

        # Make a local for tracking what end tag will be used. If namespace
        # prefixes are involved, this will be changed to account for that
        # before it's actually used.
        endTagName = self.endTagName

        if not is_same_namespace and self.namespace in nsprefixes:
            # This tag's namespace already has a prefix bound to it. Use
            # that prefix.
            prefix = nsprefixes[self.namespace]
            begin.extend(prefix + ':' + self.tagName)

            # Also make sure we use it for the end tag.
            endTagName = prefix + ':' + self.endTagName
        elif not is_same_namespace:
            # This tag's namespace has no prefix bound to it. Change the
            # default namespace to this tag's namespace so we don't need
            # prefixes.  Alternatively, we could add a new prefix binding.
            # I'm not sure why the code was written one way rather than the
            # other. -exarkun
            begin.extend(self.tagName)
            begin.extend(self.create_attr("xmlns", self.namespace))

            # The default namespace just changed.  Make sure any children
            # know about this.
            namespace = self.namespace
        else:
            # This tag has no namespace or its namespace is already the default
            # namespace.  Nothing extra to do here.
            begin.extend(self.tagName)

        prefixes = ('p%s' % str(i) for i in it.count())

        for attr, val in sorted(self.attributes.items()):
            if val and isinstance(attr, tuple):
                ns, key = attr

                if ns in nsprefixes:
                    prefix = nsprefixes[ns]
                else:
                    newprefixes[ns] = prefix = next(prefixes)

                begin.extend(self.create_attr(prefix + ':' + key, val))
            elif val:
                begin.extend(self.create_attr(attr, val))

        return begin, namespace, endTagName, newprefixes

    def _write_child(self, stream, newl, newindent, **kwargs):
        for child in self.childNodes:
            if self.tag_is_blockelement and self.tag_is_nice_format:
                stream.write(''.join((newl, newindent)))

            child.writexml(stream, newl=newl, newindent=newindent, **kwargs)

    def writexml(self, stream, *args, **kwargs):
        """
        Serialize this L{Element} to the given stream.

        @param stream: A file-like object to which this L{Element} will be
            written.

        @param nsprefixes: A C{dict} mapping namespace URIs as C{str} to
            prefixes as C{str}.  This defines the prefixes which are already in
            scope in the document at the point at which this L{Element} exists.
            This is essentially an implementation detail for namespace support.
            Applications should not try to use it.

        @param namespace: The namespace URI as a C{str} which is the default at
            the point in the document at which this L{Element} exists.  This is
            essentially an implementation detail for namespace support.
            Applications should not try to use it.
        """
        indent = kwargs.get('indent', '')
        addindent = kwargs.get('addindent', '')
        newl = kwargs.get('newl', '')
        strip = kwargs.get('strip', 0)
        nsprefixes = kwargs.get('nsprefixes', {})
        namespace = kwargs.get('namespace', '')

        # this should never be necessary unless people start
        # changing .tagName on the fly(?)
        if self.case_insensitive:
            self.endTagName = self.tagName

        _args = (namespace, nsprefixes, newl, indent)
        begin, namespace, endTagName, newprefixes = self._writexml(*_args)

        for ns, prefix in newprefixes.items():
            if prefix:
                begin.extend(self.create_attr('xmlns:' + prefix, ns))

        newprefixes.update(nsprefixes)
        downprefixes = newprefixes
        stream.write(''.join(begin))

        if self.childNodes:
            stream.write(">")
            newindent = indent + addindent

            kwargs = {
                'newindent': newindent,
                'addindent': addindent,
                'newl': newl,
                'strip': strip,
                'downprefixes': downprefixes,
                'namespace': namespace}

            self._write_child(stream, newl, newindent, **kwargs)

            if self.tag_is_blockelement:
                stream.write(''.join((newl, indent)))

            stream.write(''.join(('</', endTagName, '>')))
        elif not self.tag_is_singleton:
            stream.write(''.join(('></', endTagName, '>')))
        else:
            stream.write(" />")

    def __repr__(self):
        rep = "Element(%s" % repr(self.nodeName)

        if self.attributes:
            rep += ", attributes=%r" % (self.attributes,)

        if self._filename:
            rep += ", filename=%r" % (self._filename,)

        if self._markpos:
            rep += ", markpos=%r" % (self._markpos,)

        return rep + ')'

    def __str__(self):
        rep = "<" + self.nodeName

        if self._filename or self._markpos:
            rep += " ("

        if self._filename:
            rep += repr(self._filename)

        if self._markpos:
            rep += " line %s column %s" % self._markpos

        if self._filename or self._markpos:
            rep += ")"

        for item in self.attributes.items():
            rep += " %s=%r" % item

        if self.hasChildNodes():
            rep += " >...</%s>" % self.nodeName
        else:
            rep += " />"

        return rep
Example #12
0
class BaseLDAPEntry(object):
    implements(interfaces.ILDAPEntry)
    dn = None

    def __init__(self, dn, attributes={}):
        """

        Initialize the object.

        @param dn: Distinguished Name of the object, as a string.

        @param attributes: Attributes of the object. A dictionary of
        attribute types to list of attribute values.

        """
        self._attributes=InsensitiveDict()
        self.dn = distinguishedname.DistinguishedName(dn)

        for k,vs in attributes.items():
            if k not in self._attributes:
                self._attributes[k] = []
            self._attributes[k].extend(vs)

        for k,vs in self._attributes.items():
            self._attributes[k] = self.buildAttributeSet(k, vs)

    def buildAttributeSet(self, key, values):
        return attributeset.LDAPAttributeSet(key, values)

    def __getitem__(self, key):
        return self._attributes[key]

    def get(self, key, default=None):
        return self._attributes.get(key, default)

    def has_key(self, key):
        return key in self._attributes

    def __contains__(self, key):
        return self.has_key(key)

    def keys(self):
        a = []
        if self.get('objectClass'):
            a.append('objectClass')
        l=list(self._attributes.keys())
        l.sort()
        for key in l:
            if key.lower() != 'objectclass':
                a.append(key)
        return a

    def items(self):
        a=[]
        objectClasses = list(self.get('objectClass', []))
        objectClasses.sort()
        if objectClasses:
            a.append(('objectClass', objectClasses))

        l=list(self._attributes.items())
        l.sort()
        for key, values in l:
            if key.lower() != 'objectclass':
                vs = list(values)
                vs.sort()
                a.append((key, vs))

        return a

    def __str__(self):
        a=[]

        objectClasses = list(self.get('objectClass', []))
        objectClasses.sort()
        a.append(('objectClass', objectClasses))

        l=list(self.items())
        l.sort()
        for key, values in l:
            if key.lower() != 'objectclass':
                vs = list(values)
                vs.sort()
                a.append((key, vs))
        return ldif.asLDIF(self.dn, a)

    def __eq__(self, other):
        if not isinstance(other, BaseLDAPEntry):
            return 0
        if self.dn != other.dn:
            return 0

        my=self.keys()
        my.sort()
        its=other.keys()
        its.sort()
        if my!=its:
            return 0
        for key in my:
            myAttr=self[key]
            itsAttr=other[key]
            if myAttr!=itsAttr:
                return 0
        return 1

    def __ne__(self, other):
        return not self==other

    def __len__(self):
        return len(self.keys())

    def __nonzero__(self):
        return True

    def __repr__(self):
        x={}
        for key in self.keys():
            x[key]=self[key]
        keys=self.keys()
        keys.sort()
        a=[]
        for key in keys:
            a.append('%s: %s' % (repr(key), repr(list(self[key]))))
        attributes=', '.join(a)
        return '%s(%s, {%s})' % (
            self.__class__.__name__,
            repr(str(self.dn)),
            attributes)

    def diff(self, other):
        """
        Compute differences between this and another LDAP entry.

        @param other: An LDAPEntry to compare to.

        @return: None if equal, otherwise a ModifyOp that would make
        this entry look like other.
        """
        assert self.dn == other.dn
        if self == other:
            return None

        r = []

        myKeys = set(self.keys())
        otherKeys = set(other.keys())

        addedKeys = list(otherKeys - myKeys)
        addedKeys.sort() # for reproducability only
        for added in addedKeys:
            r.append(delta.Add(added, other[added]))

        deletedKeys = list(myKeys - otherKeys)
        deletedKeys.sort() # for reproducability only
        for deleted in deletedKeys:
            r.append(delta.Delete(deleted, self[deleted]))

        sharedKeys = list(myKeys & otherKeys)
        sharedKeys.sort() # for reproducability only
        for shared in sharedKeys:

            addedValues = list(other[shared] - self[shared])
            if addedValues:
                addedValues.sort() # for reproducability only
                r.append(delta.Add(shared, addedValues))

            deletedValues = list(self[shared] - other[shared])
            if deletedValues:
                deletedValues.sort() # for reproducability only
                r.append(delta.Delete(shared, deletedValues))

        return delta.ModifyOp(dn=self.dn, modifications=r)

    def bind(self, password):
        return defer.maybeDeferred(self._bind, password)

    def _bind(self, password):
        for digest in self.get('userPassword', ()):
            if digest.startswith('{SSHA}'):
                raw = base64.decodestring(digest[len('{SSHA}'):])
                salt = raw[20:]
                got = sshaDigest(password, salt)
                if got == digest:
                    return self
        raise ldaperrors.LDAPInvalidCredentials

    def hasMember(self, dn):
        for memberDN in self.get('member', []):
            if memberDN == dn:
                return True
        return False

    def __hash__(self):
        return hash(self.dn)
Example #13
0
class Element(Node):
    nsprefixes = None
    create_attr = lambda k, v: (' ', k, '="', escape(v), '"')

    SINGLETONS = ('img', 'br', 'hr', 'base', 'meta', 'link', 'param', 'area',
                  'input', 'col', 'basefont', 'isindex', 'frame')

    BLOCKELEMENTS = ('html', 'head', 'body', 'noscript', 'ins', 'del', 'h1',
                     'h2', 'h3', 'h4', 'h5', 'h6', 'script', 'ul', 'ol', 'dl',
                     'pre', 'hr', 'blockquote', 'address', 'p', 'div',
                     'fieldset', 'table', 'tr', 'form', 'object', 'fieldset',
                     'applet', 'map')

    NICEFORMATS = ('tr', 'ul', 'ol', 'head')

    def __init__(self,
                 tagName,
                 attributes=None,
                 parentNode=None,
                 filename=None,
                 markpos=None,
                 case_insensitive=1,
                 namespace=None):
        Node.__init__(self, parentNode)
        preserve_case = not case_insensitive
        tagName = tagName if preserve_case else tagName.lower()
        unescaped = unescape_dict(attributes or {})

        if case_insensitive:
            self.attributes = InsensitiveDict(unescaped,
                                              preserve=preserve_case)
        else:
            self.attributes = unescaped

        self.preserve_case = not case_insensitive
        self.case_insensitive = case_insensitive
        self.endTagName = self.nodeName = self.tagName = tagName
        self._filename = filename
        self._markpos = markpos
        self.namespace = namespace
        self.tag_is_blockelement = tagName in self.BLOCKELEMENTS
        self.tag_is_nice_format = tagName in self.NICEFORMATS
        self.tag_is_singleton = tagName.lower() in self.SINGLETONS

    def addPrefixes(self, pfxs):
        if self.nsprefixes is None:
            self.nsprefixes = pfxs
        else:
            self.nsprefixes.update(pfxs)

    def endTag(self, endTagName):
        if self.case_insensitive:
            endTagName = endTagName.lower()

        self.endTagName = endTagName

    def isEqualToElement(self, n):
        same_attrs = self.attributes == n.attributes

        if self.case_insensitive:
            eq = same_attrs and (self.nodeName.lower() == n.nodeName.lower())
        else:
            eq = same_attrs and (self.nodeName == n.nodeName)

        return eq

    def isEqualToNode(self, other):
        """
        Compare this element to C{other}.  If the C{nodeName}, C{namespace},
        C{attributes}, and C{childNodes} are all the same, return C{True},
        otherwise return C{False}.
        """
        return (self.nodeName.lower() == other.nodeName.lower()
                and self.namespace == other.namespace
                and self.attributes == other.attributes
                and Node.isEqualToNode(self, other))

    def cloneNode(self, deep=0, parent=None):
        clone = Element(self.tagName,
                        parentNode=parent,
                        namespace=self.namespace,
                        case_insensitive=self.case_insensitive)

        clone.attributes.update(self.attributes)

        if deep:
            clone.childNodes = [
                child.cloneNode(1, clone) for child in self.childNodes
            ]
        else:
            clone.childNodes = []

        return clone

    def getElementsByTagName(self, name):
        icase = self.case_insensitive
        return getElementsByTagName(self.childNodes, name, icase)

    def hasAttributes(self):
        return 1

    def getAttribute(self, name, default=None):
        return self.attributes.get(name, default)

    def getAttributeNS(self, ns, name, default=None):
        nsk = (ns, name)

        if nsk in self.attributes:
            return self.attributes[nsk]

        if ns == self.namespace:
            return self.attributes.get(name, default)

        return default

    def getAttributeNode(self, name):
        return _Attr(self.getAttribute(name), self)

    def setAttribute(self, name, attr):
        self.attributes[name] = attr

    def removeAttribute(self, name):
        if name in self.attributes:
            del self.attributes[name]

    def hasAttribute(self, name):
        return name in self.attributes

    def gen_prefixes(self, nsprefixes):
        for k, v in self.nsprefixes.items():
            if k not in nsprefixes:
                yield (k, v)

    def _writexml(self, namespace, nsprefixes, newl, indent):
        newprefixes = dict(self.gen_prefixes(nsprefixes))
        begin = [newl, indent, '<'] if self.tag_is_blockelement else ['<']
        is_same_namespace = self.namespace and namespace == self.namespace

        # Make a local for tracking what end tag will be used. If namespace
        # prefixes are involved, this will be changed to account for that
        # before it's actually used.
        endTagName = self.endTagName

        if not is_same_namespace and self.namespace in nsprefixes:
            # This tag's namespace already has a prefix bound to it. Use
            # that prefix.
            prefix = nsprefixes[self.namespace]
            begin.extend(prefix + ':' + self.tagName)

            # Also make sure we use it for the end tag.
            endTagName = prefix + ':' + self.endTagName
        elif not is_same_namespace:
            # This tag's namespace has no prefix bound to it. Change the
            # default namespace to this tag's namespace so we don't need
            # prefixes.  Alternatively, we could add a new prefix binding.
            # I'm not sure why the code was written one way rather than the
            # other. -exarkun
            begin.extend(self.tagName)
            begin.extend(self.create_attr("xmlns", self.namespace))

            # The default namespace just changed.  Make sure any children
            # know about this.
            namespace = self.namespace
        else:
            # This tag has no namespace or its namespace is already the default
            # namespace.  Nothing extra to do here.
            begin.extend(self.tagName)

        prefixes = ('p%s' % str(i) for i in it.count())

        for attr, val in sorted(self.attributes.items()):
            if val and isinstance(attr, tuple):
                ns, key = attr

                if ns in nsprefixes:
                    prefix = nsprefixes[ns]
                else:
                    newprefixes[ns] = prefix = next(prefixes)

                begin.extend(self.create_attr(prefix + ':' + key, val))
            elif val:
                begin.extend(self.create_attr(attr, val))

        return begin, namespace, endTagName, newprefixes

    def _write_child(self, stream, newl, newindent, **kwargs):
        for child in self.childNodes:
            if self.tag_is_blockelement and self.tag_is_nice_format:
                stream.write(''.join((newl, newindent)))

            child.writexml(stream, newl=newl, newindent=newindent, **kwargs)

    def writexml(self, stream, *args, **kwargs):
        """
        Serialize this L{Element} to the given stream.

        @param stream: A file-like object to which this L{Element} will be
            written.

        @param nsprefixes: A C{dict} mapping namespace URIs as C{str} to
            prefixes as C{str}.  This defines the prefixes which are already in
            scope in the document at the point at which this L{Element} exists.
            This is essentially an implementation detail for namespace support.
            Applications should not try to use it.

        @param namespace: The namespace URI as a C{str} which is the default at
            the point in the document at which this L{Element} exists.  This is
            essentially an implementation detail for namespace support.
            Applications should not try to use it.
        """
        indent = kwargs.get('indent', '')
        addindent = kwargs.get('addindent', '')
        newl = kwargs.get('newl', '')
        strip = kwargs.get('strip', 0)
        nsprefixes = kwargs.get('nsprefixes', {})
        namespace = kwargs.get('namespace', '')

        # this should never be necessary unless people start
        # changing .tagName on the fly(?)
        if self.case_insensitive:
            self.endTagName = self.tagName

        _args = (namespace, nsprefixes, newl, indent)
        begin, namespace, endTagName, newprefixes = self._writexml(*_args)

        for ns, prefix in newprefixes.items():
            if prefix:
                begin.extend(self.create_attr('xmlns:' + prefix, ns))

        newprefixes.update(nsprefixes)
        downprefixes = newprefixes
        stream.write(''.join(begin))

        if self.childNodes:
            stream.write(">")
            newindent = indent + addindent

            kwargs = {
                'newindent': newindent,
                'addindent': addindent,
                'newl': newl,
                'strip': strip,
                'downprefixes': downprefixes,
                'namespace': namespace
            }

            self._write_child(stream, newl, newindent, **kwargs)

            if self.tag_is_blockelement:
                stream.write(''.join((newl, indent)))

            stream.write(''.join(('</', endTagName, '>')))
        elif not self.tag_is_singleton:
            stream.write(''.join(('></', endTagName, '>')))
        else:
            stream.write(" />")

    def __repr__(self):
        rep = "Element(%s" % repr(self.nodeName)

        if self.attributes:
            rep += ", attributes=%r" % (self.attributes, )

        if self._filename:
            rep += ", filename=%r" % (self._filename, )

        if self._markpos:
            rep += ", markpos=%r" % (self._markpos, )

        return rep + ')'

    def __str__(self):
        rep = "<" + self.nodeName

        if self._filename or self._markpos:
            rep += " ("

        if self._filename:
            rep += repr(self._filename)

        if self._markpos:
            rep += " line %s column %s" % self._markpos

        if self._filename or self._markpos:
            rep += ")"

        for item in self.attributes.items():
            rep += " %s=%r" % item

        if self.hasChildNodes():
            rep += " >...</%s>" % self.nodeName
        else:
            rep += " />"

        return rep
Example #14
0
class IRCBot(irc.IRCClient):
    sasl_buffer = ""
    sasl_result = None
    sasl_login = None

    cancel_hilight_re = re.compile(ur"(?:(?<=\u00a7[0-9a-flmnor])|(?<!\u00a7)\b).+?\b")

    def __init__(self, factory, parent):
        self.factory     = factory
        self.nickname    = parent.nickname.encode('ascii')
        self.realname    = parent.realname.encode('ascii')
        self.username    = parent.ident.encode('ascii')
        self.ns_username = parent.username
        self.ns_password = parent.password
        self.password    = parent.server_password.encode('ascii')
        self.join_channels = parent.channel_map.keys()

        self.users        = InsensitiveDict()
        self.channels     = InsensitiveDict()
        self.cap_requests = set()

        self.parent = parent

    def register(self, nickname, hostname="foo", servername="bar"):
        self.sendLine("CAP LS")
        return irc.IRCClient.register(self, nickname, hostname, servername)

    def sendLine(self, line):
        if isinstance(line, unicode):
            line = line.encode('utf8', 'replace')
        irc.IRCClient.sendLine(self, line)

    def _parse_cap(self, cap):
        mod = ''
        while cap[0] in "-~=":
            mod, cap = mod + cap[0], cap[1:]
        if '/' in cap:
            vendor, cap = cap.split('/', 1)
        else:
            vendor = None
        return (cap, mod, vendor)

    def request_cap(self, *caps):
        self.cap_requests |= set(caps)
        self.sendLine("CAP REQ :{0}".format(' '.join(caps)))

    @defer.inlineCallbacks
    def end_cap(self):
        if self.sasl_result:
            yield self.sasl_result
        self.sendLine("CAP END")

    def irc_CAP(self, prefix, params):
        self.supports_cap = True
        identifier, subcommand, args = params
        args = args.split(' ')
        if subcommand == "LS":
            self.sasl_start(args)
            if not self.cap_requests:
                self.sendLine("CAP END")
        elif subcommand == "ACK":
            ack = []
            for cap in args:
                if not cap:
                    continue
                cap, mod, vendor = self._parse_cap(cap)
                if '-' in mod:
                    if cap in self.capabilities:
                        del self.capabilities[cap]
                    continue
                self.cap_requests.remove(cap)
                if cap == 'sasl':
                    self.sasl_next()
            if ack:
                self.sendLine("CAP ACK :{0}".format(' '.join(ack)))
            if not self.cap_requests:
                self.end_cap()
        elif subcommand == "NAK":
            # this implementation is probably not compliant but it will have to do for now
            for cap in args:
                self.cap_requests.remove(cap)
            if not self.cap_requests:
                self.end_cap()

    def signedOn(self):
        if ISSLTransport.providedBy(self.transport):
            cert = self.transport.getPeerCertificate()
            fp = cert.digest("sha1")
            verified = "verified" if self.factory.parent.server_fingerprint else "unverified"
            print("irc: connected securely. server fingerprint: {0} ({1})".format(fp, verified))
        else:
            print("irc: connected")
        
        if self.ns_username and self.ns_password and not self.sasl_login:
            self.msg('NickServ', 'IDENTIFY {0} {1}'.format(self.ns_username, self.ns_password))
        
        for channel in self.join_channels:
            self.join(channel)

    def irc_JOIN(self, prefix, params):
        nick = prefix.split('!')[0]
        channel = params[-1]
        if nick == self.nickname:
            self.joined(channel)
        else:
            self.userJoined(prefix, channel)

    def joined(self, channel):
        print('irc: joined channel')
        self.factory.client = self
        def who():
            self.sendLine("WHO " + channel)
        task.LoopingCall(who).start(30)
    
    def isupport(self, args):
        self.compute_prefix_names()
        
    def compute_prefix_names(self):
        KNOWN_NAMES = {"o": "op", "h": "halfop", "v": "voice"}
        prefixdata = self.supported.getFeature("PREFIX", {"o": ("@", 0), "v": ("+", 1)}).items()
        op_priority = ([priority for mode, (prefix, priority) in prefixdata if mode == "o"] + [None])[0]
        self.prefixes, self.statuses, self.priority = {}, {}, {}

        for mode, (prefix, priority) in prefixdata:
            name = "?"
            if mode in KNOWN_NAMES:
                name = KNOWN_NAMES[mode]
            elif priority == 0:
                if op_priority == 2:
                    name = "owner"
                else:
                    name = "admin"
            else:
                name = "+" + mode
            self.prefixes[mode] = prefix
            self.statuses[prefix] = name
            self.priority[name] = priority
            self.priority[mode] = priority
            self.priority[prefix] = priority

    def parse_prefixes(self, user, nick, prefixes=''):
        status = []
        prefixdata = self.supported.getFeature("PREFIX", {"o": ("@", 0), "v": ("+", 1)}).items()
        for mode, (prefix, priority) in prefixdata:
            if prefix in prefixes + nick:
                nick = nick.replace(prefix, '')
                status.append((prefix, priority))
        if nick == self.nickname:
            return
        user.status = ''.join(t[0] for t in sorted(status, key=lambda t: t[1]))
    
    def irc_RPL_WHOREPLY(self, prefix, params):
        _, channel, username, host, server, nick, status, hg = params
        if nick == self.nickname:
            return
        hops, gecos = hg.split(' ', 1)
        user = self.get_user(nick) or IRCUser(self, nick)
        user.username = username
        user.hostname = host
        user.oper = '*' in status
        user.away = status[0] == 'G'
        self.users[nick] = user
        self.get_channel(channel)[nick] = IRCUserInChannel(user, channel)
        self.parse_prefixes(user, nick, status[1:].replace('*', ''))
    
    def modeChanged(self, user, channel, _set, modes, args):
        args = list(args)
        if channel not in self.parent.channel_map:
            return
        for m, arg in zip(modes, args):
            if m in self.prefixes and arg != self.nickname:
                u = self.get_user(arg).on(channel)
                if u:
                    u.status = u.status.replace(self.prefixes[m], '')
                    if _set:
                        u.status = ''.join(sorted(list(u.status + self.prefixes[m]),
                                                  key=lambda k: self.priority[k]))

    def has_status(self, nick, status):
        if status != 0 and not status:
            return True
        if status not in self.priority:
            return False
        priority = self.priority[status]
        u = self.users.get(nick, None)
        return u and (u.priority is not None) and u.priority <= priority

    def get_channel(self, channel):
        return self.channels.setdefault(channel, InsensitiveDict())

    def get_user(self, nick):
        return self.users.get(nick, False)
    
    def userJoined(self, user, channel):
        nick = user.split('!')[0]
        user = IRCUser(self, nick)
        self.users[nick] = user
        self.get_channel(channel)[nick] = IRCUserInChannel(user, channel)
    
    def userRenamed(self, oldname, newname):
        if oldname not in self.users:
            return
        u = self.users[oldname]
        u.nick = newname
        self.users[newname] = u
        del self.users[oldname]
        for k, v in self.channels.items():
            if oldname in v:
                v[newname] = v[oldname]
                del v[oldname]
    
    def userLeft(self, user, channel):
        if user not in self.users:
            return
        del self.users[user]
        for k, v in self.channels.items():
            if user in v:
                del v[user]
    
    def userKicked(self, kickee, channel, kicker, message):
        if kickee not in self.users:
            return
        del self.users[kickee]
        for k, v in self.channels.items():
            if user in v:
                del v[user]
    
    def userQuit(self, user, quitMessage):
        if user not in self.users:
            return
        del self.users[user]
        for k, v in self.channels.items():
            if user in v:
                del v[user]

    def privmsg(self, user, channel, msg):
        pass

    def action(self, user, channel, msg):
        pass

    def irc_AUTHENTICATE(self, prefix, params):
        self.sasl_continue(params[0])

    def sasl_send(self, data):
        while data and len(data) >= 400:
            en, data = data[:400].encode('base64').replace('\n', ''), data[400:]
            self.sendLine("AUTHENTICATE " + en)
        if data:
            self.sendLine("AUTHENTICATE " + data.encode('base64').replace('\n', ''))
        else:
            self.sendLine("AUTHENTICATE +")

    def sasl_start(self, cap_list):
        if 'sasl' not in cap_list:
            return
        self.request_cap('sasl')
        self.sasl_result = defer.Deferred()
        self.sasl_mechanisms = list(SASL_MECHANISMS)

    def sasl_next(self):
        mech = None
        while not mech or not mech.is_valid():
            if not self.sasl_mechanisms:
                return False
            self.sasl_auth = mech = self.sasl_mechanisms.pop(0)(self.ns_username, self.ns_password)
        self.sendLine("AUTHENTICATE " + self.sasl_auth.name)
        return True

    def sasl_continue(self, data):
        if data == '+':
            data = ''
        else:
            data = data.decode('base64')
        if len(data) == 400:
            self.sasl_buffer += data
        else:
            response = self.sasl_auth.respond(self.sasl_buffer + data)
            if response is False:  # abort
                self.sendLine("AUTHENTICATE *")
            else:
                self.sasl_send(response)
            self.sasl_buffer = ""

    def sasl_finish(self):
        if self.sasl_result:
            self.sasl_result.callback(True)
            self.sasl_result = None

    def sasl_failed(self, whine=True):
        if self.sasl_login is False:
            return
        if self.sasl_next():
            return
        self.sasl_login = False
        self.sendLine("AUTHENTICATE *")
        self.sasl_finish()
        if whine:
            print("irc: failed to log in.")

    def irc_904(self, prefix, params):
        self.sasl_failed()

    def irc_905(self, prefix, params):
        self.sasl_failed()

    def irc_906(self, prefix, params):
        self.sasl_failed(False)

    def irc_907(self, prefix, params):
        self.sasl_failed(False)

    def irc_900(self, prefix, params):
        self.sasl_login = params[2]
        print("irc: logged in as '{0}' (using {1})".format(self.sasl_login, self.sasl_auth.name))

    def irc_903(self, prefix, params):
        self.sasl_finish()

    def alterCollidedNick(self, nickname):
        return nickname + '_'

    def cancel_hilights(self, channel, text):
        def hl(match):
            s = match.group(0)
            if len(s) >= 2 and s in self.get_channel(channel):
                return s[:-1] + '*' + s[-1]
            else:
                return s
        return self.cancel_hilight_re.sub(hl, text)

    def translate_colors(self, text):
        tr = {
            "0": "\x0301",
            "1": "\x0302",
            "2": "\x0303",
            "3": "\x0310",
            "4": "\x0304",
            "5": "\x0306",
            "6": "\x0308",
            "7": "\x0315",
            "8": "\x0314",
            "9": "\x0312",
            "a": "\x0309",
            "b": "\x0311",
            "c": "\x0304",
            "d": "\x0313",
            "e": "\x0308",
            "f": "\x0F",
        }
        return re.sub(ur"\u00a7([0-9a-f])", lambda m: tr.get(m.group(1), ""), text)

    def irc_relay(self, channel, message):
        message = message.decode('utf8')
        self.say(channel, self.translate_colors(self.cancel_hilights(channel, message)))
Example #15
0
File: irc.py Project: runfalk/mark2
class IRCBot(irc.IRCClient):
    def __init__(self, factory, plugin):
        self.factory     = factory
        self.nickname    = plugin.nickname.encode('ascii')
        self.realname    = plugin.realname.encode('ascii')
        self.username    = plugin.username.encode('ascii')
        self.ns_password = plugin.password
        self.password    = plugin.server_password.encode('ascii')
        self.channel     = plugin.channel.encode('ascii')
        self.console     = plugin.console
        self.irc_message = plugin.irc_message
        self.users       = InsensitiveDict()

    def signedOn(self):
        if have_ssl and isinstance(self.transport, TLSMemoryBIOProtocol):
            cert = self.transport.getPeerCertificate()
            fp = cert.digest("sha1")
            verified = "verified" if self.factory.parent.server_fingerprint else "unverified"
            self.console("irc: connected securely. server fingerprint: {} ({})".format(fp, verified))
        else:
            self.console("irc: connected")
        
        if self.ns_password:
            self.msg('NickServ', 'IDENTIFY %s' % self.ns_password)
        
        self.join(self.channel)

    def irc_JOIN(self, prefix, params):
        nick = prefix.split('!')[0]
        channel = params[-1]
        if nick == self.nickname:
            self.joined(channel)
        else:
            self.userJoined(prefix, channel)

    def joined(self, channel):
        self.console('irc: joined channel')
        self.factory.client = self
        def who(a):
            self.sendLine("WHO " + channel)
        self.factory.parent.repeating_task(who, 30, now=True)
    
    def isupport(self, args):
        self.compute_prefix_names()
        
    def compute_prefix_names(self):
        KNOWN_NAMES = {"o": "op", "h": "halfop", "v": "voice"}
        prefixdata = self.supported.getFeature("PREFIX", {"o": ("@", 0), "v": ("+", 1)}).items()
        op_priority = ([priority for mode, (prefix, priority) in prefixdata if mode == "o"] + [None])[0]
        self.prefixes, self.statuses, self.priority = {}, {}, {}

        for mode, (prefix, priority) in prefixdata:
            name = "?"
            if mode in KNOWN_NAMES:
                name = KNOWN_NAMES[mode]
            elif priority == 0:
                if op_priority == 2:
                    name = "owner"
                else:
                    name = "admin"
            else:
                name = "+" + mode
            self.prefixes[mode] = prefix
            self.statuses[prefix] = name
            self.priority[name] = priority
            self.priority[mode] = priority
            self.priority[prefix] = priority

    def parse_prefixes(self, user, nick, prefixes=''):
        status = []
        prefixdata = self.supported.getFeature("PREFIX", {"o": ("@", 0), "v": ("+", 1)}).items()
        for mode, (prefix, priority) in prefixdata:
            if prefix in prefixes + nick:
                nick = nick.replace(prefix, '')
                status.append((prefix, priority))
        if nick == self.nickname:
            return
        user.status = ''.join(t[0] for t in sorted(status, key=lambda t: t[1]))
    
    def irc_RPL_WHOREPLY(self, prefix, params):
        _, channel, username, host, server, nick, status, hg = params
        if nick == self.nickname:
            return
        hops, gecos = hg.split(' ', 1)
        user = IRCUser(self, nick)
        user.username = username
        user.hostname = host
        user.oper = '*' in status
        user.away = status[0] == 'G'
        self.users[nick] = user
        self.parse_prefixes(user, nick, status[1:].replace('*', ''))
    
    def modeChanged(self, user, channel, _set, modes, args):
        args = list(args)
        if channel.lower() != self.channel.lower():
            return
        for m, arg in zip(modes, args):
            if m in self.prefixes and arg != self.nickname:
                u = self.users.get(arg, None)
                if u:
                    u.status = u.status.replace(self.prefixes[m], '')
                    if _set:
                        u.status = ''.join(sorted(list(u.status + self.prefixes[m]),
                                                  key=lambda k: self.priority[k]))
    
    def userJoined(self, user, channel):
        nick = user.split('!')[0]
        user = IRCUser(self, nick)
        self.users[nick] = user
    
    def userRenamed(self, oldname, newname):
        if oldname not in self.users:
            return
        u = self.users[oldname]
        u.nick = newname
        self.users[newname] = u
        del self.users[oldname]
    
    def userLeft(self, user, channel):
        if user not in self.users:
            return
        del self.users[user]
    
    def userKicked(self, kickee, channel, kicker, message):
        if kickee not in self.users:
            return
        del self.users[kickee]
    
    def userQuit(self, user, quitMessage):
        if user not in self.users:
            return
        del self.users[user]

    def privmsg(self, user, channel, msg):
        if channel != self.channel:
            return
        if '!' not in user:
            return
        nick = user.split('!')[0]
        p = self.factory.parent
        
        if p.irc_chat_status and p.irc_chat_status in self.priority:
            priority = self.priority[p.irc_chat_status]
            u = self.users.get(nick, None)
            if not u or u.priority is None or u.priority > priority:
                return
        if p.irc_players_enabled and msg == p.irc_players_trigger:
            self.say(self.channel, p.irc_players_format.format(players=', '.join(p.players)))
        else:
            p.irc_message(nick, msg)

    def alterCollidedNick(self, nickname):
        return nickname + '_'

    def irc_relay(self, message):
        self.say(self.channel, message.encode('utf8'))
Example #16
0
class BaseLDAPEntry(WireStrAlias):
    dn = None
    _object_class_keys = set(get_strings('objectClass'))
    _object_class_lower_keys = set(get_strings('objectclass'))
    _user_password_keys = set(get_strings('userPassword'))

    def __init__(self, dn, attributes={}):
        """

        Initialize the object.

        @param dn: Distinguished Name of the object, as a string.

        @param attributes: Attributes of the object. A dictionary of
        attribute types to list of attribute values.

        """
        self._attributes = InsensitiveDict()
        self.dn = distinguishedname.DistinguishedName(dn)

        for k, vs in attributes.items():
            if k not in self._attributes:
                self._attributes[k] = []
            self._attributes[k].extend(vs)

        for k, vs in self._attributes.items():
            self._attributes[k] = self.buildAttributeSet(k, vs)

    def buildAttributeSet(self, key, values):
        return attributeset.LDAPAttributeSet(key, values)

    def __getitem__(self, key):
        for k in get_strings(key):
            if k in self._attributes:
                return self._attributes[k]
        raise KeyError(key)

    def get(self, key, default=None):
        for k in get_strings(key):
            if k in self._attributes:
                return self._attributes[k]
        return default

    def has_key(self, key):
        for k in get_strings(key):
            if k in self._attributes:
                return True
        return False

    def __contains__(self, key):
        return self.has_key(key)

    def __iter__(self):
        for key in self._attributes.iterkeys():
            yield key

    def keys(self):
        a = []
        for key in self._object_class_keys:
            if key in self._attributes:
                a.append(key)
        l = list(self._attributes.keys())
        l.sort(key=to_bytes)
        for key in l:
            if key.lower() not in self._object_class_lower_keys:
                a.append(key)
        return a

    def items(self):
        a = []

        for key in self._object_class_keys:
            objectClasses = list(self._attributes.get(key, []))
            objectClasses.sort(key=to_bytes)
            if objectClasses:
                a.append((key, objectClasses))

        l = list(self._attributes.items())
        l.sort(key=lambda x: to_bytes(x[0]))
        for key, values in l:
            if key.lower() not in self._object_class_lower_keys:
                vs = list(values)
                vs.sort()
                a.append((key, vs))

        return a

    def toWire(self):
        a = []

        for key in self._object_class_keys:
            objectClasses = list(self._attributes.get(key, []))
            objectClasses.sort(key=to_bytes)
            a.append((key, objectClasses))

        items_gen = ((key, self[key]) for key in self)
        items = sorted(items_gen, key=lambda x: to_bytes(x[0]))
        for key, values in items:
            if key.lower() not in self._object_class_lower_keys:
                vs = list(values)
                vs.sort()
                a.append((key, vs))
        return ldif.asLDIF(self.dn.getText(), a)

    def getLDIF(self):
        return self.toWire().decode('utf-8')

    def __eq__(self, other):
        if not isinstance(other, BaseLDAPEntry):
            return NotImplemented
        if self.dn != other.dn:
            return 0

        my = sorted((key for key in self), key=to_bytes)
        its = sorted((key for key in other), key=to_bytes)
        if my != its:
            return 0
        for key in my:
            myAttr = self[key]
            itsAttr = other[key]
            if myAttr != itsAttr:
                return 0
        return 1

    def __ne__(self, other):
        return not self == other

    def __len__(self):
        return len(self.keys())

    def __bool__(self):
        return True

    def __nonzero__(self):
        return self.__bool__()

    def __repr__(self):
        keys = sorted((key for key in self), key=to_bytes)
        a = []
        for key in keys:
            a.append('%s: %s' % (repr(key), repr(list(self[key]))))
        attributes = ', '.join(a)
        dn = to_bytes(self.dn.getText()) if six.PY2 else self.dn.getText()
        return '%s(%s, {%s})' % (
            self.__class__.__name__,
            repr(dn),
            attributes)

    def diff(self, other):
        """
        Compute differences between this and another LDAP entry.

        @param other: An LDAPEntry to compare to.

        @return: None if equal, otherwise a ModifyOp that would make
        this entry look like other.
        """
        assert self.dn == other.dn
        if self == other:
            return None

        r = []

        myKeys = set(key for key in self)
        otherKeys = set(key for key in other)

        addedKeys = list(otherKeys - myKeys)
        addedKeys.sort(key=to_bytes)  # for reproducability only
        for added in addedKeys:
            r.append(delta.Add(added, other[added]))

        deletedKeys = list(myKeys - otherKeys)
        deletedKeys.sort(key=to_bytes)  # for reproducability only
        for deleted in deletedKeys:
            r.append(delta.Delete(deleted, self[deleted]))

        sharedKeys = list(myKeys & otherKeys)
        sharedKeys.sort(key=to_bytes)  # for reproducability only
        for shared in sharedKeys:

            addedValues = list(other[shared] - self[shared])
            if addedValues:
                addedValues.sort(key=to_bytes)  # for reproducability only
                r.append(delta.Add(shared, addedValues))

            deletedValues = list(self[shared] - other[shared])
            if deletedValues:
                deletedValues.sort(key=to_bytes)  # for reproducability only
                r.append(delta.Delete(shared, deletedValues))

        return delta.ModifyOp(dn=self.dn, modifications=r)

    def bind(self, password):
        return defer.maybeDeferred(self._bind, password)

    def _bind(self, password):
        password = to_bytes(password)
        for key in self._user_password_keys:
            for digest in self.get(key, ()):
                digest = to_bytes(digest)
                if digest.startswith(b'{SSHA}'):
                    raw = base64.decodestring(digest[len(b'{SSHA}'):])
                    salt = raw[20:]
                    got = sshaDigest(password, salt)
                    if got == digest:
                        return self
                else:
                    # Plaintext
                    if digest == password:
                        return self
        raise ldaperrors.LDAPInvalidCredentials()

    def hasMember(self, dn):
        for memberDN in self.get('member', []):
            if memberDN == dn:
                return True
        return False

    def __hash__(self):
        # FIXME:https://github.com/twisted/ldaptor/issues/101
        # The hash should take into consideration any attribute used to
        # decide the equality.
        return hash(self.dn)