예제 #1
0
 def get_encoder(self):
     """
     Returns a HPACK encoder set up for responses.
     """
     e = Encoder()
     e.huffman_coder = HuffmanEncoder(REQUEST_CODES, REQUEST_CODES_LENGTH)
     return e
예제 #2
0
def build_headers_frame(headers, encoder=None):
    f = HeadersFrame(1)
    e = encoder
    if e is None:
        e = Encoder()
        e.huffman_coder = HuffmanEncoder(REQUEST_CODES, REQUEST_CODES_LENGTH)
    f.data = e.encode(headers)
    f.flags.add('END_HEADERS')
    return f
예제 #3
0
 def test_request_huffman_encode(self):
     encoder = HuffmanEncoder(REQUEST_CODES, REQUEST_CODES_LENGTH)
     assert encoder.encode(b"www.example.com") == (
         b'\xf1\xe3\xc2\xe5\xf2:k\xa0\xab\x90\xf4\xff')
     assert encoder.encode(b"no-cache") == (b'\xa8\xeb\x10d\x9c\xbf')
     assert encoder.encode(b"custom-key") == (b'%\xa8I\xe9[\xa9}\x7f')
     assert encoder.encode(b"custom-value") == (
         b'%\xa8I\xe9[\xb8\xe8\xb4\xbf')
예제 #4
0
    def _load_pattern(self, verbose):
        '''
        Get query compressed size pattern.
        '''
        patterns = None
        encoder = HuffmanEncoder(REQUEST_CODES, REQUEST_CODES_LENGTH)

        def __get_patterns(string):
            '''
            Get possible size patterns of a query string.
            Considering counter parameter if any exist.
            '''
            size_sequences = [[] for _ in range(8)]

            # Initial bits number from 1 to 8 (+2 octets)
            init_bytes = [
                b'AA0', b'AAA', b'AAB', b'AAX', b'XX0', b'XXA', b'XXB', b'XXX'
            ]
            query_bytes = b''

            ct = self.website.ct_start

            # Keep track of how far through an octet we are
            for char in string:
                if char == '\'' and self.website.encode_apost:
                    query_bytes += b'%27'
                elif char == ' ' and self.website.encode_space:
                    query_bytes += b'%20'
                else:
                    query_bytes += bytes(char, encoding='utf8')

                if char == '\'':
                    if self.website.ct_type == 'cp':
                        ct += 1
                    continue

                if char == ' ' and self.website.trim_space:
                    if self.website.ct_type == 'cp':
                        ct += 1
                    continue

                if self.website.ct_type == 'no':
                    encode_bytes = query_bytes
                else:
                    ct_bytes = bytes(str(ct), encoding='utf8')
                    encode_bytes = query_bytes + ct_bytes

                for i in range(len(init_bytes)):
                    size_sequences[i].append(
                        len(encoder.encode(init_bytes[i] + encode_bytes)))

                ct += 1

            return [np.diff(x).tolist() for x in size_sequences]

        # Compressed pattern is valid only for HTTP/2 requests without changing bytes
        if self.website.http_version == 2 and self.website.change_byte == 0:
            if verbose:
                print('Loading query patterns')
            if self.chinese:
                patterns = self.__load_matedata('pattern_zh_%s.pkl' %
                                                self.website)
                if patterns is None:
                    tqdm.pandas(desc='pinyin')
                    string = self.queries['query'].progress_apply(
                        lambda x: '\''.join(py.get_pinyin(x).split('-')))
                    tqdm.pandas(desc='patterns')
                    patterns = string.progress_apply(__get_patterns)
                    self.__save_matedata(patterns,
                                         'pattern_zh_%s.pkl' % self.website)
            else:
                patterns = self.__load_matedata('pattern_en_%s.pkl' %
                                                self.website)
                if patterns is None:
                    tqdm.pandas(desc='patterns')
                    patterns = self.queries['query'].progress_apply(
                        __get_patterns)
                    self.__save_matedata(patterns,
                                         'pattern_en_%s.pkl' % self.website)

        elif verbose:
            if self.website.http_version == 1.1:
                print('Compressed pattern is ignored for HTTP/1.1')
            else:
                print(
                    'Compressed pattern is invalid for changing byte parameters'
                )

        return patterns
예제 #5
0
 def test_request_huffman_encode(self):
     encoder = HuffmanEncoder(REQUEST_CODES, REQUEST_CODES_LENGTH)
     assert encoder.encode(b"www.example.com") == (b'\xf1\xe3\xc2\xe5\xf2:k\xa0\xab\x90\xf4\xff')
     assert encoder.encode(b"no-cache") == (b'\xa8\xeb\x10d\x9c\xbf')
     assert encoder.encode(b"custom-key") == (b'%\xa8I\xe9[\xa9}\x7f')
     assert encoder.encode(b"custom-value") == (b'%\xa8I\xe9[\xb8\xe8\xb4\xbf')