def test_returns_bytes_and_None_unchanged_and_converts_unicode(self):
     assert_equal(unicode_to_utf8(unicode_string), utf8_bytes)
     assert_equal(unicode_to_utf8(None), None)
     assert_equal(unicode_to_utf8(utf8_bytes), utf8_bytes)
     assert_raises(AssertionError, unicode_to_utf8, 5)
     assert_raises(AssertionError, unicode_to_utf8, False)
     assert_raises(AssertionError, unicode_to_utf8, True)
     assert_raises(AssertionError, unicode_to_utf8, [])
     assert_raises(AssertionError, unicode_to_utf8, ())
     assert_raises(AssertionError, unicode_to_utf8, {})
     assert_raises(AssertionError, unicode_to_utf8, object)
Пример #2
0
def generate_normalized_authorization_header_value(oauth_params,
                                              realm=None,
                                              param_delimiter=","):
    """
    Builds the Authorization header value.

    Please note that the generated authorization header value MUST be
    on a SINGLE line.

    :see: Authorization Header http://tools.ietf.org/html/rfc5849#section-3.5.1
    :param oauth_params:
        Protocol-specific parameters excluding the ``realm`` parameter.
    :param realm:
        If specified, the realm is included into the Authorization header.
        The realm is never percent-encoded according to the OAuth spec.
    :param param_delimiter:
        The delimiter used to separate header value parameters.
        According to the Specification, this must be a comma ",". However,
        certain services like Yahoo! use "&" instead. Comma is default.

        See https://github.com/oauth/oauth-ruby/pull/12
    :returns:
        A properly formatted Authorization header value.
    """
    if realm:
        s = 'OAuth realm="' + unicode_to_utf8(realm) + '"' + param_delimiter
    else:
        s = 'OAuth '
    oauth_params = request_protocol_params_sanitize(oauth_params)
    normalized_param_pairs = urlencode_sl(oauth_params)
    s += param_delimiter.join([k + '="' + v + '"' for k, v in normalized_param_pairs])
    return s
Пример #3
0
def percent_decode(value):
    """
    Percent-decodes according to the OAuth spec.

    :see: Percent Encoding (http://tools.ietf.org/html/rfc5849#section-3.6)
    :param value:
        Value to percent-decode. Value will be UTF-8 encoded if
        it is a Unicode string. '+' is treated as a ' ' character.
    :returns:
        Percent-decoded value.
    """
    return unquote_plus(unicode_to_utf8(value))
Пример #4
0
def urlencode_sl(query_params, allow_func=None):
    """
    Serializes a dictionary of query parameters into a list of query
    parameters, ``(name, value)`` pairs, sorted first by ``name`` then by
    ``value`` based on the OAuth percent-encoding rules and specification.

    Behaves like :func:`urllib.urlencode` with ``doseq=1``.

    :param query_params:
        Dictionary of query parameters.
    :param allow_func:
        A callback that will be called for each query parameter and should
        return ``False`` or a falsy value if that parameter should not be
        included. By default, all query parameters are included. The function
        takes the following method signature::

            def allow_func(name, value):
                return is_name_allowed(name) and is_value_allowed(value)
    :returns:
        A list of query parameters, ``(name, value)`` pairs, sorted first by
        ``name`` and then by ``value`` based on the OAuth percent-encoding rules
        and specification.
    """
    query_params = query_params or {}
    encoded_pairs = []
    for k, v in query_params.items():
        # Keys are also percent-encoded according to OAuth spec.
        k = percent_encode(unicode_to_utf8(k))
        if allow_func and not allow_func(k, v):
            continue
        elif is_bytes_or_unicode(v):
            encoded_pairs.append((k, percent_encode(v),))
        else:
            if is_sequence(v):
                # Loop over the sequence.
                if len(v) > 0:
                    for i in v:
                        encoded_pairs.append((k, percent_encode(i), ))
                # ``urllib.urlencode()`` doesn't preserve blank lists.
                # Therefore, we're discarding them.
                #else:
                #    # Preserve blank list values.
                #    encoded_pairs.append((k, "", ))
            else:
                encoded_pairs.append((k, percent_encode(v),))
    # Sort after encoding according to the OAuth spec.
    return sorted(encoded_pairs)
Пример #5
0
def _parse_authorization_header_value_l(header_value, param_delimiter=",", strict=True):
    """
    Parses the OAuth Authorization header preserving the order of the
    parameters as in the header value.

    :see: Authorization Header http://tools.ietf.org/html/rfc5849#section-3.5.1
    :param header_value:
        Header value. Non protocol parameters will be ignored.
    :param param_delimiter:
        The delimiter used to separate header value parameters.
        According to the Specification, this must be a comma ",". However,
        certain services like Yahoo! use "&" instead. Comma is default.

        If you want to use another delimiter character, the ``strict``
        argument to this function must also be set to ``False``.
        See https://github.com/oauth/oauth-ruby/pull/12
    :param strict:
        When ``True`` (default), strict checking will be performed.
        The authorization header value must be on a single line.
        The param delimiter MUST be a comma.
        When ``False``, the parser is a bit lenient.
    :returns:
        Tuple:
        (list of parameter name value pairs in order or appearance, realm)

        realm will be ``None`` if the authorization header does not have
        a realm parameter.
    """
    # Remove the auth-scheme from the value.
    header_value = unicode_to_utf8(header_value)
    if strict:
        if "\n" in header_value:
            raise ValueError("Header value must be on a single line: got `%r`" % (header_value, ))
        if param_delimiter != ",":
            raise ValueError("The param delimiter must be a comma: got `%r`" % (param_delimiter, ))

    pattern = re.compile(r"(^OAuth[\s]+)", re.IGNORECASE)
    header_value = re.sub(pattern, "", header_value.strip(), 1)
    realm = None

    pairs = [param_pair.strip()
             for param_pair in header_value.split(param_delimiter)]
    decoded_pairs = []
    for param in pairs:
        if not param:
            if header_value.endswith(param_delimiter):
                raise InvalidAuthorizationHeaderError("Malformed `Authorization` header value -- found trailing `%r` character" % param_delimiter)
            #else:
            #    continue
        nv = param.split("=", 1)
        if len(nv) != 2:
            raise InvalidAuthorizationHeaderError("bad parameter field: `%r`" % (param, ))
        name, value = nv[0].strip(), nv[1].strip()
        if len(value) < 2:
            raise InvalidAuthorizationHeaderError("bad parameter value: `%r` -- missing quotes?" % (param, ))
        if value[0] != '"' or value[-1] != '"':
            raise InvalidAuthorizationHeaderError("missing quotes around parameter value: `%r` -- values must be quoted using (\")" % (param, ))

        # We only need to remove a single pair of quotes. Do not use str.strip('"').
        # We need to be able to detect problems with the values too.
        value = value[1:-1]
        name = percent_decode(name)
        if name.lower() == "realm":
            # "realm" is case-insensitive.
            # The realm parameter value is a simple quoted string.
            # It is neither percent-encoded nor percent-decoded in OAuth.
            # realm is ignored from the protocol parameters list.
            realm = value
        else:
            value = percent_decode(value)
        decoded_pairs.append((name, value))
    return decoded_pairs, realm