def test_decoding(self): self.assertEqual(rfc1924_b85decode(mercurial_encoded), mercurial_bytes) self.assertEqual(rfc1924_b85decode(random_256_mercurial), random_256_bytes) self.assertEqual(rfc1924_b85decode(b('|NsC0')), b('\xff\xff\xff\xff')) for a, e in zip(random_bytes_list, rfc_encoded_bytes_list): self.assertEqual(rfc1924_b85decode(e), a)
def test_query_params_sorted_order(self): self.assertEqual( generate_base_string_query(dict(b=[8, 2, 4], a=1), {}), b("a=1&b=2&b=4&b=8")) qs = generate_base_string_query( dict(a=5, b=6, c=["w", "a", "t", "e", "r"]), {}) self.assertEqual(qs, b("a=5&b=6&c=a&c=e&c=r&c=t&c=w"))
def data_urlparse(data_url): """ Parses a data URL into raw bytes and metadata. :param data_url: The data url string. If a mime-type definition is missing in the metadata, "text/plain;charset=US-ASCII" will be used as default mime-type. :returns: A 2-tuple:: (bytes, mime_type) See :func:`mom.http.mimeparse.parse_mime_type` for what ``mime_type`` looks like. """ if not is_bytes(data_url): raise TypeError( "data URLs must be ASCII-encoded bytes: got %r" % type(data_url).__name__ ) metadata, encoded = data_url.rsplit(b(","), 1) _, metadata = metadata.split(b("data:"), 1) parts = metadata.rsplit(b(";"), 1) if parts[-1] == b("base64"): decode = base64_decode parts = parts[:-1] else: decode = unquote if not parts or not parts[0]: parts = [b("text/plain;charset=US-ASCII")] mime_type = parse_mime_type(parts[0]) raw_bytes = decode(encoded) return raw_bytes, mime_type
def best_match(supported, header): """Return mime-type with the highest quality ('q') from list of candidates. Takes a list of supported mime-types and finds the best match for all the media-ranges listed in header. The value of header must be a string that conforms to the format of the HTTP Accept: header. The value of 'supported' is a list of mime-types. The list of supported mime-types should be sorted in order of increasing desirability, in case of a situation where there is a tie. >>> best_match([b'application/xbel+xml', b'text/xml'], b'text/*;q=0.5,*/*; q=0.1') b'text/xml' """ split_header = _filter_blank(header.split(b(','))) parsed_header = [parse_media_range(r) for r in split_header] weighted_matches = [] pos = 0 for mime_type in supported: weighted_matches.append((fitness_and_quality_parsed(mime_type, parsed_header), pos, mime_type)) pos += 1 weighted_matches.sort() return weighted_matches[-1][0][1] and weighted_matches[-1][2] or b('')
def test_parsing_no_metadata(self): raw_bytes, mime_type = data_urlparse(no_meta_data_url) self.assertEqual(raw_bytes, png) self.assertEqual(mime_type[:2], (b('text'), b('plain'))) self.assertDictEqual(mime_type[2], { b('charset'): b('US-ASCII'), })
def test_overflow_allowed(self): self.assertEqual(uint_to_bytes(0xc0ff, fill_size=1, overflow=True), b('\xc0\xff')) self.assertEqual(uint_to_bytes(123456789, fill_size=3, overflow=True), b('\x07\x5b\xcd\x15')) self.assertEqual(uint_to_bytes(0xf00dc0ffee, fill_size=4, overflow=True), b('\xf0\x0d\xc0\xff\xee'))
def test_when_token_secret_present(self): base_string = generate_base_string( HTTP_POST, b("http://example.com/"), self.oauth_params) self.assertEqual(generate_plaintext_signature( base_string, b(""), self.oauth_token_secret ), b("&token%20test%20secret"))
def test_raises_InvalidHttpRequestError_when_identifier_invalid(self): temporary_credentials = Credentials(identifier=RFC_TEMPORARY_IDENTIFIER, shared_secret=RFC_TEMPORARY_SECRET) self.assertRaises(InvalidHttpRequestError, _OAuthClient.check_verification_code, temporary_credentials, b("non-matching-token"), b("verification-code"))
def test_when_neither_secret_present(self): base_string = generate_base_string( HTTP_POST, b("http://example.com/"), self.oauth_params) self.assertEqual(generate_plaintext_signature( base_string, b(""), None ), b("&"))
def setUp(self): self.oauth_params = dict( oauth_consumer_key=b("9djdj82h48djs9d2"), oauth_token=b("kkk9d7dh3k39sjv7"), oauth_signature_method=SIGNATURE_METHOD_HMAC_SHA1, oauth_timestamp=b("137131201"), oauth_nonce=b("7d8f3e4a"), oauth_signature=b("bYT5CMsGcbgUdFHObYMEfcx6bsw%3D") )
def test_fill_size(self): self.assertEqual(uint_to_bytes(0xc0ff, fill_size=4), b('\x00\x00\xc0\xff')) self.assertEqual(uint_to_bytes(0xc0ffee, fill_size=6), b('\x00\x00\x00\xc0\xff\xee')) self.assertEqual(uint_to_bytes(123456789, fill_size=6), b('\x00\x00\x07[\xcd\x15')) self.assertEqual(uint_to_bytes(123456789, fill_size=7), b('\x00\x00\x00\x07[\xcd\x15'))
def test_raises_InvalidHttpRequestError_when_body_and_GET(self): oauth_params = dict( oauth_blah=b("blah"), ) self.assertRaises(InvalidHttpRequestError, _OAuthClient._build_request, HTTP_GET, FOO_URI, None, b("a=b"), {}, oauth_params, OAUTH_REALM, False)
def test_codec_equivalence(self): # Padding bytes are not preserved (it is acceptable here). random_bytes = b("\x00\xbcE\x9a\xda]") expected_bytes = b("\xbcE\x9a\xda]") self.assertEqual(uint_to_bytes(bytes_to_uint(random_bytes)), expected_bytes) self.assertEqual(uint_to_bytes(bytes_to_uint_naive(random_bytes)), expected_bytes) self.assertEqual(uint_to_bytes(bytes_to_uint_simple(random_bytes)), expected_bytes)
def test_ValueError_when_encoded_length_not_20(self): self.assertRaises(ValueError, ipv6_b85decode, b('=r54lj&NUUO~Hi%c2ym0=')) self.assertRaises(ValueError, ipv6_b85decode, b('=r54lj&NUUO=')) self.assertRaises(ValueError, ipv6_b85decode_naive, b('=r54lj&NUUO~Hi%c2ym0=')) self.assertRaises(ValueError, ipv6_b85decode_naive, b('=r54lj&NUUO='))
def test_get_authentication_url(self): url = self.client.get_authentication_url(self.temporary_credentials, a="something here", b=["another thing", 5], oauth_ignored=b("ignored")) self.assertEqual(url, RFC_AUTHENTICATION_URI + b("?a=something%20here" "&b=5" "&b=another%20thing&oauth_token=") + self.temporary_credentials.identifier)
def test__resource_request_data(self): expected = RequestAdapter( HTTP_GET, RFC_RESOURCE_FULL_URL, b(''), headers = { HEADER_AUTHORIZATION_CAPS: b('''\ OAuth realm="Photos",\ oauth_consumer_key="dpf43f3p2l4k3l03",\ oauth_token="nnch734d00sl2jdk",\ oauth_signature_method="HMAC-SHA1",\ oauth_timestamp="137131202",\ oauth_nonce="chapoH",\ oauth_signature="MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D"'''), } ) auth_credentials = Credentials(RFC_TOKEN_IDENTIFIER, RFC_TOKEN_SECRET) client_credentials = Credentials(RFC_CLIENT_IDENTIFIER, RFC_CLIENT_SECRET) class MockClient(_OAuthClient): @classmethod def generate_timestamp(cls): return RFC_TIMESTAMP_3 @classmethod def generate_nonce(cls): return RFC_NONCE_3 got = MockClient._request( client_credentials, HTTP_GET, RFC_RESOURCE_URI, params={ "file": b("vacation.jpg"), "size": b("original"), }, realm=RFC_REALM, auth_credentials=auth_credentials, oauth_version=None ) self.assertEqual(got.method, expected.method) self.assertEqual(got.url, expected.url) self.assertEqual(got.body, expected.body) expected_headers, expected_realm = parse_authorization_header( expected.headers[HEADER_AUTHORIZATION_CAPS], ) got_headers, got_realm = parse_authorization_header( got.headers[HEADER_AUTHORIZATION_CAPS], ) self.assertDictEqual(got_headers, expected_headers) self.assertEqual(got_realm, expected_realm)
def test_base_string_does_not_contain_oauth_signature(self): # Ensure both are present in the query parameters as well as the URL. oauth_params = { OAUTH_PARAM_REALM: b("example.com"), } oauth_params.update(self.oauth_params) url = b("http://example.com/request?" "oauth_signature=foobar&realm=something") base_string = generate_base_string(HTTP_POST, url, oauth_params) self.assertTrue(b("oauth_signature%3D") not in base_string) self.assertTrue(b("realm%3Dexample.com") not in base_string) self.assertTrue(b("realm%3Dsomething") in base_string)
def test_raises_InvalidAuthorizationHeaderError_when_auth_present(self): oauth_params = dict( oauth_blah=b("blah"), ) self.assertRaises(InvalidAuthorizationHeaderError, _OAuthClient._build_request, HTTP_POST, FOO_URI, None, b("a=b"), { HEADER_AUTHORIZATION_CAPS: b("") }, oauth_params, OAUTH_REALM, False)
def test_zero(self): self.assertEqual(uint_to_bytes(0), b('\x00')) self.assertEqual(uint_to_bytes(0, 4), b('\x00') * 4) self.assertEqual(uint_to_bytes(0, 7), b('\x00') * 7) self.assertEqual(uint_to_bytes(0, chunk_size=1), b('\x00')) self.assertEqual(uint_to_bytes(0, chunk_size=4), b('\x00') * 4) self.assertEqual(uint_to_bytes(0, chunk_size=7), b('\x00') * 7) self.assertEqual(uint_to_bytes_naive(0), b('\x00')) self.assertEqual(uint_to_bytes_naive(0, 4), b('\x00') * 4) self.assertEqual(uint_to_bytes_naive(0, 7), b('\x00') * 7) self.assertEqual(uint_to_bytes_simple(0), b('\x00'))
def test_oauth_signature_and_realm_are_excluded_properly(self): qs = generate_base_string_query({ OAUTH_PARAM_SIGNATURE: "something" }, self.specification_example_oauth_params ) self.assertTrue(b("oauth_signature=") not in qs) self.assertTrue(b("realm=") not in qs) self.assertTrue( generate_base_string_query(dict(realm="something"), dict()), b("realm=something") )
def test_no_authentication_url(self): args = dict( temporary_credentials_uri=RFC_TEMP_URI, token_credentials_uri=RFC_TOKEN_URI, authorization_uri=RFC_AUTHORIZATION_URI, authentication_uri=None, use_authorization_header=True ) client = Client(None, self.client_credentials, **args) self.assertRaises(NotImplementedError, client.get_authentication_url, self.temporary_credentials, a=b("something here"), b=[b("another thing"), 5], oauth_ignored=b("ignored"))
def test_param_delimiter_can_be_changed(self): params = { OAUTH_PARAM_REALM: ['Examp%20le'], OAUTH_PARAM_NONCE: ['4572616e48616d6d65724c61686176'], OAUTH_PARAM_TIMESTAMP: ['137131200'], OAUTH_PARAM_CONSUMER_KEY: ['0685bd9184jfhq22'], 'oauth_something': [' Some Example'], OAUTH_PARAM_SIGNATURE_METHOD: ['HMAC-SHA1'], OAUTH_PARAM_VERSION: [OAUTH_VERSION_1], OAUTH_PARAM_TOKEN: ['ad180jjd733klru7'], 'oauth_empty': [''], OAUTH_PARAM_SIGNATURE: ['wOJIO9A2W5mFwDgiDvZbTSMK/PY='], } expected_value = b('''OAuth \ realm="http://example.com/"\ &oauth_consumer_key="0685bd9184jfhq22"\ &oauth_empty=""\ &oauth_nonce="4572616e48616d6d65724c61686176"\ &oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D"\ &oauth_signature_method="HMAC-SHA1"\ &oauth_something="%20Some%20Example"\ &oauth_timestamp="137131200"\ &oauth_token="ad180jjd733klru7"\ &oauth_version="1.0"''') self.assertEqual(generate_authorization_header(params, realm="http://example.com/", param_delimiter="&") , expected_value)
def test_ignores_body_params_if_content_type_is_not_urlencoded(self): oauth_params = dict( oauth_consumer_key=RFC_CLIENT_IDENTIFIER, oauth_token=RFC_TOKEN_IDENTIFIER, oauth_signature_method=SIGNATURE_METHOD_HMAC_SHA1, oauth_timestamp=RFC_TIMESTAMP_3, oauth_nonce=RFC_NONCE_3, ) self.assertEqual(_OAuthClient._generate_signature( HTTP_GET, # I Know ^ is a GET request and we're specifying a body in this # test. _generate_signature does not validate HTTP methods, # but only generates signatures. This example must produce # the same signature as in the RFC example, hence the test. RFC_RESOURCE_FULL_URL, params=None, body=b(""" body { font-family: "Lucida Grande", serif; } a:link { text-decoration: none; } """), headers={ HEADER_CONTENT_TYPE: CONTENT_TYPE_TEXT_CSS, }, oauth_consumer_secret=RFC_CLIENT_SECRET, oauth_token_secret=RFC_TOKEN_SECRET, oauth_params=oauth_params, ), utf8_encode(percent_decode(RFC_RESOURCE_REQUEST_SIGNATURE_ENCODED)))
def test_identity(self): zero_bytes = b('\x00\x00\x00\x00\x00') self.assertEqual(b85decode(b85encode(zero_bytes)), zero_bytes) self.assertEqual(b85decode(b85encode(random_256_bytes)), random_256_bytes) self.assertEqual(b85decode(b85encode(random_odd_bytes)), random_odd_bytes)
def test_valid_query_string(self): params = { "a2": "r b", "b5": "=%3D", "a3": ["a", "2 q"], "c@": [""], "c2": "", OAUTH_PARAM_CONSUMER_KEY: "9djdj82h48djs9d2", OAUTH_PARAM_TOKEN: "kkk9d7dh3k39sjv7", OAUTH_PARAM_SIGNATURE_METHOD: "HMAC-SHA1", OAUTH_PARAM_TIMESTAMP: ["137131201"], OAUTH_PARAM_NONCE: "7d8f3e4a", } valid_query_string = b("""\ a2=r%20b\ &a3=2%20q\ &a3=a\ &b5=%3D%253D\ &c%40=\ &c2=\ &oauth_consumer_key=9djdj82h48djs9d2\ &oauth_nonce=7d8f3e4a\ &oauth_signature_method=HMAC-SHA1\ &oauth_timestamp=137131201\ &oauth_token=kkk9d7dh3k39sjv7""") self.assertEqual(urlencode_s(params), valid_query_string)
def test_param_delimiter_can_be_changed(self): expected_value = ({ OAUTH_PARAM_NONCE: ['4572616e48616d6d65724c61686176'], OAUTH_PARAM_TIMESTAMP: ['137131200'], OAUTH_PARAM_CONSUMER_KEY: ['0685bd9184jfhq22'], 'oauth_something': [' Some Example'], OAUTH_PARAM_SIGNATURE_METHOD: ['HMAC-SHA1'], OAUTH_PARAM_VERSION: [utf8_decode(OAUTH_VERSION_1)], OAUTH_PARAM_TOKEN: ['ad180jjd733klru7'], 'oauth_empty': [''], OAUTH_PARAM_SIGNATURE: ['wOJIO9A2W5mFwDgiDvZbTSMK/PY='], }, 'Examp%20le' ) self.assertEqual(expected_value, parse_authorization_header(b('''\ OAuth\ \ realm="Examp%20le"&\ oauth_consumer_key="0685bd9184jfhq22"&\ oauth_token="ad180jjd733klru7"&\ oauth_signature_method="HMAC-SHA1"&\ oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D"&\ oauth_timestamp="137131200"&\ oauth_nonce="4572616e48616d6d65724c61686176"&\ oauth_version="1.0"&\ oauth_something="%20Some+Example"&\ oauth_empty=""\ '''), param_delimiter="&", strict=False), "parsing failed.")
def test_leading(self): self.assertEqual(bytes_leading(b('\x00\x00\x00\x00')), 4) self.assertEqual(bytes_leading(b('\x00\x00\x00')), 3) self.assertEqual(bytes_leading(b('\x00\x00\xff')), 2) self.assertEqual(bytes_leading(b('\xff')), 0) self.assertEqual(bytes_leading(b('\x00\xff')), 1) self.assertEqual(bytes_leading(b('\x00')), 1) self.assertEqual(bytes_leading(b('\x00\x00\x00\xff')), 3) self.assertEqual(bytes_leading(b('')), 0)
def test__request_data(self): expected = RequestAdapter( HTTP_POST, RFC_TEMP_URI, b(''), headers = { HEADER_AUTHORIZATION_CAPS: b('''\ OAuth realm="Photos",\ oauth_consumer_key="dpf43f3p2l4k3l03",\ oauth_signature_method="HMAC-SHA1",\ oauth_timestamp="137131200",\ oauth_nonce="wIjqoS",\ oauth_callback="http%3A%2F%2Fprinter.example.com%2Fready",\ oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D"'''), } ) client_credentials = Credentials(RFC_CLIENT_IDENTIFIER, RFC_CLIENT_SECRET) class MockClient(_OAuthClient): @classmethod def generate_timestamp(cls): return RFC_TIMESTAMP_1 @classmethod def generate_nonce(cls): return RFC_NONCE_1 got = MockClient._request( client_credentials, HTTP_POST, RFC_TEMP_URI, realm=RFC_REALM, oauth_version=None, oauth_callback=RFC_OAUTH_CALLBACK_URI ) self.assertEqual(got.method, expected.method) self.assertEqual(got.url, expected.url) self.assertEqual(got.body, expected.body) expected_headers, expected_realm = parse_authorization_header( expected.headers[HEADER_AUTHORIZATION_CAPS], ) got_headers, got_realm = parse_authorization_header( got.headers[HEADER_AUTHORIZATION_CAPS], ) self.assertDictEqual(got_headers, expected_headers) self.assertEqual(got_realm, expected_realm)
def test_parsing(self): raw_bytes, mime_type = data_urlparse(sample_data_url) self.assertEqual(raw_bytes, png) self.assertEqual(mime_type[:2], (b('text'), b('css'))) self.assertDictEqual(mime_type[2], { b('charset'): b('utf-8'), }) raw_bytes, mime_type = data_urlparse(rfc_note_data_url) self.assertEqual(raw_bytes, b('A brief note')) self.assertEqual(mime_type[:2], (b('text'), b('plain'))) self.assertDictEqual(mime_type[2], { b('charset'): b('US-ASCII'), })
def test_sanitization_force_secure(self): insecure_url = b("http://www.EXAMPLE.com/request") secure_url = b("https://www.EXAMPLE.com/request") self.assertRaises(InsecureOAuthUrlError, oauth_url_sanitize, insecure_url) self.assertRaises(InsecureOAuthUrlError, oauth_url_sanitize, insecure_url, True) self.assertEqual( oauth_url_sanitize(insecure_url, force_secure=False), b("http://www.example.com/request")) self.assertEqual( oauth_url_sanitize(secure_url, force_secure=False), b("https://www.example.com/request")) self.assertEqual( oauth_url_sanitize(secure_url, force_secure=True), b("https://www.example.com/request"))
# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import absolute_import from mom.builtins import b __author__ = "[email protected] (Yesudeep Mangalapilly)" UNICODE_STRING = "\u00ae" UNICODE_STRING2 = "深入 Python" FOO = b("foo") UFOO = "foo" JSON_FOO = b("\"foo\"") JSON_UFOO = "\"foo\"" JSON_UNICODE_VALUE = "\"\u00e9\"" UNICODE_VALUE = "\u00e9" X_BYTE = b("\xe9") UTF8_BYTES = b("\xc2\xae") UTF8_BYTES2 = b("\xe6\xb7\xb1\xe5\x85\xa5 Python") LATIN1_BYTES = b("\xe9")