def __init__( self, url, method="GET", postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=1, ): self.protocol.followRedirect = followRedirect self.timeout = timeout self.agent = agent if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault("Content-Length", len(postdata)) self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None
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 __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=1): self.protocol.followRedirect = followRedirect self.timeout = timeout self.agent = agent if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = 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 __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=True, redirectLimit=20, afterFoundGet=False): self.followRedirect = followRedirect self.redirectLimit = redirectLimit self._redirectCount = 0 self.timeout = timeout self.agent = agent self.afterFoundGet = afterFoundGet if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self._disconnectedDeferred = defer.Deferred() self.deferred = defer.Deferred() # Make sure the first callback on the result Deferred pauses the # callback chain until the request connection is closed. self.deferred.addBoth(self._waitForDisconnect) self.response_headers = None
def __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=1, proxy=None): self.protocol.followRedirect = followRedirect self.timeout = timeout self.agent = agent self.proxy = proxy if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None
def __init__(self, initial=None, case_mapping=None): if case_mapping is None: case_mapping = CaseMapping.by_name("rfc1459") elif isinstance(case_mapping, basestring): case_mapping = CaseMapping.by_name(case_mapping) self.case_mapping = case_mapping InsensitiveDict.__init__(self, initial, preserve=1)
class RestClientFactory(protocol.ClientFactory): protocol = client.HTTPPageGetter noisy = False def __init__(self, host, port, path, data, timeout = 60): self.log = log.getChild('ClientFactory') self.timeout = timeout self.agent = "RestClient" self.headers = InsensitiveDict() self.headers.setdefault('Content-Length', len(data)) self.headers.setdefault("connection", "close") self.method = 'POST' self.url = 'http://' + host + ':' + str(port) + path self.scheme = 'http' self.postdata = data self.host = host self.port = port self.path = path self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None self.cookies = {} def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.url) def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) return p def _cancelTimeout(self, result, timeoutCall): if timeoutCall.active(): timeoutCall.cancel() return result def gotHeaders(self, headers): self.response_headers = headers def gotStatus(self, version, status): self.version, self.status = version, status def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback(page) def noPage(self, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason) def clientConnectionFailed(self, _, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason)
class RestClientFactory(protocol.ClientFactory): protocol = client.HTTPPageGetter noisy = False def __init__(self, host, port, path, data, timeout=60): self.timeout = timeout self.agent = "RestClient" self.headers = InsensitiveDict() self.headers.setdefault('Content-Length', len(data)) self.headers.setdefault("connection", "close") self.method = 'POST' self.url = 'http://' + host + ':' + str(port) + path self.scheme = 'http' self.postdata = data self.host = host self.port = port self.path = path self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None self.cookies = {} def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.url) def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) return p def _cancelTimeout(self, result, timeoutCall): if timeoutCall.active(): timeoutCall.cancel() return result def gotHeaders(self, headers): self.response_headers = headers def gotStatus(self, version, status, message): self.version, self.status, self.message = version, status, message def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback(page) def noPage(self, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason) def clientConnectionFailed(self, _, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason)
class HeaderAwareHTTPClientFactory(client.HTTPClientFactory): protocol = myHTTPPageGetter noisy = False def __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=True, redirectLimit=20): self.followRedirect = followRedirect self.redirectLimit = redirectLimit self._redirectCount = 0 self.timeout = timeout self.agent = agent if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) p.method = self.method p.followRedirect = self.followRedirect if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) return p def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback((page, self.response_headers))
class HeaderAwareHTTPClientFactory(client.HTTPClientFactory): protocol = yourHTTPPageGetter noisy = False def __init__(self, url, method='GET', postdata=None, headers=None, agent="Coherence PageGetter", timeout=0, cookies=None, followRedirect=True, redirectLimit=20): self.followRedirect = followRedirect self.redirectLimit = redirectLimit self._redirectCount = 0 self.timeout = timeout self.agent = agent if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self._disconnectedDeferred = defer.Deferred() self.response_headers = None def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) p.method = self.method p.followRedirect = self.followRedirect if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) self._disconnectedDeferred = defer.Deferred() return p def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback((page, self.response_headers))
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 setIndexLink(template, indexFilename): """ Insert a link to an index document. Any node with a C{class} attribute set to C{index-link} will have its tag name changed to C{a} and its C{href} attribute set to C{indexFilename}. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type indexFilename: C{str} @param indexFilename: The address of the index document to which to link. If any C{False} value, this function will remove all index-link nodes. @return: C{None} """ indexLinks = domhelpers.findElementsWithAttribute(template, "class", "index-link") for link in indexLinks: if indexFilename is None: link.parentNode.removeChild(link) else: link.nodeName = link.tagName = link.endTagName = 'a' link.attributes = InsensitiveDict({'href': indexFilename})
def __init__(self, host, port, path, data, timeout = 60): self.timeout = timeout self.agent = "RestClient" self.headers = InsensitiveDict() self.headers.setdefault('Content-Length', len(data)) self.headers.setdefault("connection", "close") self.method = 'POST' self.url = 'http://' + host + ':' + str(port) + path self.postdata = data self.host = host self.port = port self.path = path self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None self.cookies = {}
def getChild(self, path, request): """ If this L{File}"s path refers to a directory, return a L{File} referring to the file named C{path} in that directory. If C{path} is the empty string, return a L{DirectoryLister} instead. @param path: The current path segment. @type path: L{bytes} @param request: The incoming request. @type request: An that provides L{twisted.web.iweb.IRequest}. @return: A resource representing the requested file or directory, or L{NoResource} if the path cannot be accessed. @rtype: An object that provides L{resource.IResource}. """ if isinstance(path, bytes): try: # Request calls urllib.unquote on each path segment, # leaving us with raw bytes. path = path.decode('utf-8') except UnicodeDecodeError: log.err( None, "Could not decode path segment as utf-8: %r" % (path, )) return self.childNotFound self.restat(reraise=False) if not self.isdir(): return self.childNotFound if path: try: fpath = self.child(path) except filepath.InsecurePath: return self.childNotFound else: fpath = self.childSearchPreauth(*self.indexNames) if fpath is None: return self.directoryListing() if not fpath.exists(): fpath = fpath.siblingExtensionSearch(*self.ignoredExts) if fpath is None: return self.childNotFound extension = fpath.splitext()[1] if platformType == "win32": # don't want .RPY to be different than .rpy, since that would allow # source disclosure. processor = InsensitiveDict(self.processors).get(extension) else: processor = self.processors.get(extension) if processor: return resource.IResource(processor(fpath.path, self.registry)) return self.createSimilarFile(fpath.path)
def getChild(self, path, request): """See twisted.web.Resource.getChild. """ self.restat() if not self.isdir(): return self.childNotFound if path: fpath = self.child(path) else: fpath = self.childSearchPreauth(*self.indexNames) if fpath is None: return self.directoryListing() if not fpath.exists(): fpath = fpath.siblingExtensionSearch(*self.ignoredExts) if fpath is None: return self.childNotFound if platformType == "win32": # don't want .RPY to be different than .rpy, since that would allow # source disclosure. processor = InsensitiveDict(self.processors).get( fpath.splitext()[1]) else: processor = self.processors.get(fpath.splitext()[1]) if processor: return resource.IResource(processor(fpath.path, self.registry)) return self.createSimilarFile(fpath.path)
def __init__(self, tagName, attributes=None, parentNode=None, filename=None, markpos=None, caseInsensitive=1, preserveCase=0, namespace='', escapeAttributes=1): 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 if escapeAttributes: 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 __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.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 __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=True, redirectLimit=20): self.followRedirect = followRedirect self.redirectLimit = redirectLimit self._redirectCount = 0 self.timeout = timeout self.agent = agent if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) #print( 'method: {}\nurl:{}\nheaders:{}\npostdata:{}'.format( method, url, self.headers, postdata ) ) self.waiting = 1 # Fixes Twisted 11.1.0+ support as HTTPClientFactory is expected # to have _disconnectedDeferred. See Twisted r32329. # As Scrapy implements it's own logic to handle redirects is not # needed to add the callback _waitForDisconnect. # Specifically this avoids the AttributeError exception when # clientConnectionFailed method is called. self._disconnectedDeferred = defer.Deferred() self.deferred = defer.Deferred() self.response_headers = None
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 test01_proxy(self): data = '{"type": "PacketPing"}' headers = InsensitiveDict() headers.setdefault('Content-Length', len(data)) headers.setdefault("connection", "close") headers.setdefault("proxy-connection", "foo") host = '127.0.0.1' port = 19481 path = '/POKER_REST' factory = pokerrestclient.PokerProxyClientFactory('POST', path, '1.1', headers, data, MockRequest(), 6, host + ':' + str(port) + path) reactor.connectTCP(host, port, factory) factory.deferred.addCallback(self.assertNotEquals, None) return factory.deferred
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 __init__( self, url, method="GET", postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=True, redirectLimit=20, afterFoundGet=False, ): self.followRedirect = followRedirect self.redirectLimit = redirectLimit self._redirectCount = 0 self.timeout = timeout self.agent = agent self.afterFoundGet = afterFoundGet if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault("Content-Length", len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None
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)
def __init__(self, host, port, path, data, timeout=60): self.timeout = timeout self.agent = "RestClient" self.headers = InsensitiveDict() self.headers.setdefault("Content-Length", len(data)) self.headers.setdefault("connection", "close") self.method = "POST" self.url = "http://" + host + ":" + str(port) + path self.scheme = "http" self.postdata = data self.host = host self.port = port self.path = path self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None self.cookies = {} self._disconnectedDeferred = defer.Deferred()
def locateChild(self, ctx, segments): r = self.children.get(segments[0], None) if r: return r, segments[1:] path = segments[0] self.fp.restat() if not self.fp.isdir(): return rend.NotFound if path: fpath = self.fp.child(path) else: fpath = self.fp.childSearchPreauth(*self.indexNames) if fpath is None: if self.allowListing: return self.directoryListing(), segments[1:] else: return rend.NotFound if not fpath.exists(): fpath = fpath.siblingExtensionSearch(*self.ignoredExts) if fpath is None: return rend.NotFound # Don't run processors on directories - if someone wants their own # customized directory rendering, subclass File instead. if fpath.isfile(): if platformType == "win32": # don't want .RPY to be different than .rpy, since that # would allow source disclosure. processor = InsensitiveDict(self.processors).get( fpath.splitext()[1]) else: processor = self.processors.get(fpath.splitext()[1]) if processor: return (inevow.IResource(processor(fpath.path, self.registry)), segments[1:]) return self.createSimilarFile(fpath.path), segments[1:]
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 __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 getChild(self, path, request): """ If this L{File}'s path refers to a directory, return a L{File} referring to the file named C{path} in that directory. If C{path} is the empty string, return a L{DirectoryLister} instead. """ self.restat(reraise=False) if not self.isdir(): return self.childNotFound if path: try: fpath = self.child(path) except filepath.InsecurePath: return self.childNotFound else: fpath = self.childSearchPreauth(*self.indexNames) if fpath is None: return self.directoryListing() if not fpath.exists(): fpath = fpath.siblingExtensionSearch(*self.ignoredExts) if fpath is None: return self.childNotFound if platformType == "win32": # don't want .RPY to be different than .rpy, since that would allow # source disclosure. processor = InsensitiveDict(self.processors).get( fpath.splitext()[1]) else: processor = self.processors.get(fpath.splitext()[1]) if processor: return resource.IResource(processor(fpath.path, self.registry)) return self.createSimilarFile(fpath.path)
def index(document, filename, chapterReference): """ Extract index entries from the given document and store them for later use and insert named anchors so that the index can link back to those entries. Any node with a C{class} attribute set to C{index} is considered an index entry. @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @type filename: C{str} @param filename: A link to the output for the given document which will be included in the index to link to any index entry found here. @type chapterReference: ??? @param chapterReference: ??? @return: C{None} """ entries = domhelpers.findElementsWithAttribute(document, "class", "index") if not entries: return i = 0 for entry in entries: i += 1 anchor = 'index%02d' % i if chapterReference: ref = getSectionReference(entry) or chapterReference else: ref = 'link' indexer.addEntry(filename, anchor, entry.attributes['value'], ref) # does nodeName even affect anything? entry.nodeName = entry.tagName = entry.endTagName = 'a' entry.attributes = InsensitiveDict({'name': anchor})
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
def __send_http_response(self, inh, request, response_msg): """ When we've know what message to send back to the HTTP client which has connected to the HTTP server, we issue this message back. @param inh: an inhabinant who will receive the response @type inh: AbstractInhabitant @param request: web server request. @type request: Request @param response_msg: response message to send. @type response_msg: AbstractMessage """ if not self.connection_alive: logger.debug('Connection died inside %r while trying ' 'to reply with %r', self, response_msg) # That's very very bad! We should put the message back to queue. self.tr_manager.post_message(response_msg) else: logger.debug('Sending response %r to %r', response_msg, request.requestHeaders) response_msg.in_transfer = True # Add the default server-specific headers, # then the message-specific headers. _headers = InsensitiveDict(dict(request.responseHeaders .getAllRawHeaders())) _pragma = ','.join(ifilter(None, [response_msg.get_pragma(), self.extra_pragma()])) HTTPTransport.update_headers(_headers, {'Pragma': [_pragma]}) HTTPTransport.update_headers(_headers, response_msg.get_headers()) for k, v_list in _headers.iteritems(): request.responseHeaders.setRawHeaders(k, v_list) logger.debug('New headers for %r are: %r', response_msg, request.responseHeaders) @contract_epydoc def produce_body_in_main(body, msg): """ @type body: col.Iterable @type msg: AbstractMessage """ assert in_main_thread() try: producer = LazyPullProducer(request, body) producer.completed.addBoth(self._ready_to_finish.callback) except Exception: logger.exception('Error during writing back the request:') # We haven't succeeded to send the message to the client. # Put it back to the queue. callInThread(self.tr_manager.post_message, msg) assert not in_main_thread() # get_body() may take long _body = response_msg.get_body() logger.debug('Writing body: %r', response_msg) callFromThread(produce_body_in_main, _body, response_msg)
def __send_http_response(self, inh, request, response_msg): """ When we've know what message to send back to the HTTP client which has connected to the HTTP server, we issue this message back. @param inh: an inhabinant who will receive the response @type inh: AbstractInhabitant @param request: web server request. @type request: Request @param response_msg: response message to send. @type response_msg: AbstractMessage """ if not self.connection_alive: logger.debug( 'Connection died inside %r while trying ' 'to reply with %r', self, response_msg) # That's very very bad! We should put the message back to queue. self.tr_manager.post_message(response_msg) else: logger.debug('Sending response %r to %r', response_msg, request.requestHeaders) response_msg.in_transfer = True # Add the default server-specific headers, # then the message-specific headers. _headers = InsensitiveDict( dict(request.responseHeaders.getAllRawHeaders())) _pragma = ','.join( ifilter(None, [response_msg.get_pragma(), self.extra_pragma()])) HTTPTransport.update_headers(_headers, {'Pragma': [_pragma]}) HTTPTransport.update_headers(_headers, response_msg.get_headers()) for k, v_list in _headers.iteritems(): request.responseHeaders.setRawHeaders(k, v_list) logger.debug('New headers for %r are: %r', response_msg, request.responseHeaders) @contract_epydoc def produce_body_in_main(body, msg): """ @type body: col.Iterable @type msg: AbstractMessage """ assert in_main_thread() try: producer = LazyPullProducer(request, body) producer.completed.addBoth(self._ready_to_finish.callback) except Exception: logger.exception('Error during writing back the request:') # We haven't succeeded to send the message to the client. # Put it back to the queue. callInThread(self.tr_manager.post_message, msg) assert not in_main_thread() # get_body() may take long _body = response_msg.get_body() logger.debug('Writing body: %r', response_msg) callFromThread(produce_body_in_main, _body, response_msg)
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'))
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)))
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
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'))
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
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)
class HTTPClientFactory(protocol.ClientFactory): """Download a given URL. @type deferred: Deferred @ivar deferred: A Deferred that will fire when the content has been retrieved. Once this is fired, the ivars `status', `version', and `message' will be set. @type status: str @ivar status: The status of the response. @type version: str @ivar version: The version of the response. @type message: str @ivar message: The text message returned with the status. @type response_headers: dict @ivar response_headers: The headers that were specified in the response from the server. @type method: str @ivar method: The HTTP method to use in the request. This should be one of OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, or CONNECT (case matters). Other values may be specified if the server being contacted supports them. @type redirectLimit: int @ivar redirectLimit: The maximum number of HTTP redirects that can occur before it is assumed that the redirection is endless. @type afterFoundGet: C{bool} @ivar afterFoundGet: Deviate from the HTTP 1.1 RFC by handling redirects the same way as most web browsers; if the request method is POST and a 302 status is encountered, the redirect is followed with a GET method @type _redirectCount: int @ivar _redirectCount: The current number of HTTP redirects encountered. @ivar _disconnectedDeferred: A L{Deferred} which only fires after the last connection associated with the request (redirects may cause multiple connections to be required) has closed. The result Deferred will only fire after this Deferred, so that callers can be assured that there are no more event sources in the reactor once they get the result. """ protocol = HTTPPageGetter url = None scheme = None host = '' port = None path = None def __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=True, redirectLimit=20, afterFoundGet=False): self.followRedirect = followRedirect self.redirectLimit = redirectLimit self._redirectCount = 0 self.timeout = timeout self.agent = agent self.afterFoundGet = afterFoundGet if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self._disconnectedDeferred = defer.Deferred() self.deferred = defer.Deferred() # Make sure the first callback on the result Deferred pauses the # callback chain until the request connection is closed. self.deferred.addBoth(self._waitForDisconnect) self.response_headers = None def _waitForDisconnect(self, passthrough): """ Chain onto the _disconnectedDeferred, preserving C{passthrough}, so that the result is only available after the associated connection has been closed. """ self._disconnectedDeferred.addCallback(lambda ignored: passthrough) return self._disconnectedDeferred def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.url) def setURL(self, url): self.url = url scheme, host, port, path = _parse(url) if scheme and host: self.scheme = scheme self.host = host self.port = port self.path = path def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) p.followRedirect = self.followRedirect p.afterFoundGet = self.afterFoundGet if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) return p def _cancelTimeout(self, result, timeoutCall): if timeoutCall.active(): timeoutCall.cancel() return result def gotHeaders(self, headers): self.response_headers = headers if headers.has_key('set-cookie'): for cookie in headers['set-cookie']: cookparts = cookie.split(';') cook = cookparts[0] cook.lstrip() k, v = cook.split('=', 1) self.cookies[k.lstrip()] = v.lstrip() def gotStatus(self, version, status, message): self.version, self.status, self.message = version, status, message def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback(page) def noPage(self, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason) def clientConnectionFailed(self, _, reason): """ When a connection attempt fails, the request cannot be issued. If no result has yet been provided to the result Deferred, provide the connection failure reason as an error result. """ if self.waiting: self.waiting = 0 # If the connection attempt failed, there is nothing more to # disconnect, so just fire that Deferred now. self._disconnectedDeferred.callback(None) self.deferred.errback(reason)
def _create_message_from_headers(self, headers, auth_peer, me, known_inhs, must_know_peer=True, peer_proto=None): """ Given the headers of the message, the "myself" reference to the receiving inhabitant, as well as the container of other known inhabitants, create a message. @param headers: The headers of the message. @type headers: InsensitiveDict @param auth_peer: What inhabitant authenticated as the originator of the message? @type auth_peer: NoneType, AbstractInhabitant @param me: The inhabitant object of the system processing this message. @type me: AbstractInhabitant @param known_inhs: The dictionary-like mapping the UUIDs to other known inhabitants of the system. @param must_know_peer: Whether we must know the peer beforehand to process the message. At the moment, it is used on the host, when it receives the messages from unknown other hosts. In the future, we ALWAYS must know the peer. @type must_know_peer: bool @todo: As soon as the Host->Host connections are preceded with the connection from the Node to the target Host (which notifies the target Host about the expected connection), C{must_know_peer} argument should be removed (and the code kept in the C{must_know_peer = True} position). @param peer_proto: The function which creates a peer object prototype depending upon the available information, if the peer is unknown. Default value is a subclass of C{AbstractInhabitant} constructor. Must accept all the usual C{AbstractInhabitant} constructor arguments. @todo: Remove peer_proto as long as must_know_peer is removed. @returns: The new message object. @rtype: AbstractMessage @raises MessageProcessingException: if the message could not be processed properly. """ if peer_proto is None: peer_proto = AbstractInhabitant # Validate HTTP request pragma_data_list = headers.get('Pragma', None) if pragma_data_list is None or not pragma_data_list: raise MessageProcessingException('No message type header') assert isinstance(pragma_data_list, list) if len(pragma_data_list) != 1: raise MessageProcessingException( 'Message type header is misconstructed') pragma_data = HTTPTransport.parse_pragma_header(pragma_data_list[0]) # Validate again if 'msgtype' not in pragma_data: raise MessageProcessingException('No message type') if 'msgid' not in pragma_data: raise MessageProcessingException('No message ID') if 'from' not in pragma_data: raise MessageProcessingException('No source peer UUID') if 'to' not in pragma_data: raise MessageProcessingException('No destination peer UUID') if 'status_code' not in pragma_data: logger.warning('No status code!') # TODO: after some time (when all clients have been migrated), # change it to "raise MessageProcessingException()" below. # raise MessageProcessingException('No status code') # Validate build version if 'build' in pragma_data: _build_str = pragma_data['build'] try: self.validate_build(_build_str) except MessageProcessingException: raise except Exception: logger.exception('Received the unparseable build version %r:', _build_str) raise MessageProcessingException( 'Incorrect build version: {}'.format(_build_str)) # Validate status code try: status_code_txt = pragma_data.get('status_code', 0) int(status_code_txt) except: logger.error('Received the unparseable status_code %r:', status_code_txt) # TODO: after some time (when all clients have been migrated), # change it to "raise MessageProcessingException() msg_type = pragma_data['msgtype'] msg_uuid = uuid.UUID(pragma_data['msgid']) _from_uuid = uuid.UUID(pragma_data['from']) to_uuid = uuid.UUID(pragma_data['to']) status_code = int(pragma_data.get('status_code', 0)) # Pre-validate origination peer if _from_uuid == NULL_UUID and auth_peer is None: raise MessageProcessingException( 'Missing source UUID: {}'.format(_from_uuid)) from_uuid = _from_uuid if _from_uuid != NULL_UUID \ else auth_peer.uuid # This still can be NULL_UUID at this point. if from_uuid == NULL_UUID: logger.debug('Totally no idea what host does %r have', auth_peer) # Validate termination UUID if me.uuid in (to_uuid, NULL_UUID): direct = True dst_inh = me elif to_uuid in known_inhs: direct = False dst_inh = known_inhs[to_uuid] logger.debug('Passthrough connection from %r to %r', from_uuid, to_uuid) else: raise MessageProcessingException( 'Unknown destination UUID: {}'.format(to_uuid)) # Now create the AbstractMessage object according # to the received information. # Some more validation of the origination peer if auth_peer is not None: logger.debug('Assuming sender/auth_peer is %r', auth_peer) src_inh = auth_peer elif from_uuid not in known_inhs and must_know_peer: raise MessageProcessingException( 'Unknown source UUID: {}'.format(from_uuid)) else: logger.debug('Assuming sender/uuid is %r', from_uuid) # Try to get the peer somehow src_inh = known_inhs.get(from_uuid, None) if src_inh is None: src_inh = peer_proto(uuid=from_uuid) logger.debug('Finally, sender is %r', src_inh) assert self.tr_manager is not None message = self.tr_manager.create_message(name=msg_type, src=src_inh, dst=dst_inh, uuid=msg_uuid, direct=direct, status_code=status_code) message.init_from_headers(InsensitiveDict(headers)) return message
# enable: W9602 # an example of call has_key on a dict # a warning should be generated if {}.has_key("bar"): pass foo = {} if foo.has_key("bar"): pass # an example of call has_key on a existing class # no warnings should be showed in this case from twisted.python.util import InsensitiveDict bar = InsensitiveDict() if bar.has_key("bar"): pass # an example of call has_key on a unknown object # no warnings should be showed as we do not know what it is result = baz.has_key("bar")
class HTTPClientFactory(protocol.ClientFactory): """Download a given URL. @type deferred: Deferred @ivar deferred: A Deferred that will fire when the content has been retrieved. Once this is fired, the ivars `status', `version', and `message' will be set. @type status: str @ivar status: The status of the response. @type version: str @ivar version: The version of the response. @type message: str @ivar message: The text message returned with the status. @type response_headers: dict @ivar response_headers: The headers that were specified in the response from the server. """ protocol = HTTPPageGetter url = None scheme = None host = '' port = None path = None def __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=1): self.protocol.followRedirect = followRedirect self.timeout = timeout self.agent = agent if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.url) def setURL(self, url): self.url = url scheme, host, port, path = _parse(url) if scheme and host: self.scheme = scheme self.host = host self.port = port self.path = path def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) return p def _cancelTimeout(self, result, timeoutCall): if timeoutCall.active(): timeoutCall.cancel() return result def gotHeaders(self, headers): self.response_headers = headers if headers.has_key('set-cookie'): for cookie in headers['set-cookie']: cookparts = cookie.split(';') cook = cookparts[0] cook.lstrip() k, v = cook.split('=', 1) self.cookies[k.lstrip()] = v.lstrip() def gotStatus(self, version, status, message): self.version, self.status, self.message = version, status, message def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback(page) def noPage(self, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason) def clientConnectionFailed(self, _, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason)
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
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
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)
class HTTPClientFactory(protocol.ClientFactory): """Download a given URL. @type deferred: Deferred @ivar deferred: A Deferred that will fire when the content has been retrieved. Once this is fired, the ivars `status', `version', and `message' will be set. @type status: str @ivar status: The status of the response. @type version: str @ivar version: The version of the response. @type message: str @ivar message: The text message returned with the status. @type response_headers: dict @ivar response_headers: The headers that were specified in the response from the server. @type method: str @ivar method: The HTTP method to use in the request. This should be one of OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, or CONNECT (case matters). Other values may be specified if the server being contacted supports them. @type redirectLimit: int @ivar redirectLimit: The maximum number of HTTP redirects that can occur before it is assumed that the redirection is endless. @type afterFoundGet: C{bool} @ivar afterFoundGet: Deviate from the HTTP 1.1 RFC by handling redirects the same way as most web browsers; if the request method is POST and a 302 status is encountered, the redirect is followed with a GET method @type _redirectCount: int @ivar _redirectCount: The current number of HTTP redirects encountered. """ protocol = HTTPPageGetter url = None scheme = None host = "" port = None path = None def __init__( self, url, method="GET", postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=True, redirectLimit=20, afterFoundGet=False, ): self.followRedirect = followRedirect self.redirectLimit = redirectLimit self._redirectCount = 0 self.timeout = timeout self.agent = agent self.afterFoundGet = afterFoundGet if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault("Content-Length", len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.url) def setURL(self, url): self.url = url scheme, host, port, path = _parse(url) if scheme and host: self.scheme = scheme self.host = host self.port = port self.path = path def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) p.followRedirect = self.followRedirect p.afterFoundGet = self.afterFoundGet if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) return p def _cancelTimeout(self, result, timeoutCall): if timeoutCall.active(): timeoutCall.cancel() return result def gotHeaders(self, headers): self.response_headers = headers if headers.has_key("set-cookie"): for cookie in headers["set-cookie"]: cookparts = cookie.split(";") cook = cookparts[0] cook.lstrip() k, v = cook.split("=", 1) self.cookies[k.lstrip()] = v.lstrip() def gotStatus(self, version, status, message): self.version, self.status, self.message = version, status, message def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback(page) def noPage(self, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason) def clientConnectionFailed(self, _, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason)
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)
class HTTPClientFactory(protocol.ClientFactory): """Download a given URL. @type deferred: Deferred @ivar deferred: A Deferred that will fire when the content has been retrieved. Once this is fired, the ivars `status', `version', and `message' will be set. @type status: str @ivar status: The status of the response. @type version: str @ivar version: The version of the response. @type message: str @ivar message: The text message returned with the status. @type response_headers: dict @ivar response_headers: The headers that were specified in the response from the server. """ protocol = HTTPPageGetter url = None scheme = None host = '' port = None path = None def __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=1, proxy=None): self.protocol.followRedirect = followRedirect self.timeout = timeout self.agent = agent self.proxy = proxy if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.url) def setURL(self, url): self.url = url scheme, host, port, path = _parse(url) if scheme and host: self.scheme = scheme self.host = host self.port = port if self.proxy: self.path = "%s://%s:%s%s" % (self.scheme, self.host, self.port, path) else: self.path = path def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) return p def _cancelTimeout(self, result, timeoutCall): if timeoutCall.active(): timeoutCall.cancel() return result def gotHeaders(self, headers): self.response_headers = headers if headers.has_key('set-cookie'): for cookie in headers['set-cookie']: cookparts = cookie.split(';') cook = cookparts[0] cook.lstrip() k, v = cook.split('=', 1) self.cookies[k.lstrip()] = v.lstrip() def gotStatus(self, version, status, message): self.version, self.status, self.message = version, status, message def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback(page) def noPage(self, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason) def clientConnectionFailed(self, _, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason)
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'))
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
class HTTPClientFactory(protocol.ClientFactory): """Download a given URL. @type deferred: Deferred @ivar deferred: A Deferred that will fire when the content has been retrieved. Once this is fired, the ivars `status', `version', and `message' will be set. @type status: str @ivar status: The status of the response. @type version: str @ivar version: The version of the response. @type message: str @ivar message: The text message returned with the status. @type response_headers: dict @ivar response_headers: The headers that were specified in the response from the server. @type method: str @ivar method: The HTTP method to use in the request. This should be one of OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, or CONNECT (case matters). Other values may be specified if the server being contacted supports them. @type redirectLimit: int @ivar redirectLimit: The maximum number of HTTP redirects that can occur before it is assumed that the redirection is endless. @type afterFoundGet: C{bool} @ivar afterFoundGet: Deviate from the HTTP 1.1 RFC by handling redirects the same way as most web browsers; if the request method is POST and a 302 status is encountered, the redirect is followed with a GET method @type _redirectCount: int @ivar _redirectCount: The current number of HTTP redirects encountered. """ protocol = HTTPPageGetter url = None scheme = None host = '' port = None path = None def __init__(self, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter", timeout=0, cookies=None, followRedirect=True, redirectLimit=20, afterFoundGet=False): self.followRedirect = followRedirect self.redirectLimit = redirectLimit self._redirectCount = 0 self.timeout = timeout self.agent = agent self.afterFoundGet = afterFoundGet if cookies is None: cookies = {} self.cookies = cookies if headers is not None: self.headers = InsensitiveDict(headers) else: self.headers = InsensitiveDict() if postdata is not None: self.headers.setdefault('Content-Length', len(postdata)) # just in case a broken http/1.1 decides to keep connection alive self.headers.setdefault("connection", "close") self.postdata = postdata self.method = method self.setURL(url) self.waiting = 1 self.deferred = defer.Deferred() self.response_headers = None def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.url) def setURL(self, url): self.url = url scheme, host, port, path = _parse(url) if scheme and host: self.scheme = scheme self.host = host self.port = port self.path = path def buildProtocol(self, addr): p = protocol.ClientFactory.buildProtocol(self, addr) p.followRedirect = self.followRedirect p.afterFoundGet = self.afterFoundGet if self.timeout: timeoutCall = reactor.callLater(self.timeout, p.timeout) self.deferred.addBoth(self._cancelTimeout, timeoutCall) return p def _cancelTimeout(self, result, timeoutCall): if timeoutCall.active(): timeoutCall.cancel() return result def gotHeaders(self, headers): self.response_headers = headers if headers.has_key('set-cookie'): for cookie in headers['set-cookie']: cookparts = cookie.split(';') cook = cookparts[0] cook.lstrip() k, v = cook.split('=', 1) self.cookies[k.lstrip()] = v.lstrip() def gotStatus(self, version, status, message): self.version, self.status, self.message = version, status, message def page(self, page): if self.waiting: self.waiting = 0 self.deferred.callback(page) def noPage(self, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason) def clientConnectionFailed(self, _, reason): if self.waiting: self.waiting = 0 self.deferred.errback(reason)
def _render(self, request, avatar): """Node-specific request processing. @param request: Web server request. @type request: Request @type avatar: Host @returns: nothing (not a C{Deferred} object!). But, due to C{inlineCallbacks}, yields the intermediate C{Deferred}s. @todo: Proper error handling. @todo: Properly handle the situation when the passthrough is restricted: generate the reply which contains the Error 404. @todo: This should be streamlined using super() as soon as C{twisted.web.resource.Resource} becomes a new-style class """ assert not in_main_thread() # Kind-of-calling the parent, but the parent in this case should # return a Deferred as well,... let's not bother with it. # DeferredProcessingResource._render(self, request, avatar) logger.debug('') logger.debug('') logger.debug('Avatar %r;' '\tincoming headers %r;' '\tfrom %r', avatar, request.requestHeaders, request.client) # We setup the default headers for response even before # we start analyzing the incoming message, # so that if analyzing fails for some reason, we have the headers # and can create a more-or-less proper error reply. _requestHeaders = InsensitiveDict(dict(request.requestHeaders .getAllRawHeaders())) _responseHeaders = InsensitiveDict() self.initialize_headers(_responseHeaders) message = self.create_message_from_headers(headers=_requestHeaders, auth_peer=avatar) message.body_receiver = RequestBodyReceiver(message=message, request=request) # Make sure the body is received, before going further dummy_received_data = yield message.body_receiver.on_finish assert not in_main_thread() if message.direct: # If this is the message directed to ourselves, # process it and send the response logger.debug('') logger.debug('> Der Mitteilung Nahert: %r von %s', message, message.src) # Process the incoming message try: self.tr_manager.handle_incoming_message(message) except TransactionProcessingException as e: # The incoming transaction cannot be processed. # TODO: handle error properly, send a error reply maybe logger.error('Error (%r) during incoming msg processing: %s', e, e) logger.debug('Will send response to %r from %r %s', message, message.src, hash(message.src)) for k, v_list in _responseHeaders.iteritems(): request.responseHeaders.setRawHeaders(k, v_list) logger.debug('Done with response headers') elif self._accept_passthrough_message(message): # Non-direct message, and passthrough allowed: # wait for the body, then put in the queue. logger.debug('Passthrough message %r: body already available', message) self.tr_manager.post_message(message) else: # Passthrough is restricted for this message! raise NotImplementedError(u'Failed message {!r}:\n' u'from: {!r}\n' u' to: {!r}'.format(message, message.src, message.dst)) # How to check if we still need a message? still_need_checker = lambda: self.connection_alive # No matter if we are processing the message or passing it through, # we must send a response somehow. # If this is the message to us, we'd prefer a response to reply it; # but if this is a passthrough message, it will go to a different peer. prefer_msg_uuid = message.uuid if message.direct else None try: # Let's (asynchronously) wait for the response message here. resp_msg = self.__response_msg \ = yield self.tr_manager.wait_for_message_for_peer( inh=message.src, prefer_msg_uuid=prefer_msg_uuid, still_wait_checker=still_need_checker) except internet_error.ConnectionClosed as e: logger.warning('Stopped to wait for a message due to %r', e) self._handle_connection_close(Failure(e)) except Exception as e: logger.exception('Stopped to wait for a message due to %r', e) self._handle_connection_close(Failure(e)) else: # Since now and till the end of transfer we store the message # in self.__response_msg. assert not in_main_thread() if resp_msg is None: # The connection died already, while waiting for the message. assert not self.connection_alive else: # Got the message, send it back assert isinstance(resp_msg, AbstractMessage), repr(resp_msg) self.__send_http_response(message.src, request, resp_msg)
def _render(self, request, avatar): """Node-specific request processing. @param request: Web server request. @type request: Request @type avatar: Host @returns: nothing (not a C{Deferred} object!). But, due to C{inlineCallbacks}, yields the intermediate C{Deferred}s. @todo: Proper error handling. @todo: Properly handle the situation when the passthrough is restricted: generate the reply which contains the Error 404. @todo: This should be streamlined using super() as soon as C{twisted.web.resource.Resource} becomes a new-style class """ assert not in_main_thread() # Kind-of-calling the parent, but the parent in this case should # return a Deferred as well,... let's not bother with it. # DeferredProcessingResource._render(self, request, avatar) logger.debug('') logger.debug('') logger.debug('Avatar %r;' '\tincoming headers %r;' '\tfrom %r', avatar, request.requestHeaders, request.client) # We setup the default headers for response even before # we start analyzing the incoming message, # so that if analyzing fails for some reason, we have the headers # and can create a more-or-less proper error reply. _requestHeaders = InsensitiveDict( dict(request.requestHeaders.getAllRawHeaders())) _responseHeaders = InsensitiveDict() self.initialize_headers(_responseHeaders) message = self.create_message_from_headers(headers=_requestHeaders, auth_peer=avatar) message.body_receiver = RequestBodyReceiver(message=message, request=request) # Make sure the body is received, before going further dummy_received_data = yield message.body_receiver.on_finish assert not in_main_thread() if message.direct: # If this is the message directed to ourselves, # process it and send the response logger.debug('') logger.debug('> Der Mitteilung Nahert: %r von %s', message, message.src) # Process the incoming message try: self.tr_manager.handle_incoming_message(message) except TransactionProcessingException as e: # The incoming transaction cannot be processed. # TODO: handle error properly, send a error reply maybe logger.error('Error (%r) during incoming msg processing: %s', e, e) logger.debug('Will send response to %r from %r %s', message, message.src, hash(message.src)) for k, v_list in _responseHeaders.iteritems(): request.responseHeaders.setRawHeaders(k, v_list) logger.debug('Done with response headers') elif self._accept_passthrough_message(message): # Non-direct message, and passthrough allowed: # wait for the body, then put in the queue. logger.debug('Passthrough message %r: body already available', message) self.tr_manager.post_message(message) else: # Passthrough is restricted for this message! raise NotImplementedError(u'Failed message {!r}:\n' u'from: {!r}\n' u' to: {!r}'.format( message, message.src, message.dst)) # How to check if we still need a message? still_need_checker = lambda: self.connection_alive # No matter if we are processing the message or passing it through, # we must send a response somehow. # If this is the message to us, we'd prefer a response to reply it; # but if this is a passthrough message, it will go to a different peer. prefer_msg_uuid = message.uuid if message.direct else None try: # Let's (asynchronously) wait for the response message here. resp_msg = self.__response_msg \ = yield self.tr_manager.wait_for_message_for_peer( inh=message.src, prefer_msg_uuid=prefer_msg_uuid, still_wait_checker=still_need_checker) except internet_error.ConnectionClosed as e: logger.warning('Stopped to wait for a message due to %r', e) self._handle_connection_close(Failure(e)) except Exception as e: logger.exception('Stopped to wait for a message due to %r', e) self._handle_connection_close(Failure(e)) else: # Since now and till the end of transfer we store the message # in self.__response_msg. assert not in_main_thread() if resp_msg is None: # The connection died already, while waiting for the message. assert not self.connection_alive else: # Got the message, send it back assert isinstance(resp_msg, AbstractMessage), repr(resp_msg) self.__send_http_response(message.src, request, resp_msg)