示例#1
0
	def parse_request(self, message):
		try:
		    from http_parser.parser import HttpParser
		except ImportError:
		    from http_parser.pyparser import HttpParser

		p = HttpParser()
		nparsed = p.execute(message,len(message))
		
		self.method = p.get_method()
		self.path = p.get_path()
		self.headers = p.get_headers()

		if p.get_method() == 'GET':
			self.status = 200

		#if "Range" in p.get_headers():
		#	strings = self.headers["Range"]
		#	print strings

		elif p.get_method() != 'GET':
			self.status = 501		#if the method is not a GET
			#TODO maybe make this a head request eventually if you do the download accelerator

		if not p.get_method():
			self.status = 400

		if p.get_path() == '/':
			self.path = '/index.html'

		elif p.get_path().endswith('/'):
			self.path += 'index.html'
		
		if p.get_path() is None:
			self.status = 501


		#print self.path
		"""
		print '\nMethod: ' 
		print p.get_method() 
		print '\nPath: ' 
		print p.get_path()
		print '\nHeaders: ' 
		print p.get_headers()
		print '\nVersion: '
		version = p.get_version()
		print version
		"""
		#print '\nRESPONSE CODE: ' + str(self.status) + '\n'
		#print self.path
		#print self.status
		#working so far
示例#2
0
    def get_appropriate_response(self):

        try:
            # try to use the fast C parser
            from http_parser.parser import HttpParser
        except ImportError:
            # fall back to the Python parser
            from http_parser.pyparser import HttpParser

        p = HttpParser()
        nparsed = p.execute(self.content.encode('utf-8'), len(self.content))

        if not p.is_headers_complete():
            return HttpResponseBadRequest(content_f=BAD_REQUEST_HTML)

        # check method
        if p.get_method() not in SUPPORTED_METHODS:
            return HttpResponseNotImplemented(content_f=NOT_IMPLEMENTED_HTML)

        base_filepath = ''
        try:
            base_filepath = settings.HOSTS[p.get_headers()['Host'].split(':')
                                           [0]]
        except KeyError:
            base_filepath = settings.HOSTS['default']

        req_file = self.content.split(' ')[1]
        if req_file == '/':
            req_file = '/index.html'

        try:
            full_path = base_filepath + req_file
            open(full_path)

            # check if modified
            if 'If-None-Match' in p.get_headers() and p.get_headers(
            )['If-None-Match'] == etag_for_file(full_path):
                return HttpResponse(status=304, content_f=full_path)

            if p.get_method() == 'HEAD':
                return HttpResponse(content_f=full_path, method='HEAD')
            if 'Range' in p.get_headers():
                return HttpResponsePartialContent(
                    content_f=full_path, h_range=p.get_headers()['Range'])
            return HttpResponse(content_f=full_path)
        except IOError as err:
            if err.errno == 13:
                return HttpResponseForbidden(content_f=FORBIDDEN_HTML)
            elif err.errno == 2:
                return HttpResponseNotFound(content_f=NOT_FOUND_HTML)

        return HttpResponseServerError(content_f=SERVER_ERROR_HTML)
示例#3
0
def parse_request(http_request, protocol, host, port):
    """
    Parse HTTP request form Burp Suite to dict
    TODO cookie parse
    """
    httpParser = HttpParser()
    httpParser.execute(http_request, len(http_request))

    header = dict(httpParser.get_headers())
    header.pop("Content-Length")  # remove Content-Length
    # cookie = header["Cookie"]
    body = httpParser.recv_body()
    method = httpParser.get_method()
    url = protocol + "://" + host + httpParser.get_path()
    query = httpParser.get_query_string()

    params = dict(urlparse.parse_qsl(query))
    data = dict(urlparse.parse_qsl(body)) if method == "POST" else {}
    try:
        jsondata = json.loads(
            body) if method == "POST" and header["Content-Type"] == "application/json" else {}
    except Exception as e:
        print "[!] " + e
        jsondata = {}
    return method, url, header, params, data, jsondata
def main():

    p = HttpParser()
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    body = []
    header_done = False
    try:
        s.connect(('gunicorn.org', 80))
        s.send(b("GET / HTTP/1.1\r\nHost: gunicorn.org\r\n\r\n"))

        while True:
            data = s.recv(1024)
            if not data:
                break

            recved = len(data)
            nparsed = p.execute(data, recved)
            assert nparsed == recved

            if p.is_headers_complete() and not header_done:
                print(p.get_headers())
                print(p.get_headers()['content-length'])
                print(p.get_method())
                header_done = True

            if p.is_partial_body():
                body.append(p.recv_body())

            if p.is_message_complete():
                break

        print(b("").join(body))

    finally:
        s.close()
示例#5
0
class Request:
    parser = None
    _body = None

    def __init__(self, data):
        self.parser = HttpParser()
        self.parser.execute(data, len(data))

        self.method = self.parser.get_method()
        self.path = self.parser.get_path()
        self.headers = self.parser.get_headers()
        self.querystring = parse_qs(unquote(self.parser.get_query_string()),
                                    keep_blank_values=True)
        if self.querystring:
            self.path += "?{}".format(self.parser.get_query_string())

    def add_data(self, data):
        self.parser.execute(data, len(data))

    @property
    def body(self):
        if self._body is None:
            self._body = decode_from_bytes(self.parser.recv_body())
        return self._body

    def __str__(self):
        return "{} - {} - {}".format(self.method, self.path, self.headers)
示例#6
0
    async def handle_url(self, request: HttpParser) -> HttpResponse:
        method = request.get_method().upper()
        if method not in ('GET', 'HEAD'):
            return HttpResponse(405)
        path = request.get_path()
        if path.endswith('/'):
            path += 'index.html'
        relative = os.path.relpath(url2pathname(path), '/')
        filename = os.path.join(self.root_dir, relative)
        try:
            byte_range = None
            if 'Range' in request.get_headers():
                # Not RFC 7233 compliant
                range_match = re.match(r'bytes=(\d+)-(\d+)',
                                       request.get_headers()['Range'])
                if not range_match:
                    return HttpResponse(400, 'Invalid Range header')
                start, end = map(int, range_match.groups())
                # Python range is exclusive, HTTP Range is inclusive
                byte_range = range(start, end + 1)
            length = 0
            async with aiofiles.open(filename, 'rb') as f:
                if method == 'GET':
                    if byte_range is not None:
                        await f.seek(byte_range.start)
                        data = await f.read(len(byte_range))
                        byte_range = range(byte_range.start,
                                           byte_range.start + len(data))
                        await f.seek(0, os.SEEK_END)
                        length = await f.tell()
                        response = HttpResponse(206, data)
                    else:
                        data = await f.read()
                        response = HttpResponse(200, data)
                else:
                    # Used instead of os.stat to ensure the file can be accessed
                    response = HttpResponse(200)
                    await f.seek(0, os.SEEK_END)
                    length = await f.tell()
                    if byte_range is not None:
                        byte_range = range(byte_range.start,
                                           min(length, byte_range.stop))
                    response.headers['Content-Length'] = length
            if byte_range is not None:
                response.headers['Content-Range'] = 'bytes %d-%d/%d' % (
                    byte_range.start, byte_range.stop - 1, length)

        except FileNotFoundError:
            return HttpResponse(404,
                                'This is not the file you are looking for')
        except PermissionError:
            return HttpResponse(403)
        _, extension = os.path.splitext(filename)
        extension = extension[1:]
        if extension.lower() in self.mime_types:
            response.headers['Content-Type'] = self.mime_types[
                extension.lower()]
        response.headers['Last-Modified'] = formatdate(
            os.stat(filename).st_mtime, False, True)
        return response
示例#7
0
    def start(self):
        signal.signal(signal.SIGTERM, SIG_DFL)
        print(f"Worker booted with pid: {os.getpid()}")
        while True:
            body = []
            conn, addr = self.socket.accept()
            http_parser = HttpParser()
            with conn:
                while True:
                    data = conn.recv(1024)
                    if not data:
                        break
                    recved = len(data)
                    nparsed = http_parser.execute(data, recved)
                    assert nparsed == recved

                    if http_parser.is_headers_complete():
                        print(http_parser.get_headers())

                    if http_parser.is_partial_body():
                        body.append(http_parser.recv_body())

                    if http_parser.is_message_complete():
                        break

                buffered_body = io.StringIO("".join(body))
                koi(self.app,
                    conn,
                    request_method=http_parser.get_method(),
                    headers=http_parser.get_headers(),
                    body=buffered_body,
                    content_length=http_parser.get_headers().get(
                        'content-length', 0))
示例#8
0
    def handler(self):
        httpParser1 = HttpParser()
        httpParser2 = HttpParser()
        serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        serverSocket.bind(('', 5000))
        serverSocket.listen(1)
        conn, addr = serverSocket.accept()
        cumulatedPacketLength = 0
        while 1:
            data = conn.recv(1024)
            receivedPacketLength = len(data)
            httpParser1.execute(data, receivedPacketLength)
            print httpParser1.get_method()
            cumulatedPacketLength += receivedPacketLength
            if cumulatedPacketLength > 235:
                self.isReceivedRequestMatchExpectation = True
                response_body_raw = '{"success":true,"data":"FILE_FOUND_AND_LOADED"}'
                conn.send('%s %s %s\r\n%s: %s\r\n%s: %s\r\n\r\n%s' % (  'HTTP/1.1', '200', 'OK',\
                                                                        'Content-Type','application/json; charset=utf-8',\
                                                                        'Content-Length',len(response_body_raw),\
                                                                        response_body_raw))
                conn.close()
            break

        serverSocket.listen(1)
        conn, addr = serverSocket.accept()
        cumulatedPacketLength = 0
        while 1:
            data = conn.recv(1024)
            receivedPacketLength = len(data)
            httpParser2.execute(data, receivedPacketLength)
            print httpParser2.get_method()
            cumulatedPacketLength += receivedPacketLength
            if cumulatedPacketLength > 235:
                self.isReceivedRequestMatchExpectation = True
                response_body_raw = '{"success":true,"data":"FILE_FOUND_AND_LOADED"}'
                conn.send('%s %s %s\r\n%s: %s\r\n%s: %s\r\n\r\n%s' % (  'HTTP/1.1', '200', 'OK',\
                                                                        'Content-Type','application/json; charset=utf-8',\
                                                                        'Content-Length',len(response_body_raw),\
                                                                        response_body_raw))
                conn.close()
                serverSocket.close()
            break
示例#9
0
	def get_appropriate_response(self):

		try:
			# try to use the fast C parser
			from http_parser.parser import HttpParser
		except ImportError:
			# fall back to the Python parser
			from http_parser.pyparser import HttpParser

		p = HttpParser()
		nparsed = p.execute(self.content.encode('utf-8'), len(self.content))

		if not p.is_headers_complete():
			return HttpResponseBadRequest(content_f=BAD_REQUEST_HTML)

		# check method
		if p.get_method() not in SUPPORTED_METHODS:
			return HttpResponseNotImplemented(content_f=NOT_IMPLEMENTED_HTML)

		base_filepath = ''
		try:
			base_filepath = settings.HOSTS[p.get_headers()['Host'].split(':')[0]]
		except KeyError:
			base_filepath = settings.HOSTS['default']

		req_file = self.content.split(' ')[1]
		if req_file == '/':
			req_file = '/index.html'

		try:
			full_path = base_filepath + req_file
			open(full_path)
			if p.get_method() == 'HEAD':
				return HttpResponse(content_f=full_path, method='HEAD')
			if 'Range' in p.get_headers():
				return HttpResponsePartialContent(content_f=full_path, h_range=p.get_headers()['Range'])	
			return HttpResponse(content_f=full_path)
		except IOError as err:
			if err.errno == 13:
				return HttpResponseForbidden(content_f=FORBIDDEN_HTML)
			elif err.errno == 2:
				return HttpResponseNotFound(content_f=NOT_FOUND_HTML)

		return HttpResponseServerError(content_f=SERVER_ERROR_HTML)
示例#10
0
    def parseData(self, data, fd):
        p = HttpParser()
        nparsed = p.execute(data,len(data))
        resp = Response()
        if self.debugging:
            print p.get_method(),p.get_path(),p.get_headers()

        if (p.get_method() == 'GET'):
            resp = self.handleGet(p, resp)
        elif (p.get_method() == 'DELETE'):
            resp.setCode(501)
        else:
            resp.setCode(400)

        self.clients[fd].send(str(resp))
        try:
            self.clients[fd].send(resp.body)
        except:
            pass
示例#11
0
 def __init__(self, raw):
     self.raw = raw
     req = HttpParser()
     req.execute(raw.request, len(raw.request))
     self.headers = req.get_headers()
     self.body = b"".join(req._body)
     self.url = req.get_url()
     self.path = req.get_path()
     self.method = req.get_method()
     self.arguments = req.get_query_string()
     self.slug = [a for a in self.path.split('/') if a != '']
示例#12
0
def proxy(data):
    """
    the function called by tproxy to determine where to send traffic

    tproxy will call this function repeatedly for the same connection, as we
    receive more incoming data, until we return something other than None.

    typically our response tells tproxy where to proxy the connection to, but
    may also tell it to hang up, or respond with some error message.
    """

    log = logging.getLogger("proxy")

    bytes_received = len(data)

    parser = HttpParser()
    bytes_parsed = parser.execute(data, bytes_received)

    if bytes_parsed != bytes_received:
        return {'close': 'HTTP/1.0 400 Bad Request\r\n\r\nParse error'}

    if not parser.is_headers_complete():
        if bytes_received > MAX_HEADER_LENGTH:
            return {
                'close': 'HTTP/1.0 400 Bad Request\r\n'
                '\r\nHeaders are too large'
            }
        return None

    headers = parser.get_headers()

    # the hostname may be in the form of hostname:port, in which case we want
    # to discard the port, and route just on hostname
    route_host = headers.get('HOST', None)
    if route_host:
        match = _HOST_PORT_REGEXP.match(route_host)
        if match:
            route_host = match.group(1)

    try:
        log.debug("Routing %r" % (parser.get_url(), ))
        return _ROUTER.route(route_host, parser.get_method(),
                             parser.get_path(), parser.get_query_string())
    except Exception, err:
        log.error("error routing %r, %s" % (
            parser.get_url(),
            traceback.format_exc(),
        ))
        gevent.sleep(ERROR_DELAY)
        return {
            'close': 'HTTP/1.0 502 Gateway Error\r\n'
            '\r\nError routing request'
        }
示例#13
0
def proxy(data):
    """
    the function called by tproxy to determine where to send traffic

    tproxy will call this function repeatedly for the same connection, as we
    receive more incoming data, until we return something other than None.

    typically our response tells tproxy where to proxy the connection to, but
    may also tell it to hang up, or respond with some error message.
    """

    log = logging.getLogger("proxy")

    bytes_received = len(data)

    parser =  HttpParser()
    bytes_parsed = parser.execute(data, bytes_received)

    if bytes_parsed != bytes_received:
        return { 'close': 
            'HTTP/1.0 400 Bad Request\r\n\r\nParse error' }

    if not parser.is_headers_complete(): 
        if bytes_received > MAX_HEADER_LENGTH:
            return { 'close': 
                'HTTP/1.0 400 Bad Request\r\n'
                '\r\nHeaders are too large' }
        return None

    headers = parser.get_headers()

    # the hostname may be in the form of hostname:port, in which case we want
    # to discard the port, and route just on hostname
    route_host = headers.get('HOST', None)
    if route_host:
        match = _HOST_PORT_REGEXP.match(route_host)
        if match:
            route_host = match.group(1)

    try:
        log.debug("Routing %r" % ( parser.get_url(), ))
        return _ROUTER.route(
            route_host,
            parser.get_method(),
            parser.get_path(),
            parser.get_query_string())
    except Exception, err:
        log.error("error routing %r, %s" % (
            parser.get_url(), traceback.format_exc(), ))
        gevent.sleep(ERROR_DELAY)
        return { 'close': 
            'HTTP/1.0 502 Gateway Error\r\n'
            '\r\nError routing request' }
示例#14
0
def get_headers_data(data):
    """ """
    parser = HttpParser()
    parser.execute(data, len(data))
    url = parser.get_url()
    method = parser.get_method()
    if method == 'CONNECT':
        host, _, port = url.partition(":")
    else:
        url = urlparse(url)
        host, _, port = url.netloc.partition(":")
    port = port and port.isdigit() and int(port) or 80
    return (host, port), method, parser.get_version()
示例#15
0
    async def run(self):
        p = HttpParser(kind=0)
        while not p.is_message_complete():
            data = await self._loop.sock_recv(self._sock, 1024)
            if not data:
                break
            nparsed = p.execute(data, len(data))
            if nparsed != len(data):
                break

        if not (p.is_message_complete() and p.get_method() in ("GET", "HEAD")):
            response = (b"HTTP/1.1 400 Bad Request\r\n"
                        b"Content-Type: text/plain\r\n"
                        b"\r\n"
                        b"Bad Request\n")
            await self._loop.sock_sendall(self._sock, response)
            await self.close()
            return

        channel = p.get_path().strip("/")
        monitor = self._server.get_monitor(channel)
        if monitor is None:
            response = (b"HTTP/1.1 404 Not Found\r\n"
                        b"Content-Type: text/plain\r\n"
                        b"\r\n")
            await self._loop.sock_sendall(self._sock, response)
            await self.close()
            return

        response = b"HTTP/1.1 200 OK\r\n"
        if monitor.has_video:
            response += b"Content-Type: video/x-matroska\r\n\r\n"
        else:
            response += b"Content-Type: audio/x-matroska\r\n\r\n"
        await self._loop.sock_sendall(self._sock, response)
        if p.get_method() == "HEAD":
            await self.close()
            return
        monitor.add_fd(self._sock.fileno())
示例#16
0
    def _handle(self,
                source,
                dest,
                to_backend,
                on_between_handle,
                data_sent=False):
        buffer_size = self.option('buffer')

        # Getting the HTTP query and sending it to the backend.
        parser = HttpParser()
        if not data_sent:
            while not parser.is_message_complete():
                data = self._get_data(source, buffer_size)
                if not data:
                    return self._close_both(source, dest)
                nparsed = parser.execute(data, len(data))
                assert nparsed == len(data)
                if self.option('overwrite_host_header'):
                    data = HOST_REPLACE.sub(
                        '\r\nHost: %s\r\n' % self.proxy.backend, data)
                dest.sendall(data)
        keep_alive_src = parser.should_keep_alive()
        method = parser.get_method()

        if on_between_handle():
            # Getting the HTTP response and sending it back to the source.
            parser = HttpParser()
            while not (parser.is_message_complete() or
                       (method == 'HEAD' and parser.is_headers_complete())):
                data = self._get_data(dest, buffer_size)
                if not data:
                    return self._close_both(source, dest)
                nparsed = parser.execute(data, len(data))
                assert nparsed == len(data)
                source.sendall(data)
            keep_alive_dst = parser.should_keep_alive()

            # do we close the client ?
            if not keep_alive_src or not self.option('keep_alive'):
                source.close()
                source._closed = True

            if (not keep_alive_dst or not self.option('reuse_socket')
                    or not self.option('keep_alive')):
                dest.close()
                dest._closed = True
        else:
            keep_alive_dst = False

        return keep_alive_dst and self.option('keep_alive')
示例#17
0
    def _handle(self, source, dest, to_backend, on_between_handle,
                data_sent=False):
        buffer_size = self.option('buffer')

        # Getting the HTTP query and sending it to the backend.
        parser = HttpParser()
        if not data_sent:
            while not parser.is_message_complete():
                data = self._get_data(source, buffer_size)
                if not data:
                    return self._close_both(source, dest)
                nparsed = parser.execute(data, len(data))
                assert nparsed == len(data)
                if self.option('overwrite_host_header'):
                    data = HOST_REPLACE.sub('\r\nHost: %s\r\n'
                                            % self.proxy.backend, data)
                dest.sendall(data)
        keep_alive_src = parser.should_keep_alive()
        method = parser.get_method()

        if on_between_handle():
            # Getting the HTTP response and sending it back to the source.
            parser = HttpParser()
            while not (parser.is_message_complete() or
                       (method == 'HEAD' and parser.is_headers_complete())):
                data = self._get_data(dest, buffer_size)
                if not data:
                    return self._close_both(source, dest)
                nparsed = parser.execute(data, len(data))
                assert nparsed == len(data)
                source.sendall(data)
            keep_alive_dst = parser.should_keep_alive()

            # do we close the client ?
            if not keep_alive_src or not self.option('keep_alive'):
                source.close()
                source._closed = True

            if (not keep_alive_dst or not self.option('reuse_socket') or not
                self.option('keep_alive')):
                dest.close()
                dest._closed = True
        else:
            keep_alive_dst = False

        return keep_alive_dst and self.option('keep_alive')
示例#18
0
    def handleData(self,fd):
        self.debug("Entering handleData")
        if '\r\n\r\n' not in self.con_cache[fd]:
            self.debug("Partial message - Exiting handleData")
            return 
        p = HttpParser() 
        nparsed = p.execute(self.con_cache[fd],len(self.con_cache[fd]))                 
        
        method = p.get_method()
        path = p.get_path()
        headers = p.get_headers() 
        debugStr = "\nMethod: %s\nPath: %s\nHeaders: %s\n" % (method,path,headers)  
        #self.debug(debugStr)
       
        rangeRequest = None 
        if 'Range' in headers:
            rangeRequest = headers['Range']
            self.debug("Range: %s" % (rangeRequest))
           

        validMethods = ['GET','HEAD','PUT','DELETE','POST']
        isValid = False 
        
        if method not in validMethods:
            response = self.makeError('400','Bad Request')
        elif method != 'GET' and method != 'HEAD':
            response = self.makeError('501','Not Implemented')
        else:
            if path == '/':
                path = '/index.html'
                
            path = self.hosts['default'] + path 
            (isValid,response) = self.makeResponse(path,rangeRequest) 

        self.clients[fd].send(response)
         
        self.debug("PATH:%s"%(path))
       
        if isValid and not rangeRequest and method != "HEAD":
            self.sendAll(path,fd) 
        elif isValid and rangeRequest and method != "HEAD":
            (start,end) = self.getByteRange(rangeRequest) 
            self.send(path,fd,start,end) 

        self.debug("Exiting handleData") 
示例#19
0
    def test_constructor(self):
        ''' Instance attributes autosubstitution.
        '''
        headers = {
            'Host': 'httpbin.org',
            'Connection': 'close',
        }
        hc = HttpCompiler(method='PATCH', headers=headers)
        qs = '/path/to/check'
        req = hc.build_raw(qs)

        p = HttpParser()
        p.execute(req, len(req))
        result_hdrs = p.get_headers()

        self.assertTrue(p.get_method(), 'PATCH')
        self.assertTrue(
            all([result_hdrs[h] == headers[h] for h in headers.keys()]))
示例#20
0
    def test_constructor(self):
        ''' Instance attributes autosubstitution.
        '''
        headers = {
            'Host': 'httpbin.org',
            'Connection': 'close',
        }
        hc = HttpCompiler(method='PATCH', headers=headers)
        qs = '/path/to/check'
        req = hc.build_raw(qs)

        p = HttpParser()
        p.execute(req, len(req))
        result_hdrs = p.get_headers()

        self.assertTrue(p.get_method(), 'PATCH')
        self.assertTrue(all(
            [result_hdrs[h] == headers[h] for h in headers.keys()]))
示例#21
0
class HttpRequest(object):
    __cgi_config = None

    def __init__(self, request_text, server_config):
        self.__parser = HttpParser()
        self.__parser.execute(request_text, len(request_text))
        self.__server_config = server_config

    def get_body(self):
        if self.__parser.is_partial_body():
            return self.__parser.recv_body()
        return None

    def get_headers(self):
        return self.__parser.get_headers()

    def get_request_method(self):
        return self.__parser.get_method()

    def get_request_path(self):
        return self.__parser.get_path()

    def get_cgi_config(self):
        if self.__cgi_config is None:
            __cgi_config = {}
            #WSGI required variable
            #__cgi_config['wsgi.input'] = io.StringIO(self.get_body())

            #CGI
            __cgi_config['SERVER_NAME'] = self.__server_config['server_name']
            __cgi_config['SERVER_PORT'] = self.__server_config['server_port']
            __cgi_config['SERVER_PROTOCOL']: 'HTTP/1.1'
            __cgi_config['REQUEST_METHOD'] = self.get_request_method()
            __cgi_config['PATH_INFO'] = self.get_request_path()

            for header, value in self.get_headers().items():
                __cgi_config[f'HTTP_{header}'] = value

            self.__cgi_config = __cgi_config
        return self.__cgi_config
示例#22
0
class QHttpConnection(QObject):
    newRequest = pyqtSignal(QHttpRequest, QHttpResponse)
    disconnected = pyqtSignal()
    
    def __init__(self, sock, parent = None):
        super(QHttpConnection, self).__init__(parent)

        self.m_sock = sock
        self.m_body = []
        self.m_parser = HttpParser()

        self.m_request = QHttpRequest(self)
        self.m_request = None
        self.m_response = QHttpResponse(self)
        self.m_response = None
        
        self.m_sock.readyRead.connect(self._onReadyRead)
        self.m_sock.disconnected.connect(self._onDisconnected)
        self.m_sock.bytesWritten.connect(self._onBytesWritten)
        
        return
    
    def write(self, data):
        self.m_sock.write(data)
        return

    def _onReadyRead(self):
        #qDebug('hehe')
        qtdata = self.m_sock.readAll()
        pydata = qtdata.data()
        np = self.m_parser.execute(pydata, len(pydata))
        qDebug(str(np) + '=?' + str(len(pydata)))
        #qDebug(qtdata)
        #qDebug(qtdata.toHex())
        #print(self.m_parser._body)
        #print(self.m_parser._body)

        #qDebug(str(self.m_parser.is_message_begin()))
        #qDebug(str(self.m_parser.is_message_complete()))
        #qDebug(str(self.m_parser.is_headers_complete()))

        if self.m_parser.is_headers_complete():
            if self.m_request != None:
                qWarning('alread have a request object')
            else:
                self.m_request = QHttpRequest(self)
                _qogc.add(self.m_request)
                # qDebug(str(self.m_request))
                # print(self.m_parser.get_headers())
            True

        ### body area
        # qDebug(str(self.m_parser.is_message_begin()))
        # not use lines,这个可能指的是在客户端时,数据下载完成标识吧。
        if self.m_parser.is_message_begin() and self.m_request != None:
            qDebug('body coming...')
            self.m_request.hasBody()
            
        mth = self.m_parser.get_method()
        # qDebug(mth)
            
        if mth == 'GET':
            if self.m_parser.is_headers_complete():
                self.m_response = QHttpResponse(self)
                self.m_response.done.connect(self._onResponseDone)
                _qogc.add(self.m_response)

                self.newRequest.emit(self.m_request, self.m_response)
            pass
        elif mth == 'POST':
            if self.m_parser.is_partial_body(): self.m_body.append(self.m_parser.recv_body())
            if self.m_parser.is_message_complete(): print(b''.join(self.m_body))
        elif mth == 'CONNECT':
            if self.m_parser.is_headers_complete():
                if self.m_response != None:
                    qWarning('alread have a response object')
                else:
                    self.m_response = QHttpResponse(self)
                    self.m_response.done.connect(self._onResponseDone)
                    _qogc.add(self.m_response)

                    self.newRequest.emit(self.m_request, self.m_response)
            else:
                qDebug('hdr not complete')
            True
        else:
            qWarning("not impled method:" + mth)
            self.m_sock.close()
        
        return

    def _onDisconnected(self):
        # qDebug('hehe')
        self.disconnected.emit()
        return

    def _onBytesWritten(self, count):
        # qDebug('hehe')
        return

    def _onResponseDone(self):
        self.m_sock.disconnectFromHost()
        self.m_sock.close()
        # qDebug(str(self.m_request))
        return

    def close(self):
        self.m_sock.flush()
        self.m_sock.close()
        return

    def last(self): return
示例#23
0
	def parseRequest(self, data):
		if (self.debug):
			print "entering parse Request--------\n"

		# Create a parser object

		try:
    			from http_parser.parser import HttpParser
		except ImportError:
    			from http_parser.pyparser import HttpParser

		parser = HttpParser()
		nparser = parser.execute(data, len(data))

		response = None
		path = None
		host = None
		isRangeReq = None
		isHeadReq = False

		# Get Protocol Version
		version = "HTTP/1.1"

		#check if request is valid
		method = parser.get_method()
		if method not in self.validMethods:
			if (self.debug):
				print "received a non valid method: %s\n" %method
			response = self.createError("400", "Bad Request")

		elif method != "GET" and method != "HEAD":
			if (self.debug):
				print "received a method which we do not implement\n"
			response = self.createError("501", "Not Implemented")
		
		else:
			if method == "HEAD":
				isHeadReq = True
			url = parser.get_path()

			# Check for url errors
			if (url == ""):
				if self.debug:
					print "url is empty\n"
				resposne = self.createError("400", "Bad Request")

			elif (url == "/"):
				url = "/index.html"

			headers = parser.get_headers()

			if "Range" in headers:
				isRangeReq = headers["Range"]
				if self.debug:
					print "Range Request = %s" %isRangeReq

			#get Host
			if "Host" in headers:
				host = headers["Host"].split(':')[0]
				if (self.debug):
					print "host is: %s\n"%host

			# Handle errors in host
			if host not in self.hosts:
				if 'default' not in self.hosts:
					if self.debug:
						print " not host or default\n"
					response = self.createError("400", "Bad Request")

				else:
					# Use the default host
					if self.debug:
						print "using default host\n"

					path = self.hosts['default']

					if (self.debug):
						print "path is: %s\n"%path

					path += url

					if (self.debug):
						print "full path is: %s\n"%path

					response = self.createResponse(path, isRangeReq)

			else: #use given host
				path = self.hosts[host]
				if (self.debug):
					print "path is: %s\n"%path

				path += url

				if (self.debug):
					print "full path is: %s\n"%path

				response = self.createResponse(path, isRangeReq)
		
		if isHeadReq:
			path = None

		if self.debug:
			print "end of parse request\n"

		return response, path, isRangeReq
示例#24
0
class QHttpConnection(QObject):
    newRequest = pyqtSignal(QHttpRequest, QHttpResponse)
    disconnected = pyqtSignal()

    def __init__(self, sock, parent=None):
        super(QHttpConnection, self).__init__(parent)

        self.m_sock = sock
        self.m_body = []
        self.m_parser = HttpParser()

        self.m_request = QHttpRequest(self)
        self.m_request = None
        self.m_response = QHttpResponse(self)
        self.m_response = None

        self.m_sock.readyRead.connect(self._onReadyRead)
        self.m_sock.disconnected.connect(self._onDisconnected)
        self.m_sock.bytesWritten.connect(self._onBytesWritten)

        return

    def write(self, data):
        self.m_sock.write(data)
        return

    def _onReadyRead(self):
        #qDebug('hehe')
        qtdata = self.m_sock.readAll()
        pydata = qtdata.data()
        np = self.m_parser.execute(pydata, len(pydata))
        qDebug(str(np) + '=?' + str(len(pydata)))
        #qDebug(qtdata)
        #qDebug(qtdata.toHex())
        #print(self.m_parser._body)
        #print(self.m_parser._body)

        #qDebug(str(self.m_parser.is_message_begin()))
        #qDebug(str(self.m_parser.is_message_complete()))
        #qDebug(str(self.m_parser.is_headers_complete()))

        if self.m_parser.is_headers_complete():
            if self.m_request != None:
                qWarning('alread have a request object')
            else:
                self.m_request = QHttpRequest(self)
                _qogc.add(self.m_request)
                # qDebug(str(self.m_request))
                # print(self.m_parser.get_headers())
            True

        ### body area
        # qDebug(str(self.m_parser.is_message_begin()))
        # not use lines,这个可能指的是在客户端时,数据下载完成标识吧。
        if self.m_parser.is_message_begin() and self.m_request != None:
            qDebug('body coming...')
            self.m_request.hasBody()

        mth = self.m_parser.get_method()
        # qDebug(mth)

        if mth == 'GET':
            if self.m_parser.is_headers_complete():
                self.m_response = QHttpResponse(self)
                self.m_response.done.connect(self._onResponseDone)
                _qogc.add(self.m_response)

                self.newRequest.emit(self.m_request, self.m_response)
            pass
        elif mth == 'POST':
            if self.m_parser.is_partial_body():
                self.m_body.append(self.m_parser.recv_body())
            if self.m_parser.is_message_complete():
                print(b''.join(self.m_body))
        elif mth == 'CONNECT':
            if self.m_parser.is_headers_complete():
                if self.m_response != None:
                    qWarning('alread have a response object')
                else:
                    self.m_response = QHttpResponse(self)
                    self.m_response.done.connect(self._onResponseDone)
                    _qogc.add(self.m_response)

                    self.newRequest.emit(self.m_request, self.m_response)
            else:
                qDebug('hdr not complete')
            True
        else:
            qWarning("not impled method:" + mth)
            self.m_sock.close()

        return

    def _onDisconnected(self):
        # qDebug('hehe')
        self.disconnected.emit()
        return

    def _onBytesWritten(self, count):
        # qDebug('hehe')
        return

    def _onResponseDone(self):
        self.m_sock.disconnectFromHost()
        self.m_sock.close()
        # qDebug(str(self.m_request))
        return

    def close(self):
        self.m_sock.flush()
        self.m_sock.close()
        return

    def last(self):
        return
示例#25
0
 def handle_url(self, request: HttpParser) -> HttpResponse:
     return HttpResponse(
         501, '%s %s' % (request.get_method(), request.get_path()))
示例#26
0
 def handle_read(self):
     try:
         logging.debug('Connection.handle_read - id=%d' % self.id)
         b = self.sock.recv(2048)
         logging.debug(
             'Connection.handle_read - received buffer size is %d bytes' %
             len(b))
         logging.debug(
             'Connection.handle_read - received buffer is : \n%s' % b)
         if not len(b):
             logging.debug(
                 'Connection.handle_read - 0 bytes received on %d. closing'
                 % self.id)
             self.close()
             return
         self.read_buf += b
     except socket.error as err:
         if err.args[0] not in NONBLOCKING:
             self.handle_error('%s' % args[1])
         else:
             logging.error(
                 'Connection.handle_read - NONBLOCKING event on read : %s' %
                 args[1])
     else:
         # check if we have a full http request
         parser = HttpParser()
         recved = len(self.read_buf)
         nparsed = parser.execute(self.read_buf, recved)
         assert nparsed == recved
         if not parser.is_message_complete():
             # we got a partial request keep on reading
             logging.debug(
                 'Connection.handle_read - partial buffer received : \n%s' %
                 self.read_buf)
             self.reset(pyev.EV_READ)
         else:
             # we got a full request
             self.read_buf = ''
             # match the verb with URI and call
             # after that register for write to send response
             verb = parser.get_method()
             url = parser.get_path()
             logging.debug(
                 'Connection.handle_read - id  %d - method is %s and url %s'
                 % (self.id, verb, url))
             call, keyword_args = register.get_callable(url, verb)
             if not call:
                 err = HttpResponse()
                 err.status_code = 404
                 err.status_string = 'Not Found'
                 err.headers['Content-Type'] = 'application/txt'
                 err.body = 'URI Not Found\r\n'
                 self.write_buf = err.to_string()
             else:
                 keyword_args['http_request'] = parser
                 logging.debug('Connection.handle_read - kargs=%s' %
                               keyword_args)
                 try:
                     response = call(*[
                         register.handler,
                     ], **keyword_args)
                     self.write_buf = response.to_string()
                 except:
                     err = HttpResponse()
                     err.status_code = 500
                     err.status_string = 'Internal Server Error'
                     err.headers['Content-Type'] = 'application/txt'
                     err.body = 'Upsssss.\r\n'
                     self.write_buf = err.to_string()
             logging.debug('Connection.handle_read - requesting write %d' %
                           self.id)
             self.reset(pyev.EV_WRITE)
示例#27
0
文件: protocol.py 项目: dstufft/stein
class HTTPProtocol(FlowControlMixin, asyncio.Protocol):

    def __init__(self, stream_reader, callback, loop=None):
        super().__init__(loop=loop)
        self._stream_reader = stream_reader
        self._stream_writer = None

        self._callback = callback
        self._task = None

        self._server = None

    def connection_made(self, transport):
        self._parser = HttpParser()

        self._stream_reader.set_transport(transport)
        self._stream_writer = asyncio.StreamWriter(
            transport,
            self,
            self._stream_reader,
            self._loop,
        )

        # Grab the name of our socket if we have it
        self._server = transport.get_extra_info("sockname")

    def connection_lost(self, exc):
        if exc is None:
            self._stream_reader.feed_eof()
        else:
            self._stream_reader.set_exception(exc)

        super().connection_lost(exc)

    def data_received(self, data):
        # Parse our incoming data with our HTTP parser
        self._parser.execute(data, len(data))

        # If we have not already handled the headers and we've gotten all of
        # them, then invoke the callback with the headers in them.
        if self._task is None and self._parser.is_headers_complete():
            coro = self.dispatch(
                {
                    "server": self._server,
                    "protocol": b"HTTP/" + b".".join(
                        str(x).encode("ascii")
                        for x in self._parser.get_version()
                    ),
                    "method": self._parser.get_method().encode("latin1"),
                    "path": self._parser.get_path().encode("latin1"),
                    "query": self._parser.get_query_string().encode("latin1"),
                    "headers": self._parser.get_headers(),
                },
                self._stream_reader,
                self._stream_writer,
            )
            self._task = asyncio.Task(coro, loop=self._loop)

        # Determine if we have any data in the body buffer and if so feed it
        # to our StreamReader
        if self._parser.is_partial_body():
            self._stream_reader.feed_data(self._parser.recv_body())

        # Determine if we've completed the end of the HTTP request, if we have
        # then we should close our stream reader because there is nothing more
        # to read.
        if self._parser.is_message_complete():
            self._stream_reader.feed_eof()

    def eof_received(self):
        # We've gotten an EOF from the client, so we'll propagate this to our
        # StreamReader
        self._stream_reader.feed_eof()

    @asyncio.coroutine
    def dispatch(self, request, request_body, response):
        # Get the status, headers, and body from the callback. The body must
        # be iterable, and each item can either be a bytes object, or an
        # asyncio coroutine, in which case we'll ``yield from`` on it to wait
        # for it's value.
        status, resp_headers, body = yield from self._callback(
            request,
            request_body,
        )

        # Write out the status line to the client for this request
        # TODO: We probably don't want to hard code HTTP/1.1 here
        response.write(b"HTTP/1.1 " + status + b"\r\n")

        # Write out the headers, taking special care to ensure that any
        # mandatory headers are added.
        # TODO: We need to handle some required headers
        for key, values in resp_headers.items():
            # In order to handle headers which need to have multiple values
            # like Set-Cookie, we allow the value of the header to be an
            # iterable instead of a bytes object, in which case we'll write
            # multiple header lines for this header.
            if isinstance(values, (bytes, bytearray)):
                values = [values]

            for value in values:
                response.write(key + b": " + value + b"\r\n")

        # Before we get to the body, we need to write a blank line to separate
        # the headers and the response body
        response.write(b"\r\n")

        for chunk in body:
            # If the chunk is a coroutine, then we want to wait for the result
            # before we write it.
            if asyncio.iscoroutine(chunk):
                chunk = yield from chunk

            # Write our chunk out to the connect client
            response.write(chunk)

        # We've written everything in our iterator, so we want to close the
        # connection.
        response.close()
    def recvrawsocket2(sockobj, address):
        try:
            #        if 1:
            # logger.error(sockobj)
            #            logger.debug(dir(sockobj))
            request_path = ""
            body = []
            p = HttpParser()
            seqid = uuid.uuid1()
            requestdict = dict()
            requestdict['sock'] = sockobj
            #                requestdatetime = time.strftime('%Y.%m.%d.%H.%M.%S', time.localtime(time.time()))
            requestdatetime = time.time()
            requestdict['requestdatetime'] = requestdatetime
            responsesocketdict[seqid.__str__()] = requestdict
            # logger.debug("responsesocketdict len = %d", len(responsesocketdict))

            while True:
                request = sockobj.recv(recv_buf_len)
                #                logger.warning("request  : %s" % (request))

                recved = len(request)
                #                logger.warning("recved   : %d" % (recved))

                if (recved == 0):
                    logger.warning("socket is closed by peer %r" % (sockobj))
                    sockobj.close()
                    break

                nparsed = p.execute(request, recved)
                #                logger.warning("nparsed  : %d" % (nparsed))
                if nparsed != recved:
                    logger.warning("parse error")
                    sockobj.close()
                    break

                if p.is_headers_complete():
                    request_headers = p.get_headers()
    #                        for key in request_headers:
    #                        logger.debug("headers complete %s" % (request_headers.__str__()))

    #                        logger.warning("headers complete")

                if p.is_partial_body():
                    body.append(p.recv_body())
    #                        logger.warning("body  : %s" % (body))

                if p.is_message_complete():
                    #                        logger.warning("message complete")
                    break

#            logger.debug(p.get_method())
#            logger.debug(p.get_path())
#            logger.debug(p.get_query_string())

            routekey = ""
            servicepath = ""

            # 如果是/xxx格式认为是route key,如果是/xxx/yyy/zzz格式认为是dest service
            request_path = p.get_path()[1:]
            request_pathlist = request_path.split('/')
            servicename = request_pathlist[0]
            action_name = ''
            servicelist = os.listdir('./apps')
            content = dict()
            if p.get_method() == 'GET':
                if servicename == 'showip':
                    sockobj.sendall("HTTP/1.1 200 OK \n\n%s" % (sockobj))
                    sockobj.shutdown(socket.SHUT_WR)
                    sockobj.close()
                    return

                if len(request_pathlist) != 2:
                    ret = dict()
                    ret['errcode'] = '40004'
                    ret['errmsg'] = _errmsg['40004']
                    sockobj.sendall('HTTP/1.1 500 OK\n\n%s' %
                                    (json.dumps(ret)))
                    sockobj.shutdown(socket.SHUT_WR)
                    sockobj.close()
                    return

                action_name = request_pathlist[1]

                querystring = p.get_query_string()
                querylist = querystring.split('&')
                action_body = dict()
                for query in querylist:
                    kvlist = query.split('=')
                    action_body[kvlist[0]] = ''.join(kvlist[1:])
                content['action_cmd'] = action_name
                content['seq_id'] = str(random.randint(10000, 1000000))
                content['body'] = action_body
                content['version'] = '1.0'

            else:
                if len(body) > 0:
                    content = json.loads("".join(body))
#                content = "".join(body)

# logger.debug("servicename=%s,action_name=%s"%(servicename,action_name))
# logger.debug("content=%r"%(content))
            if servicename == 'testurl':
                sockobj.sendall('HTTP/1.1 200 OK\n\n%s' %
                                (content['body']['signature']))
                sockobj.shutdown(socket.SHUT_WR)
                sockobj.close()
                return

            if servicename in servicelist:
                routekey = "A:Queue:%s" % servicename
                if servicename in _config:
                    routekey = _config[servicename]['Consumer_Queue_Name']
                content['sockid'] = seqid.__str__()
                content['from'] = selfqueuename
                _redis.lpush(routekey, json.dumps(content))
            else:
                ret = dict()
                ret['errcode'] = '40004'
                ret['errmsg'] = _errmsg['40004']
                sockobj.sendall('HTTP/1.1 404 OK\n\n%s' % (json.dumps(ret)))
                sockobj.shutdown(socket.SHUT_WR)
                sockobj.close()

    #                requestdict = dict()
    #                requestdict['sock'] = sockobj
    #                requestdatetime = time.strftime(
    #                    '%Y.%m.%d.%H.%M.%S', time.localtime(time.time()))
    #                requestdict['requestdatetime'] = requestdatetime
    #                responsesocketdict[seqid.__str__()] = requestdict

    # sockobj.sendall('HTTP/1.1 200 OK\n\nWelcome %s' % (
    #    seqid))
    # sockobj.close()

        except Exception as e:
            logger.error("recvrawsocket2 %s except raised : %s " %
                         (e.__class__, e.args))
示例#29
0
文件: http.py 项目: bjornua/dna
class HttpStream(object):
    """ An HTTP parser providing higher-level access to a readable,
    sequential io.RawIOBase object. You can use implementions of
    http_parser.reader (IterReader, StringReader, SocketReader) or 
    create your own.
    """
    def __init__(self, stream, kind=HTTP_BOTH, decompress=False):
        """ constructor of HttpStream. 

        :attr stream: an io.RawIOBase object
        :attr kind: Int,  could be 0 to parseonly requests, 
        1 to parse only responses or 2 if we want to let
        the parser detect the type.
        """
        self.parser = HttpParser(kind=kind, decompress=decompress)
        self.stream = stream

    def _check_headers_complete(self):
        if self.parser.is_headers_complete():
            return

        while True:
            try:
                data = self.next()
            except StopIteration:
                if self.parser.is_headers_complete():
                    return
                raise NoMoreData()

            if self.parser.is_headers_complete():
                return

    def url(self):
        """ get full url of the request """
        self._check_headers_complete()
        return self.parser.get_url()

    def path(self):
        """ get path of the request (url without query string and
        fragment """
        self._check_headers_complete()
        return self.parser.get_path()

    def query_string(self):
        """ get query string of the url """
        self._check_headers_complete()
        return self.parser.get_query_string()

    def fragment(self):
        """ get fragment of the url """
        self._check_headers_complete()
        return self.parser.get_fragment()

    def version(self):
        self._check_headers_complete()
        return self.parser.get_version()

    def status_code(self):
        """ get status code of a response as integer """
        self._check_headers_complete()
        return self.parser.get_status_code()

    def status(self):
        """ return complete status with reason """
        status_code = self.status_code()
        reason = status_reasons.get(int(status_code), 'unknown')
        return "%s %s" % (status_code, reason)

    def method(self):
        """ get HTTP method as string"""
        self._check_headers_complete()
        return self.parser.get_method()

    def headers(self):
        """ get request/response headers, headers are returned in a
        OrderedDict that allows you to get value using insensitive
        keys."""
        self._check_headers_complete()
        return self.parser.get_headers()

    def should_keep_alive(self):
        """ return True if the connection should be kept alive
        """
        self._check_headers_complete()
        return self.parser.should_keep_alive()

    def is_chunked(self):
        """ return True if Transfer-Encoding header value is chunked"""
        self._check_headers_complete()
        return self.parser.is_chunked()

    def wsgi_environ(self, initial=None):
        """ get WSGI environ based on the current request.
        
        :attr initial: dict, initial values to fill in environ.
        """
        self._check_headers_complete()
        return self.parser.get_wsgi_environ()

    def body_file(self,
                  buffering=None,
                  binary=True,
                  encoding=None,
                  errors=None,
                  newline=None):
        """ return the body as a buffered stream object. If binary is
        true an io.BufferedReader will be returned, else an
        io.TextIOWrapper.
        """
        self._check_headers_complete()

        if buffering is None:
            buffering = -1
        if buffering < 0:
            buffering = DEFAULT_BUFFER_SIZE

        raw = HttpBodyReader(self)
        buffer = BufferedReader(raw, buffering)
        if binary:
            return buffer
        text = TextIOWrapper(buffer, encoding, errors, newline)
        return text

    def body_string(self,
                    binary=True,
                    encoding=None,
                    errors=None,
                    newline=None):
        """ return body as string """
        return self.body_file(binary=binary,
                              encoding=encoding,
                              newline=newline).read()

    def __iter__(self):
        return self

    def next(self):
        if self.parser.is_message_complete():
            raise StopIteration

        # fetch data
        b = bytearray(DEFAULT_BUFFER_SIZE)
        recved = self.stream.readinto(b)
        if recved is None:
            raise NoMoreData("no more data")

        del b[recved:]

        # parse data
        nparsed = self.parser.execute(bytes(b), recved)
        if nparsed != recved and not self.parser.is_message_complete():
            raise ParserError("nparsed != recved")

        if recved == 0:
            raise StopIteration

        return bytes(b)
示例#30
0
class HttpProxyProtocol(asyncio.Protocol):
    ''' Implement HTTP(S) proxy behavior. '''

    def __init__(self, loop, config, token_store):
        ''' Constructor. '''

        self._parser = HttpParser()
        self._body = b''
        self._config = config
        self._loop = loop
        self._mitm = None
        self._mitm_host = None
        self._token_store = token_store

        self._instagram = InstagramApi(
            client_id=config['Instagram']['ClientID'],
            client_secret=config['Instagram']['ClientSecret'],
        )

        self._twitter = TwitterApi(
            consumer_key=config['Twitter']['ConsumerKey'],
            consumer_secret=config['Twitter']['ConsumerSecret'],
            app_token=config['Twitter']['AppToken'],
            app_token_secret=config['Twitter']['AppTokenSecret'],
        )

    def connection_made(self, transport):
        ''' Save a reference to the transport so that we can send a reply. '''
        log.debug('Connection opened.')
        self._transport = transport

    def connection_lost(self, exc):
        log.debug('Connection closed.')

    def data_received(self, data):
        ''' Parse incoming HTTP request. '''

        log.debug('Data received: {}'.format(data))
        self._parser.execute(data, len(data))

        if self._parser.is_partial_body():
            self._body += self._parser.recv_body()

        if self._parser.is_message_complete():
            method = self._parser.get_method()
            uri = self._parser.get_url()
            version = self._parser.get_version()
            headers = self._parser.get_headers()
            content_type = headers.get('Content-type', '')
            charset = _get_charset(content_type)
            body = self._body.decode(charset)

            log.debug('Client charset: {}'.format(charset))
            log.debug('Client status: method={} uri={} version={}' \
                      .format(method, uri, version))
            log.debug('Client headers: {}'.format(headers))
            log.debug('Client body: {}...'.format(body[:1000]))

            if method == 'CONNECT':
                asyncio.async(self._start_mitm(uri, version))
                self._parser = HttpParser()
            else:
                asyncio.async(
                    self._request_upstream(
                        method,
                        uri,
                        version,
                        headers,
                        body
                    )
                )


    def start_tls(self, version):
        '''
        Initiate TLS session with the client.

        This part is completely hacky! We mess around with the
        transport's internals in order to wrap the current transport in TLS.
        Python doesn't have an official way to do this, although it *might*
        get fixed in 3.6: http://bugs.python.org/issue23749
        '''

        log.debug('The proxy is starting TLS with its client.')

        status_line = 'HTTP/{}.{} {} {}\r\n\r\n' \
                      .format(version[0], version[1], 200, 'OK')
        self._transport.write(status_line.encode('ascii'))

        ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
        ssl_context.set_ciphers('HIGH:!aNull:!eNull')
        ssl_context.load_cert_chain('ssl/server.crt', 'ssl/server.key')

        original_socket = self._transport._sock
        self._transport = self._loop._make_ssl_transport(
            original_socket,
            self,
            ssl_context,
            server_side=True
        )

    @asyncio.coroutine
    def _request_upstream(self, method, uri, version, headers, body):
        ''' Forward the request to the upstream server. '''

        try:
            yield from self._request_upstream_helper(
                method, uri, version, headers, body
            )
        except Exception:
            charset = _get_charset(headers.get('Content-type', ''))
            response = render_http_response(
                version,
                500,
                'PROXY ERROR',
                {'Content-type': 'text/plain; charset={}'.format(charset)},
                traceback.format_exc().encode(charset)
            )
            self._transport.write(response)
            self._transport.close()
            raise

    @asyncio.coroutine
    def _request_upstream_helper(self, method, uri, version, headers, body):
        ''' Forward the request to the upstream server. '''

        log.debug('_request_upstream(): method={}, uri={}' \
                  .format(method, uri))

        if self._mitm_host:
            parsed = urlparse(uri)
            url = 'https://{}{}'.format(self._mitm_host, parsed.path)
        else:
            url = uri

        token, remaining = self._token_store.dispense(url)
        log.debug('Signing request with {} token: {}.'
                  .format(token.site, token.public))

        if 'instagram' in url:
            qp = parse_qs(parsed.query)
            qp['access_token'] = token.public

            qp['sig'] = self._instagram.oauth_sign(
                method=method,
                url=url,
                token=token,
                query_params=qp,
                body_params=parse_qs(body)
            )

            params = ['{}={}'.format(quote(k.encode('utf8')), quote(v.encode('utf8'))) for k,v in qp.items()]
            uri = '{}?{}'.format(parsed.path, '&'.join(params))
            log.debug('Signed instagram URL: {}'.format(uri))
        elif 'twitter' in url:
            headers['Authorization'] = self._twitter.oauth_sign(
                method=method,
                url=url,
                token=token.public,
                token_secret=token.secret,
                query_params=parse_qs(parsed.query),
                body_params=parse_qs(body)
            )
        else:
            raise ValueError('No signing algorithm known for URL: {}'
                             .format(url))

        if self._mitm is None:
            url = urlparse(uri)
            host = url.hostname
            port = url.port

            if port is None:
                port = 80 if url.scheme == 'http' else 443

            log.debug('Connecting to upstream (plaintext).')
            upstream = yield from asyncio.open_connection(host, port)
            upstream_reader, upstream_writer = upstream
            request = render_http_request(method, uri, version, headers, body)
            upstream_writer.write(request)

            response = b''
            parser = HttpParser()

            while True:
                if not parser.is_headers_complete():
                    data = yield from upstream_reader.readline()
                else:
                    data = yield from upstream_reader.read(
                        int(parser.get_headers()['Content-Length'])
                    )

                log.debug('Received plaintext from upstream: {}'.format(data))
                parser.execute(data, len(data))

                if parser.is_partial_body():
                    body += parser.recv_body()

                if parser.is_message_complete():
                    version = self._parser.get_version()
                    status = self._parser.get_status_code()
                    reason = None # For some reason, the parser doesn't expose this :(
                    headers = self._parser.get_headers()

                    if status == 200:
                        self._token_store.update_rate_limit(url, headers)

                    log.debug('Plaintext upstream status: {}'.format(status))
                    log.debug('Plaintext upstream headers: {}'.format(headers))
                    log.debug('Plaintext upstream body: {}...'.format(body[:1000]))

                    response = render_http_response(
                        version, status, reason, headers, body
                    )

                    break

            upstream_writer.close()

        else:
            upstream_write = self._mitm.forward
            request = render_http_request(method, uri, version, headers, body)
            upstream_write(request)
            response = yield from self._mitm.receive()
            version, status, reason, headers, body = response

            if status == 200:
                self._token_store.update_rate_limit(token, url, headers)

            response = render_http_response(
                version, status, reason, headers, body
            )

        # Forward the upstream response to the client.
        self._transport.write(response)
        self._transport.close()

    def _set_header(self, key, value):
        ''' Set a header value. '''

        key = key.strip().upper()
        value = value.strip()
        self._headers[key] = value

    @asyncio.coroutine
    def _start_mitm(self, uri, version):
        ''' MITM a connection to the upstream server. '''

        log.debug('The proxy is starting an MITM connection.')
        host, port = uri.split(':')
        port = int(port)
        self._mitm_host = host

        _, self._mitm = yield from self._loop.create_connection(
            lambda: MitmProtocol(self._loop, version, self),
            host,
            port,
            ssl = ssl.create_default_context()
        )
示例#31
0
    def handleRequest(self, data):
        #should only get here if the request is completed to the double line return
        Debug.dprint("POLLER::handleRequest:data->" + str(data) + "<-data")
        #create and serve the clients request
        self.respHeaders = {}
        self.respHeaders['Server'] = "SimpleHTTP/0.6 Python/2.7.9"
        self.respHeaders['Date'] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime())

        #parse the data (GET header)
        try:
            from http_parser.parser import HttpParser
        except ImportError:
            from http_parser.pyparser import HttpParser

        p = HttpParser()
        nparsed = p.execute(data,len(data))

        #print basic debug from http parser
        Debug.dprint("POLLER::handleRequest:HttpParser:get_method()->" + p.get_method())
        Debug.dprint("POLLER::handleRequest:HttpParser:get_path()->" + p.get_path())
        Debug.dprint("POLLER::handleRequest:HttpParser:get_headers()\n")
        dataHeaders = p.get_headers()
        for i in dataHeaders:
            Debug.dprint(i + ":" + dataHeaders[i])

        #assign from http parser, headers grabbed previously
        method = p.get_method();
        path = p.get_path();




        #check for GET, if not return 501
        if method != 'GET':
            return self.code501();





        #identify host
        if dataHeaders.has_key('Host'):
            #if a host key is present
            Debug.dprint("POLLER::handleRequest:Host->" + dataHeaders['Host'])
            #check for the host key in the config dictionary
            if configHost.has_key(dataHeaders['Host']):
                #if the specified host is in the config dictionary, make the root directory the path assiated with requested host
                rootDir = configHost[dataHeaders['Host']]
            else:
                #if the specified host is not in the config dictionary, set to default??? THIS MAY NEED TO BE AN ERROR
                rootDir = configHost['default']
        else:
            #if a host key is not present
            rootDir = configHost['default']





        #identify requested file
        #for the case of an empty path, point to index
        if path =="/":
            #if the path is blank, set the path to index.html
            path = "/index.html"

        #attempt to retreive the file
        try:
            #identify the type of file
            fileType = ""
            if path.find('.') != -1:
                #split at the file extention period and isolate the filetype
                pathSplit = path.split('.')
                fileType = str(pathSplit[len(pathSplit) - 1])
                Debug.dprint("POLLER::handleRequest:fileType->" + str(fileType));

            #assign a MIME type from the condif dictionary
            if configMedia.has_key(fileType):
                self.respHeaders['Content-Type'] = configMedia[fileType]
            else:
                self.respHeaders['Content-Type'] = "test/plain"

            #check if the file excists, if not throw code 404
            #create filepath
            filePath = rootDir + path
            Debug.dprint("POLLER::handleRequest:filePath->" + str(filePath));
            if not os.path.isfile(filePath):
                return self.code404()

            #check for permissions, if not throw code 403
            if not os.access(filePath, os.R_OK):
                return self.code403()

            #read file as binary into a body variable
            fileReader = open(filePath, 'rb')
            respBody = fileReader.read()

        except IOError:
            return self.code500()


        #if everything worked, package response and return
        self.respHeaders['Content-Length'] = os.stat(filePath).st_size
        self.respHeaders['Last-Modified'] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime(os.stat(filePath).st_mtime))

        response = "HTTP/1.1 200 OK\r\n"

        for key in self.respHeaders:
            response += str(key) + ": " + str(self.respHeaders[key]) + "\r\n"
            Debug.dprint("POLLER::responseHeader: " + str(key) + ": " + str(self.respHeaders[key]))

        response += "\r\n"
        response += str(respBody)
        return response
示例#32
0
 def handle_read(self):
     try:
         logging.debug('Connection.handle_read - id=%d' % self.id)
         b = self.sock.recv(2048)
         logging.debug('Connection.handle_read - received buffer size is %d bytes' % len(b))
         logging.debug('Connection.handle_read - received buffer is : \n%s' % b)
         if not len(b):
             logging.debug('Connection.handle_read - 0 bytes received on %d. closing' %
                           self.id)
             self.close()
             return
         self.read_buf += b
     except socket.error as err:
         if err.args[0] not in NONBLOCKING:
             self.handle_error('%s' % args[1])
         else :
             logging.error('Connection.handle_read - NONBLOCKING event on read : %s' % args[1])
     else:
         # check if we have a full http request
         parser = HttpParser()
         recved = len(self.read_buf)
         nparsed = parser.execute(self.read_buf, recved)
         assert nparsed == recved
         if not parser.is_message_complete():
             # we got a partial request keep on reading
             logging.debug(
                 'Connection.handle_read - partial buffer received : \n%s' % 
                  self.read_buf)
             self.reset(pyev.EV_READ)
         else :
             # we got a full request
             self.read_buf = ''
             # match the verb with URI and call
             # after that register for write to send response
             verb = parser.get_method()
             url = parser.get_path()
             logging.debug('Connection.handle_read - id  %d - method is %s and url %s' % 
                 (self.id, verb, url))
             call, keyword_args = register.get_callable(url, verb)
             if not call :
                 err = HttpResponse()
                 err.status_code = 404
                 err.status_string = 'Not Found'
                 err.headers['Content-Type'] = 'application/txt'                    
                 err.body = 'URI Not Found\r\n'
                 self.write_buf = err.to_string()
             else :        
                 keyword_args['http_request'] = parser
                 logging.debug('Connection.handle_read - kargs=%s' % keyword_args)
                 try :
                     response = call(*[register.handler,], **keyword_args)
                     self.write_buf = response.to_string()
                 except :
                     err = HttpResponse()
                     err.status_code = 500
                     err.status_string = 'Internal Server Error'
                     err.headers['Content-Type'] = 'application/txt'                    
                     err.body = 'Upsssss.\r\n'
                     self.write_buf = err.to_string()
             logging.debug('Connection.handle_read - requesting write %d' % self.id)
             self.reset(pyev.EV_WRITE)
示例#33
0
class Interceptor(asyncio.Protocol):
    def __init__(self):
        # Loading the protocol certificates.
        ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        ssl_context.load_cert_chain("ssl/server.crt", "ssl/server.key")

        # Initiates the HttpParser object.
        self.http_parser = HttpParser()

        # Creates the TLS flag.
        self.using_tls = False

        # Initiating our HTTP transport with the emulated client.
        self.HTTP_Protocol = HTTP(using_ssl=False)

        # Setting our SSL context for the server.
        ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        ssl_context.load_cert_chain("ssl/server.crt", "ssl/server.key")

        # Opening our HTTPS transport.
        self.HTTPS_Protocol = asyncio.sslproto.SSLProtocol(
            loop=asyncio.get_running_loop(),
            app_protocol=HTTP(using_ssl=True),
            sslcontext=ssl_context,
            waiter=None,
            server_side=True,
        )

    def connection_made(self, transport):
        """ Called when client makes initial connection to the server. Receives a transporting object from the client. """

        # Setting our transport object.
        self.transport = transport

        # Getting the client address and port number.
        self.client_addr, self.client_ip = self.transport.get_extra_info("peername")

        # Prints opening client information.
        print(colored(f"CONNECTING WITH {self.client_addr}:{self.client_ip}", "blue"))

    def data_received(self, data):
        """
            Called when a connected client sends data to the server; HTTP or HTTPS requests.

            Note:
                This method is called multiple times during a typical TLS/SSL connection with a client.
                    1. Client sends server message to connect; "CONNECT."
                    2. Server replies with "OK" and begins handshake.
                    3. Client sends server encrypted HTTP requests; "GET", "POST", etc.
        """

        # Parses the data the client has sent to the server.
        self.http_parser.execute(data, len(data))

        if self.http_parser.get_method() == "CONNECT" and self.using_tls == False:
            # Replies to the client that the server has connected.
            self.transport.write(b"HTTP/1.1 200 OK\r\n\r\n")
            # Does a TLS/SSL handshake with the client.
            self.HTTPS_Protocol.connection_made(self.transport)
            # Sets our TLS flag to true.
            self.using_tls = True

            # Prints the data the client has sent. Since this is the initial 'CONNECT' data, it will be unencrypted.
            print(data)
        elif self.using_tls:
            # With HTTPS protocol enabled, receives encrypted data from the client.
            self.HTTPS_Protocol.data_received(data)
        else:
            # Receives standard, non-encrypted data from the client (TLS/SSL is off).
            self.HTTP_Protocol.connection_made(self.transport)
            self.HTTP_Protocol.data_received(data)
示例#34
0
文件: httpwrap.py 项目: yalpdevx/pupy
class PupyHTTPWrapperServer(BasePupyTransport):
    path = '/index.php?d='
    allowed_methods = ('GET')
    server = None
    headers = {
        'Content-Type': 'text/html; charset=utf-8',
        'Server': 'Apache',
        'Connection': 'close',
    }

    __slots__ = ('parser', 'is_http', 'body', 'downstream_buffer',
                 'well_known', 'omit', 'probe_len')

    def __init__(self, *args, **kwargs):
        super(PupyHTTPWrapperServer, self).__init__(*args, **kwargs)

        self.parser = HttpParser()
        self.is_http = None
        self.body = []
        self.downstream_buffer = Buffer()

        self.well_known = ('GET', 'POST', 'OPTIONS', 'HEAD', 'PUT', 'DELETE')
        self.omit = tuple('{} {}'.format(x, y) for x in self.well_known
                          for y in (self.path, '/ws/', 'ws/'))
        self.probe_len = max(len(x) for x in self.omit)

    def _http_response(self,
                       code,
                       status,
                       headers=None,
                       datasize=None,
                       content=None):
        headers = {}
        headers.update(self.headers)

        if headers:
            headers.update(headers)

        if datasize:
            headers.update({
                'Content-Length': datasize,
                'Content-Type': 'application/octet-stream',
            })

        data = '\r\n'.join([
            'HTTP/1.1 {} {}'.format(code, status), '\r\n'.join([
                '{}: {}'.format(key, value)
                for key, value in headers.iteritems()
            ])
        ]) + '\r\n\r\n'

        self.downstream.write(data)

    def _handle_file(self, filepath):
        try:
            with open(filepath) as infile:
                size = stat(filepath).st_size
                self._http_response(200, 'OK', datasize=size)

                while True:
                    data = infile.read(65535)
                    if data:
                        self.downstream.write(data)
                    else:
                        break

        except:
            self._http_response(404, 'Not found', 'Not found')

    def _handle_not_found(self):
        self._http_response(404, 'Not found', 'Not found')

    def _handle_http(self, data):
        self.parser.execute(data, len(data))

        if self.parser.is_headers_complete():
            try:
                if not self.parser.get_method() in self.allowed_methods:
                    self._http_response(405, 'Method Not Allowed')

                else:
                    urlpath = self.parser.get_path()
                    urlpath = [
                        x.strip() for x in urlpath.split('/')
                        if (x and not str(x) in ('.', '..'))
                    ]

                    root = self.server.config.get_folder('wwwroot')
                    secret = self.server.config.getboolean('httpd', 'secret')
                    log = self.server.config.getboolean('httpd', 'log')

                    if secret:
                        wwwsecret = self.server.config.get('randoms',
                                                           'wwwsecret',
                                                           random=5)
                        if not (urlpath and urlpath[0] == wwwsecret):
                            self._handle_not_found()
                            if log:
                                self.server.info(
                                    '{}: GET {} | SECRET = {}'.format(
                                        '{}:{}'.format(*self.downstream.
                                                       transport.peer[:2]),
                                        urlpath, wwwsecret),
                                    error=True)
                            return

                        urlpath = urlpath[1:]

                    urlpath = path.sep.join([
                        self.server.config.get('randoms', x, new=False) or x
                        for x in urlpath
                    ])

                    if not urlpath:
                        urlpath = 'index.html'

                    filepath = path.join(root, urlpath)

                    if path.exists(filepath):
                        self._handle_file(filepath)
                        if log:
                            message = urlpath
                            if filepath in self.server.served_content:
                                message = message + ' <' + self.server.served_content[
                                    filepath] + '>'

                            self.server.info('{}: GET /{}'.format(
                                '{}:{}'.format(
                                    *self.downstream.transport.peer[:2]),
                                message))

                    else:
                        self._handle_not_found()
                        if log:
                            self.server.info('{}: GET {}'.format(
                                '{}:{}'.format(
                                    *self.downstream.transport.peer[:2]),
                                urlpath),
                                             error=True)
            finally:
                self.close()

    def downstream_recv(self, data):
        header = data.peek(self.probe_len)

        if __debug__:
            logger.debug('Recv: len=%d // header = %s', len(data), header)

        if self.server and self.is_http is None:
            self.is_http = header.startswith(self.well_known) and \
              not header.startswith(self.omit)

            if __debug__:
                logger.debug('Http: %s', self.is_http)

        if self.is_http:
            self._handle_http(data.read())
        else:
            if __debug__:
                logger.debug('Write to upstream: len=%d, handler=%s',
                             len(data), self.upstream.on_write_f)

            data.write_to(self.upstream)

            if self.downstream_buffer:
                if __debug__:
                    logger.debug(
                        'Flush buffer to downstream: len=%d, handler=%s',
                        len(self.downstream_buffer),
                        self.downstream.on_write_f)

                self.downstream_buffer.write_to(self.downstream)

            if __debug__:
                logger.debug('Release transport')

            raise ReleaseChainedTransport()

    def upstream_recv(self, data):
        if __debug__:
            logger.debug('Send intent: len=%d', len(data))

        if self.is_http is None:
            data.write_to(self.downstream_buffer)

            if __debug__:
                logger.debug('HTTP? Append to pending buffer: total len=%d',
                             len(self.downstream_buffer))

        elif not self.is_http:
            if __debug__:
                logger.debug('Non-HTTP: Direct pass (handler=%s)',
                             self.downstream.on_write_f)

            if self.downstream_buffer:
                self.downstream_buffer.write_to(self.downstream)

            data.write_to(self.downstream)
        else:
            if __debug__:
                logger.debug('HTTP: Omit data')

            pass
示例#35
0
文件: web.py 项目: jvansteeter/CS-360
    def handleRequest(self,data):
        """Prcess the request made by the client and send the response"""
        Debug.dprint("POLLER::handleRequest()")
        self.headers = {}
        self.headers['Server'] = "SimpleHTTP/0.6 Python/2.7.9"
        self.headers['Date'] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime())
        #self.headers['Connection'] = "close"
        p = HttpParser()
        nparsed = p.execute(data,len(data))
        method = p.get_method()
        path = p.get_path()
        headers = p.get_headers()
        Debug.dprint("POLLER::handleClient()::get_method= " + str(p.get_method()))
        Debug.dprint("POLLER::handleClient()::get_path= " + str(p.get_path()))
        Debug.dprint("POLLER::handleClient()::get_headers= " + str(p.get_headers()))

        """Check the Method, if not GET return 501"""
        if method != 'GET':
            return self.response501()

        """Determine Host"""
        if headers.has_key('Host'):
            Debug.dprint("POLLER::Host= " + headers['Host'])
            RootDir = ""
            if headers['Host'].find("localhost") != -1 and configHost.has_key('localhost'):
                RootDir = configHost['localhost']
            else:
                RootDir = configHost['default']
        else:
            RootDir = configHost['default']

        """Find requested Resource"""
        if path == "/":
            path = "/index.html"
        try:
            dataType = ""
            if path.find('.') != -1:
                pathObjects = path.split('.')
                dataType = str(pathObjects[len(pathObjects) - 1])

            if configMedia.has_key(dataType):
                self.headers['Content-Type'] = configMedia[dataType]
            else:
                self.headers['Content-Type'] = "text/plain"

            fileName = RootDir + path
            """See if the requested file actually exists"""
            if not os.path.isfile(fileName):
                return self.response404()
            
            """Check if we have permissions to open the file"""
            if not os.access(fileName, os.R_OK):
                return self.response403()

            fileReader = open(fileName, 'rb')
            body = fileReader.read()
            self.headers['Content-Length'] = os.stat(fileName).st_size
            self.headers['Last-Modified'] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime(os.stat(fileName).st_mtime))
            response = "HTTP/1.1 200 OK\r\n"
            for key in self.headers:
                response += str(key) + ": " + str(self.headers[key]) + "\r\n"
                Debug.dprint("POLLER::responseHeader: " + str(key) + ": " + str(self.headers[key]))
            """response += "Date: " + str(self.headers['Date']) + "\r\n"
            response += "Server: " + str(self.headers['Server']) + "\r\n"
            response += "Content-Type: " + str(self.headers['Content-Type']) + "\r\n"
            response += "Content-Length: " + str(self.headers['Content-Length']) + "\r\n"
            response += "Last-Modified: " + str(self.headers['Last-Modified']) + "\r\n"""
            response += "\r\n"
            response += str(body)
            return response
        except IOError:
            return self.response500()
示例#36
0
文件: poller.py 项目: dolson25/school
                date = time.strftime(self.format, time.gmtime())

                if (not p.is_headers_complete()):
                    # 404 Bad Request
                    response = "HTTP/1.1 400 Bad Request\r\n"
                    response += "Date: " + date + "\r\n"
                    response += "Server: David's Python Server (Ubuntu)\r\n"
                    message = "Bad HTTP Request, 400"
                    response += "Content-Length: " + str(len(message)) + "\r\n"
                    response += "Content-Type: text/html\r\n\r\n"
                    response += message
                    self.clients[fd].send(response)
                    return

                if (not (p.get_method() == "GET" or p.get_method() == "HEAD")):
                    # 501 Not Implemented
                    response = "HTTP/1.1 501 Not Implemented\r\n"
                    response += "Date: " + date + "\r\n"
                    response += "Server: David's Python Server (Ubuntu)\r\n"
                    message = "Method Not Implemented, 501"
                    response += "Content-Length: " + str(len(message)) + "\r\n"
                    response += "Content-Type: text/html\r\n\r\n"
                    response += message
                    self.clients[fd].send(response)
                    return

                #find the file from the url
                file_path = ""

                if (p.get_path() == '/'):
while True:
    (clientsocket, address) = serversocket.accept()
    parser = HttpParser()
    body = []
    while True:
        data = clientsocket.recv(1024)
        if not data:
            break
        
        recved = len(data)
        nparsed = parser.execute(data, recved)
        assert nparsed == recved

        if parser.is_headers_complete():
            print parser.get_method()
            print parser.get_path()

        if parser.is_partial_body():
            body.append(parser.recv_body())

        if parser.is_message_complete():
            break
    
    print ''.join(body)

    result = process_request(parser.get_method(),
                             parser.get_path(),
                             dict([x.split('=') for x in ''.join(body).split('&') if len(x.split('=')) == 2]))
    result += '\n'
    clientsocket.send(response + str(result))
示例#38
0
class HttpStream(object):
    """ An HTTP parser providing higher-level access to a readable,
    sequential io.RawIOBase object. You can use implementions of
    http_parser.reader (IterReader, StringReader, SocketReader) or
    create your own.
    """

    def __init__(self, stream, kind=HTTP_BOTH, decompress=False):
        """ constructor of HttpStream.

        :attr stream: an io.RawIOBase object
        :attr kind: Int,  could be 0 to parseonly requests,
        1 to parse only responses or 2 if we want to let
        the parser detect the type.
        """
        self.parser = HttpParser(kind=kind, decompress=decompress)
        self.stream = stream

    def _check_headers_complete(self):
        if self.parser.is_headers_complete():
            return

        while True:
            try:
                next(self)
            except StopIteration:
                if self.parser.is_headers_complete():
                    return
                raise NoMoreData("Can't parse headers")

            if self.parser.is_headers_complete():
                return


    def _wait_status_line(self, cond):
        if self.parser.is_headers_complete():
            return True

        data = []
        if not cond():
            while True:
                try:
                    d = next(self)
                    data.append(d)
                except StopIteration:
                    if self.parser.is_headers_complete():
                        return True
                    raise BadStatusLine(b"".join(data))
                if cond():
                    return True
        return True

    def _wait_on_url(self):
        return self._wait_status_line(self.parser.get_url)

    def _wait_on_status(self):
        return self._wait_status_line(self.parser.get_status_code)

    def url(self):
        """ get full url of the request """
        self._wait_on_url()
        return self.parser.get_url()

    def path(self):
        """ get path of the request (url without query string and
        fragment """
        self._wait_on_url()
        return self.parser.get_path()

    def query_string(self):
        """ get query string of the url """
        self._wait_on_url()
        return self.parser.get_query_string()

    def fragment(self):
        """ get fragment of the url """
        self._wait_on_url()
        return self.parser.get_fragment()

    def version(self):
        self._wait_on_status()
        return self.parser.get_version()

    def status_code(self):
        """ get status code of a response as integer """
        self._wait_on_status()
        return self.parser.get_status_code()

    def status(self):
        """ return complete status with reason """
        status_code = self.status_code()
        reason = status_reasons.get(int(status_code), 'unknown')
        return "%s %s" % (status_code, reason)


    def method(self):
        """ get HTTP method as string"""
        self._wait_on_status()
        return self.parser.get_method()

    def headers(self):
        """ get request/response headers, headers are returned in a
        OrderedDict that allows you to get value using insensitive
        keys."""
        self._check_headers_complete()
        return self.parser.get_headers()

    def should_keep_alive(self):
        """ return True if the connection should be kept alive
        """
        self._check_headers_complete()
        return self.parser.should_keep_alive()

    def is_chunked(self):
        """ return True if Transfer-Encoding header value is chunked"""
        self._check_headers_complete()
        return self.parser.is_chunked()

    def wsgi_environ(self, initial=None):
        """ get WSGI environ based on the current request.

        :attr initial: dict, initial values to fill in environ.
        """
        self._check_headers_complete()
        return self.parser.get_wsgi_environ()

    def body_file(self, buffering=None, binary=True, encoding=None,
            errors=None, newline=None):
        """ return the body as a buffered stream object. If binary is
        true an io.BufferedReader will be returned, else an
        io.TextIOWrapper.
        """
        self._check_headers_complete()

        if buffering is None:
            buffering = -1
        if buffering < 0:
            buffering = DEFAULT_BUFFER_SIZE

        raw = HttpBodyReader(self)
        buf = BufferedReader(raw, buffering)
        if binary:
            return buf
        text = TextIOWrapper(buf, encoding, errors, newline)
        return text

    def body_string(self, binary=True, encoding=None, errors=None,
            newline=None):
        """ return body as string """
        return self.body_file(binary=binary, encoding=encoding,
                newline=newline).read()

    def __iter__(self):
        return self

    def __next__(self):
        if self.parser.is_message_complete():
            raise StopIteration

        # fetch data
        b = bytearray(DEFAULT_BUFFER_SIZE)
        recved = self.stream.readinto(b)
        if recved is None:
            raise NoMoreData("no more data")

        del b[recved:]
        to_parse = bytes(b)
        # parse data
        nparsed = self.parser.execute(to_parse, recved)
        if nparsed != recved and not self.parser.is_message_complete():
            raise ParserError("nparsed != recved (%s != %s) [%s]" % (nparsed,
                recved, bytes_to_str(to_parse)))

        if recved == 0:
            raise StopIteration

        return to_parse

    next = __next__
示例#39
0
class PupyHTTPWrapperServer(BasePupyTransport):
    path = '/index.php?d='
    allowed_methods = ('GET')
    server = None
    headers = {
        'Content-Type': 'text/html; charset=utf-8',
        'Server': 'Apache',
        'Connection': 'close',
    }

    __slots__ = (
        'parser', 'is_http',
        'body', 'downstream_buffer',
        'well_known', 'omit', 'probe_len'
    )

    def __init__(self, *args, **kwargs):
        super(PupyHTTPWrapperServer, self).__init__(*args, **kwargs)

        self.parser = HttpParser()
        self.is_http = None
        self.body = []
        self.downstream_buffer = Buffer()

        self.well_known = ('GET', 'POST', 'OPTIONS', 'HEAD', 'PUT', 'DELETE')
        self.omit = tuple(
            '{} {}'.format(x, y) for x in self.well_known for y in (
                self.path, '/ws/', 'ws/'))
        self.probe_len = max(len(x) for x in self.omit)

    def _http_response(self, code, status, headers=None, datasize=None, content=None):
        headers = {}
        headers.update(self.headers)

        if headers:
            headers.update(headers)

        if datasize:
            headers.update({
                'Content-Length': datasize,
                'Content-Type': 'application/octet-steram',
            })

        data = '\r\n'.join([
            'HTTP/1.1 {} {}'.format(code, status),
            '\r\n'.join([
                '{}: {}'.format(key, value) for key,value in headers.iteritems()
            ])
        ]) + '\r\n\r\n'

        self.downstream.write(data)

    def _handle_file(self, filepath):
        try:
            with open(filepath) as infile:
                size = stat(filepath).st_size
                self._http_response(200, 'OK', datasize=size)

                while True:
                    data = infile.read(65535)
                    if data:
                        self.downstream.write(data)
                    else:
                        break

        except:
            self._http_response(404, 'Not found', 'Not found')

    def _handle_not_found(self):
        self._http_response(404, 'Not found', 'Not found')

    def _handle_http(self, data):
        self.parser.execute(data, len(data))

        if self.parser.is_headers_complete():
            try:
                if not self.parser.get_method() in self.allowed_methods:
                    self._http_response(405, 'Method Not Allowed')

                else:
                    urlpath = self.parser.get_path()
                    urlpath = [
                        x.strip() for x in urlpath.split('/') if (
                            x and not str(x) in ('.', '..')
                        )
                    ]

                    root = self.server.config.get_folder('wwwroot')
                    secret = self.server.config.getboolean('httpd', 'secret')
                    log = self.server.config.getboolean('httpd', 'log')

                    if secret:
                        wwwsecret = self.server.config.get('randoms', 'wwwsecret', random=5)
                        if not (urlpath and urlpath[0] == wwwsecret):
                            self._handle_not_found()
                            if log:
                                self.server.handler.display_error('{}: GET {} | SECRET = {}'.format(
                                    '{}:{}'.format(*self.downstream.transport.peer[:2]), urlpath, wwwsecret))
                            return

                        urlpath = urlpath[1:]

                    urlpath = path.sep.join([
                        self.server.config.get('randoms', x, new=False) or x for x in urlpath
                    ])

                    if not urlpath:
                        urlpath = 'index.html'

                    filepath = path.join(root, urlpath)

                    if path.exists(filepath):
                        self._handle_file(filepath)
                        if log:
                            self.server.handler.display_success('{}: GET {}'.format(
                                '{}:{}'.format(*self.downstream.transport.peer[:2]), urlpath))

                    else:
                        self._handle_not_found()
                        if log:
                            self.server.handler.display_error('{}: GET {}'.format(
                                '{}:{}'.format(*self.downstream.transport.peer[:2]), urlpath))

            except Exception, e:
                print "Exception: {}".format(e)

            finally:
    def parse(self):
        data = [{
            'label':
            '以太网帧头部 / Ethernet Headers',
            'value':
            '',
            'bold':
            True,
            'children': [{
                'label': '目的端 MAC 地址',
                'value': self.ethHeader.destMac
            }, {
                'label': '发送端 MAC 地址',
                'value': self.ethHeader.sourceMac
            }, {
                'label':
                '帧类型',
                'value':
                '%s (0x%s)' % (self.ethHeader.type, self.ethHeader.type_code)
            }]
        }]

        if self.protocol == 'ARP':
            data.append({
                'label':
                'ARP 消息 / Address Resolution Protocol',
                'value':
                '',
                'bold':
                True,
                'children': [{
                    'label':
                    '硬件类型',
                    'value':
                    '%s (%s)' % (self.arpBody.hardware_type,
                                 self.arpBody.hardware_type_code)
                }, {
                    'label':
                    '协议类型',
                    'value':
                    '%s (0x%s)' % (self.arpBody.protocol_type,
                                   self.arpBody.protocol_type_code)
                }, {
                    'label': '硬件地址长度',
                    'value': str(self.arpBody.hardware_size)
                }, {
                    'label': '协议地址长度',
                    'value': str(self.arpBody.protocol_size)
                }, {
                    'label':
                    '操作码',
                    'value':
                    '%s (%s)' %
                    (self.arpBody.operation, self.arpBody.operation_code)
                }, {
                    'label': '发送端 MAC 地址',
                    'value': self.arpBody.sender_mac_address
                }, {
                    'label': '发送端 IP 地址',
                    'value': self.arpBody.sender_ip_address
                }, {
                    'label': '目的端 MAC 地址',
                    'value': self.arpBody.target_mac_address
                }, {
                    'label': '目的端 IP 地址',
                    'value': self.arpBody.target_ip_address
                }]
            })
        else:

            if self.ipHeader.version == 4:
                self.ipHeader.verifyChecksum = verifyChecksum(
                    self.ipHeader.header_raw, [], '').verifyChecksum
                data.append({
                    'label':
                    'IPv4 头部 / IPv4 Header',
                    'value':
                    '',
                    'bold':
                    True,
                    'children': [{
                        'label': '协议版本',
                        'value': self.ipHeader.version
                    }, {
                        'label':
                        '头部长度',
                        'value':
                        str(self.ipHeader.header_length) + ' Bytes'
                    }, {
                        'label':
                        '服务类型',
                        'value':
                        '0x%s' % (self.ipHeader.differentiated_services)
                    }, {
                        'label': '来源 IP',
                        'value': self.ipHeader.source_ip
                    }, {
                        'label': '目标 IP',
                        'value': self.ipHeader.dest_ip
                    }, {
                        'label': '总长度',
                        'value': self.ipHeader.total_length
                    }, {
                        'label':
                        '标识',
                        'value':
                        '0x%s (%s)' % (self.ipHeader.identification,
                                       self.ipHeader.identification_int)
                    }, {
                        'label':
                        '标志',
                        'value':
                        '%s' % (self.ipHeader.flags.raw),
                        'children': [{
                            'label':
                            '保留位',
                            'value':
                            '%s | %s... .... .... ....' %
                            (self.ipHeader.flags.reserved,
                             int(self.ipHeader.flags.reserved))
                        }, {
                            'label':
                            'Don\'t fragment',
                            'value':
                            '%s | .%s.. .... .... ....' %
                            (self.ipHeader.flags.fragment,
                             int(self.ipHeader.flags.fragment))
                        }, {
                            'label':
                            'More fragments',
                            'value':
                            '%s | ..%s. .... .... ....' %
                            (self.ipHeader.flags.more_fragment,
                             int(self.ipHeader.flags.more_fragment))
                        }, {
                            'label':
                            '分段偏移',
                            'value':
                            '%s | ...%s' %
                            (self.ipHeader.flags.fragment_offset,
                             self.ipHeader.flags.fragment_offset_bin)
                        }]
                    }, {
                        'label': '生存期',
                        'value': self.ipHeader.time_to_live
                    }, {
                        'label':
                        '协议',
                        'value':
                        '%s (%s)' %
                        (self.ipHeader.protocol, self.ipHeader.protocol_code)
                    }, {
                        'label':
                        '校验和',
                        'value':
                        '0x%s (%s)' % (self.ipHeader.origin_checksum, '校验' + {
                            True: '通过',
                            False: '失败'
                        }[self.ipHeader.verifyChecksum])
                    }]
                })

            else:
                ipv6_header = {
                    'label':
                    'IPv6 头部 / IPv6 Header',
                    'value':
                    '',
                    'bold':
                    True,
                    'children': [{
                        'label': '协议版本',
                        'value': self.ipHeader.version
                    }, {
                        'label': '通信分类',
                        'value': '0x%s' % (self.ipHeader._class)
                    }, {
                        'label': '流标签',
                        'value': '0x%s' % (self.ipHeader.float_label)
                    }, {
                        'label': '有效载荷长度',
                        'value': self.ipHeader.payload_length
                    }, {
                        'label':
                        '下一头部类型',
                        'value':
                        '%s (%s)' % (self.ipHeader.next_header,
                                     self.ipHeader.next_header_code)
                    }, {
                        'label': '跳数限制',
                        'value': self.ipHeader.hop_limit
                    }, {
                        'label': '源 IP',
                        'value': self.ipHeader.source_ip
                    }, {
                        'label': '目的 IP',
                        'value': self.ipHeader.dest_ip
                    }]
                }

                for option in self.ipHeader.options:
                    ipv6_header['children'].append({
                        'label':
                        consts.protocol_types[str(option['code'])],
                        'value':
                        '0x' + option['value'],
                        'children': [{
                            'label':
                            '下一头部类型',
                            'value':
                            '%s (%s)' % (consts.protocol_types[str(
                                option['next_header'])], option['next_header'])
                        }]
                    })

                data.append(ipv6_header)

            if self.ipHeader.version == 4 and self.ipHeader.flags.more_fragment == True:
                # print('Waiting for more fragments.')
                ids = self.ip_ids[self.ipHeader.identification_int]
                slicing = {
                    'label': 'IP 分片',
                    'value': '共 %s 个数据包' % len(ids),
                    'bold': True,
                    'children': []
                }
                for id in ids:
                    slicing['children'].append({
                        'label':
                        '#%s' % id,
                        'value':
                        '%s Bytes' % (self.ip_packets[id].length / 8)
                    })
                data.append(slicing)
            else:
                if self.ipHeader.protocol == 'TCP':
                    self.ipBody.tcpHeader.verifyChecksum = verifyChecksum(
                        self.ipBody.parameters[0], self.ipBody.parameters[1],
                        self.ipHeader.protocol).verifyChecksum
                    self.ipBody.tcpHeader.options = tcpOptions(
                        BitArray(self.ipBodyRaw)
                        [160:self.ipBody.tcpHeader.header_length * 8]).options
                    tcp_header = {
                        'label':
                        'TCP 头部 / Transmission Control Protocol Header',
                        'value':
                        '',
                        'bold':
                        True,
                        'children': [{
                            'label': '源端口',
                            'value': self.ipBody.tcpHeader.source_port
                        }, {
                            'label':
                            '目的端口',
                            'value':
                            self.ipBody.tcpHeader.destination_port
                        }, {
                            'label':
                            '数据序号 (seq)',
                            'value':
                            self.ipBody.tcpHeader.sequence_number
                        }, {
                            'label':
                            '确认序号 (ack)',
                            'value':
                            self.ipBody.tcpHeader.acknowledge_number
                        }, {
                            'label':
                            '首部长度',
                            'value':
                            self.ipBody.tcpHeader.header_length
                        }, {
                            'label':
                            '标志位',
                            'value':
                            '0x' + self.ipBody.tcpHeader.flags_raw,
                            'children': [{
                                'label':
                                'Reserved',
                                'value':
                                '%s | %s. .... ....' %
                                (self.ipBody.tcpHeader.flags.reserved.uint,
                                 self.ipBody.tcpHeader.flags.reserved.bin)
                            }, {
                                'label':
                                'Nonce',
                                'value':
                                '%s | ...%d .... ....' %
                                (self.ipBody.tcpHeader.flags.nonce,
                                 self.ipBody.tcpHeader.flags.nonce)
                            }, {
                                'label':
                                'Congestion Window Reduced',
                                'value':
                                '%s | .... %d... ....' %
                                (self.ipBody.tcpHeader.flags.cwr,
                                 self.ipBody.tcpHeader.flags.cwr)
                            }, {
                                'label':
                                'ECN-Echo',
                                'value':
                                '%s | .... .%d.. ....' %
                                (self.ipBody.tcpHeader.flags.ecn_echo,
                                 self.ipBody.tcpHeader.flags.ecn_echo)
                            }, {
                                'label':
                                'Urgent',
                                'value':
                                '%s | .... ..%d. ....' %
                                (self.ipBody.tcpHeader.flags.urgent,
                                 self.ipBody.tcpHeader.flags.urgent)
                            }, {
                                'label':
                                'Acknowledgment',
                                'value':
                                '%s | .... ...%d ....' %
                                (self.ipBody.tcpHeader.flags.acknowledgement,
                                 self.ipBody.tcpHeader.flags.acknowledgement)
                            }, {
                                'label':
                                'Push',
                                'value':
                                '%s | .... .... %d...' %
                                (self.ipBody.tcpHeader.flags.push,
                                 self.ipBody.tcpHeader.flags.push)
                            }, {
                                'label':
                                'Reset',
                                'value':
                                '%s | .... .... .%d..' %
                                (self.ipBody.tcpHeader.flags.reset,
                                 self.ipBody.tcpHeader.flags.reset)
                            }, {
                                'label':
                                'Syn',
                                'value':
                                '%s | .... .... ..%d.' %
                                (self.ipBody.tcpHeader.flags.syn,
                                 self.ipBody.tcpHeader.flags.syn)
                            }, {
                                'label':
                                'Fin',
                                'value':
                                '%s | .... .... ...%d' %
                                (self.ipBody.tcpHeader.flags.fin,
                                 self.ipBody.tcpHeader.flags.fin)
                            }]
                        }, {
                            'label': '窗口大小',
                            'value': self.ipBody.tcpHeader.window_size
                        }, {
                            'label':
                            '校验和',
                            'value':
                            '0x%s (%s)' %
                            (self.ipBody.tcpHeader.checksum, '校验' + {
                                True: '通过',
                                False: '失败'
                            }[self.ipBody.tcpHeader.verifyChecksum])
                        }]
                    }
                    options = []
                    if self.ipBody.tcpHeader.options:
                        for idx in range(len(self.ipBody.tcpHeader.options)):
                            option = {
                                'label':
                                self.ipBody.tcpHeader.options[idx][0]['label'],
                                'value':
                                '(%s)' %
                                self.ipBody.tcpHeader.options[idx][0]['value'],
                                'children':
                                self.ipBody.tcpHeader.options[idx][1:]
                            }
                            options.append(option)
                    if options:
                        tcp_header['children'].append({
                            'label': '选项',
                            'value': '',
                            'children': options
                        })

                    data.append(tcp_header)

                    print(self.id)
                    print(tcp_bodies)
                    if self.id in packet_id_struct:
                        tmp = []
                        http_payload = None
                        for p_id in packet_id_struct[self.id]:
                            tmp.append({'value': '', 'label': '#%s' % p_id})

                        if self.id in tcp_bodies:
                            # print(tcp_bodies[self.id]['data'].decode('utf-8', 'ignore'))
                            children = [{
                                'label':
                                '该包是 TCP 分段的最后一段, 可以通过右下角按钮「导出 TCP 分段数据」.',
                                'value': '',
                                'bold': True
                            }, {
                                'label': '共 %s 个分段' % len(tmp),
                                'value': '',
                                'bold': True,
                                'children': tmp
                            }]

                            try:
                                p = HttpParser()
                                recved = len(tcp_bodies[self.id]['data'])
                                nparsed = p.execute(
                                    tcp_bodies[self.id]['data'], recved)
                                assert nparsed == recved

                                headers = []
                                for header in p.get_headers():
                                    headers.append({
                                        'label':
                                        header,
                                        'value':
                                        p.get_headers()[header]
                                    })

                                print(p.get_path(), p.get_url(),
                                      p.get_fragment(), p.get_method(),
                                      p.get_query_string(),
                                      p.get_status_code(),
                                      p.get_wsgi_environ())

                                http_payload = [{
                                    'label':
                                    'HTTP 版本',
                                    'value':
                                    '%s.%s' %
                                    (p.get_version()[0], p.get_version()[1])
                                }, {
                                    'label': 'HTTP 头部',
                                    'value': '',
                                    'children': headers
                                }]

                                if len(p.get_url()) != 0:
                                    http_payload.append({
                                        'label': '请求方式',
                                        'value': p.get_method()
                                    })
                                    http_payload.append({
                                        'label': '路径',
                                        'value': p.get_url()
                                    })
                                    http_payload.append({
                                        'label':
                                        '请求参数',
                                        'value':
                                        p.get_query_string()
                                    })
                                    http_payload.append({
                                        'label':
                                        '主机名',
                                        'value':
                                        p.get_wsgi_environ()['HTTP_HOST']
                                    })
                                else:
                                    http_payload.append({
                                        'label':
                                        '状态码',
                                        'value':
                                        p.get_status_code()
                                    })

                            except AssertionError:
                                pass

                        else:
                            children = [{
                                'label': '共 %s 个分段' % len(tmp),
                                'value': '',
                                'bold': True,
                                'children': tmp
                            }]

                        data.append({
                            'label': 'TCP 数据 / TCP Payload',
                            'value': '',
                            'bold': True,
                            'children': children
                        })

                        if http_payload != None:
                            data.append({
                                'label': 'HTTP 数据 / HTTP Data',
                                'value': '',
                                'bold': True,
                                'children': http_payload
                            })
                    '''
                    if self.ipBody.tcpBody.has_body:
                        try:
                            p = HttpParser()
                            recved = len(self.ipBody.tcpBody.buf)
                            nparsed = p.execute(self.ipBody.tcpBody.buf, recved)
                            assert nparsed == recved

                            print(p.get_headers())
                        except AssertionError:
                            print('NOT HTTP')

                        data.append({
                            'label': 'TCP 数据 / Data',
                            'value': '',
                            'bold': True,
                            'children': [
                                {
                                    'label': '数据',
                                    'value': self.ipBody.tcpBody.raw
                                }
                            ]
                        })
                    '''

                elif self.ipHeader.protocol == 'UDP':
                    self.ipBody.udpHeader.verifyChecksum = verifyChecksum(
                        self.ipBody.parameters[0], self.ipBody.parameters[1],
                        self.ipHeader.protocol).verifyChecksum
                    data.append({
                        'label':
                        'UDP 头部 / User Datagram Protocol Header',
                        'value':
                        '',
                        'bold':
                        True,
                        'children': [{
                            'label': '源端口',
                            'value': self.ipBody.udpHeader.source_port
                        }, {
                            'label':
                            '目的端口',
                            'value':
                            self.ipBody.udpHeader.destination_port
                        }, {
                            'label': '长度',
                            'value': self.ipBody.udpHeader.length
                        }, {
                            'label':
                            '校验和',
                            'value':
                            '0x%s (%s)' %
                            (self.ipBody.udpHeader.checksum, '校验' + {
                                True: '通过',
                                False: '失败'
                            }[self.ipBody.udpHeader.verifyChecksum])
                        }]
                    })

                    if self.ipBody.udpHeader.source_port == 53 or self.ipBody.udpHeader.destination_port == 53:  # DNS
                        children = [{
                            'label': '会话标识',
                            'value': self.ipBody.dnsBody.transaction_id
                        }, {
                            'label':
                            '标志',
                            'value':
                            '0x' + self.ipBody.dnsBody.transaction_id
                        }, {
                            'label': '问题数',
                            'value': self.ipBody.dnsBody.questions
                        }, {
                            'label': '回答资源记录数',
                            'value': self.ipBody.dnsBody.answer_rrs
                        }, {
                            'label': '授权资源记录数',
                            'value': self.ipBody.dnsBody.authority_rrs
                        }, {
                            'label': '附加资源记录数',
                            'value': self.ipBody.dnsBody.additional_rrs
                        }]

                        if len(self.ipBody.dnsBody.queries) > 0:
                            queries = []
                            for query in self.ipBody.dnsBody.queries:
                                queries.append({
                                    'label':
                                    str(query.qname),
                                    'value':
                                    '',
                                    'bold':
                                    True,
                                    'children': [{
                                        'label': '域名',
                                        'value': str(query.qname)
                                    }, {
                                        'label':
                                        'Type',
                                        'value':
                                        '%s (%s)' %
                                        (consts.dns_types[query.qtype],
                                         query.qtype)
                                    }, {
                                        'label':
                                        'Class',
                                        'value':
                                        '%s (%s)' %
                                        (consts.dns_classes[query.qclass],
                                         query.qclass)
                                    }]
                                })
                            children.append({
                                'label': '查询问题',
                                'value': '',
                                'bold': True,
                                'children': queries
                            })

                        if len(self.ipBody.dnsBody.answers) > 0:
                            answers = []
                            for answer in self.ipBody.dnsBody.answers:
                                answers.append({
                                    'label':
                                    str(answer.rname),
                                    'value':
                                    '',
                                    'bold':
                                    True,
                                    'children': [{
                                        'label': '域名',
                                        'value': str(answer.rname)
                                    }, {
                                        'label':
                                        'Type',
                                        'value':
                                        '%s (%s)' %
                                        (consts.dns_types[answer.rtype],
                                         answer.rtype)
                                    }, {
                                        'label':
                                        'Class',
                                        'value':
                                        '%s (%s)' %
                                        (consts.dns_classes[answer.rclass],
                                         answer.rclass)
                                    }, {
                                        'label': '生存时间 (ttl)',
                                        'value': str(answer.ttl)
                                    }, {
                                        'label': '数据',
                                        'value': str(answer.rdata)
                                    }]
                                })
                            children.append({
                                'label': '回答',
                                'value': '',
                                'bold': True,
                                'children': answers
                            })

                        data.append({
                            'label': 'DNS / Domain Name System',
                            'value': '',
                            'bold': True,
                            'children': children
                        })

                elif 'ICMP' in self.ipHeader.protocol:
                    if 'IPv6' in self.ipHeader.protocol:
                        self.ipBody.icmpHeader.verifyChecksum = verifyChecksum(
                            self.ipBody.parameters[0],
                            self.ipBody.parameters[1],
                            self.ipHeader.protocol).verifyChecksum
                    else:
                        self.ipBody.icmpHeader.verifyChecksum = verifyChecksum(
                            self.ipBody.parameters, [], '').verifyChecksum
                    data.append({
                        'label':
                        'ICMP 头部 / Internet Control Message Protocol Headers',
                        'value':
                        '',
                        'bold':
                        True,
                        'children': [{
                            'label':
                            '类型',
                            'value':
                            '%s (%s)' % (self.ipBody.icmpHeader.type,
                                         self.ipBody.icmpHeader.type_name)
                        }, {
                            'label': '代码',
                            'value': self.ipBody.icmpHeader.code
                        }, {
                            'label':
                            '校验和',
                            'value':
                            '0x%s (%s)' %
                            (self.ipBody.icmpHeader.checksum, '校验' + {
                                True: '通过',
                                False: '失败'
                            }[self.ipBody.icmpHeader.verifyChecksum])
                        }]
                    })

                elif 'IGMP' in self.ipHeader.protocol:
                    if self.ipHeader.payload_length == 8:
                        self.ipBody.igmpHeader.verifyChecksum = verifyChecksum(
                            self.ipBody.parameters, [], '').verifyChecksum
                        data.append({
                            'label':
                            'IGMP 头部 / Internet Group Management Protocol Headers',
                            'value':
                            '',
                            'bold':
                            True,
                            'children': [{
                                'label':
                                '类型',
                                'value':
                                '0x%s(%s)' % (self.ipBody.igmpHeader.type,
                                              self.ipBody.igmpHeader.type_name)
                            }, {
                                'label':
                                '最大响应时延',
                                'value':
                                '%s 秒(0x%s)' %
                                (self.ipBody.igmpHeader.maxRespTime,
                                 self.ipBody.igmpHeader.maxRespTimeHex)
                            }, {
                                'label':
                                '校验和',
                                'value':
                                '0x%s(%s)' %
                                (self.ipBody.igmpHeader.checksum, '校验' + {
                                    True: '通过',
                                    False: '失败'
                                }[self.ipBody.igmpHeader.verifyChecksum])
                            }, {
                                'label':
                                '组地址',
                                'value':
                                self.ipBody.igmpHeader.groupAddress
                            }]
                        })
                    else:
                        self.ipBody.igmpv3Header.verifyChecksum = verifyChecksum(
                            self.ipBody.parameters, [], '').verifyChecksum
                        data.append({
                            'label':
                            'IGMPv3 头部 / Internet Group Management Protocol Version 3 Headers',
                            'value':
                            '',
                            'bold':
                            True,
                            'children': [{
                                'label':
                                '类型',
                                'value':
                                '0x%s' % self.ipBody.igmpv3Header.type
                            }, {
                                'label':
                                '校验和',
                                'value':
                                '0x%s(%s)' %
                                (self.ipBody.igmpv3Header.checksum, '校验' + {
                                    True: '通过',
                                    False: '失败'
                                }[self.ipBody.igmpv3Header.verifyChecksum])
                            }]
                        })

        return data