示例#1
0
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)
示例#2
0
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)
示例#3
0
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))
示例#4
0
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 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
示例#6
0
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)
示例#7
0
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)
示例#8
0
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)
示例#9
0
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)
示例#10
0
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)
示例#11
0
class IRCBot(irc.IRCClient):
    sasl_buffer = ""
    sasl_result = None
    sasl_login = None

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

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

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

        self.parent = parent

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def irc_relay(self, channel, message):
        message = message.decode('utf8')
        self.say(channel, self.translate_colors(self.cancel_hilights(channel, message)))
示例#12
0
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)

        #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 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))