1""" 
    2oauthlib.parameters 
    3~~~~~~~~~~~~~~~~~~~ 
    4 
    5This module contains methods related to `section 3.5`_ of the OAuth 1.0a spec. 
    6 
    7.. _`section 3.5`: https://tools.ietf.org/html/rfc5849#section-3.5 
    8""" 
    9from urllib.parse import urlparse, urlunparse 
    10 
    11from oauthlib.common import extract_params, urlencode 
    12 
    13from . import utils 
    14 
    15 
    16# TODO: do we need filter_params now that oauth_params are handled by Request? 
    17#       We can easily pass in just oauth protocol params. 
    18@utils.filter_params 
    19def prepare_headers(oauth_params, headers=None, realm=None): 
    20    """**Prepare the Authorization header.** 
    21    Per `section 3.5.1`_ of the spec. 
    22 
    23    Protocol parameters can be transmitted using the HTTP "Authorization" 
    24    header field as defined by `RFC2617`_ with the auth-scheme name set to 
    25    "OAuth" (case insensitive). 
    26 
    27    For example:: 
    28 
    29        Authorization: OAuth realm="Example", 
    30            oauth_consumer_key="0685bd9184jfhq22", 
    31            oauth_token="ad180jjd733klru7", 
    32            oauth_signature_method="HMAC-SHA1", 
    33            oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", 
    34            oauth_timestamp="137131200", 
    35            oauth_nonce="4572616e48616d6d65724c61686176", 
    36            oauth_version="1.0" 
    37 
    38 
    39    .. _`section 3.5.1`: https://tools.ietf.org/html/rfc5849#section-3.5.1 
    40    .. _`RFC2617`: https://tools.ietf.org/html/rfc2617 
    41    """ 
    42    headers = headers or {} 
    43 
    44    # Protocol parameters SHALL be included in the "Authorization" header 
    45    # field as follows: 
    46    authorization_header_parameters_parts = [] 
    47    for oauth_parameter_name, value in oauth_params: 
    48        # 1.  Parameter names and values are encoded per Parameter Encoding 
    49        #     (`Section 3.6`_) 
    50        # 
    51        # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6 
    52        escaped_name = utils.escape(oauth_parameter_name) 
    53        escaped_value = utils.escape(value) 
    54 
    55        # 2.  Each parameter's name is immediately followed by an "=" character 
    56        #     (ASCII code 61), a """ character (ASCII code 34), the parameter 
    57        #     value (MAY be empty), and another """ character (ASCII code 34). 
    58        part = '{}="{}"'.format(escaped_name, escaped_value) 
    59 
    60        authorization_header_parameters_parts.append(part) 
    61 
    62    # 3.  Parameters are separated by a "," character (ASCII code 44) and 
    63    #     OPTIONAL linear whitespace per `RFC2617`_. 
    64    # 
    65    # .. _`RFC2617`: https://tools.ietf.org/html/rfc2617 
    66    authorization_header_parameters = ', '.join( 
    67        authorization_header_parameters_parts) 
    68 
    69    # 4.  The OPTIONAL "realm" parameter MAY be added and interpreted per 
    70    #     `RFC2617 section 1.2`_. 
    71    # 
    72    # .. _`RFC2617 section 1.2`: https://tools.ietf.org/html/rfc2617#section-1.2 
    73    if realm: 
    74        # NOTE: realm should *not* be escaped 
    75        authorization_header_parameters = ('realm="%s", ' % realm + 
    76                                           authorization_header_parameters) 
    77 
    78    # the auth-scheme name set to "OAuth" (case insensitive). 
    79    authorization_header = 'OAuth %s' % authorization_header_parameters 
    80 
    81    # contribute the Authorization header to the given headers 
    82    full_headers = {} 
    83    full_headers.update(headers) 
    84    full_headers['Authorization'] = authorization_header 
    85    return full_headers 
    86 
    87 
    88def _append_params(oauth_params, params): 
    89    """Append OAuth params to an existing set of parameters. 
    90 
    91    Both params and oauth_params is must be lists of 2-tuples. 
    92 
    93    Per `section 3.5.2`_ and `3.5.3`_ of the spec. 
    94 
    95    .. _`section 3.5.2`: https://tools.ietf.org/html/rfc5849#section-3.5.2 
    96    .. _`3.5.3`: https://tools.ietf.org/html/rfc5849#section-3.5.3 
    97 
    98    """ 
    99    merged = list(params) 
    100    merged.extend(oauth_params) 
    101    # The request URI / entity-body MAY include other request-specific 
    102    # parameters, in which case, the protocol parameters SHOULD be appended 
    103    # following the request-specific parameters, properly separated by an "&" 
    104    # character (ASCII code 38) 
    105    merged.sort(key=lambda i: i[0].startswith('oauth_')) 
    106    return merged 
    107 
    108 
    109def prepare_form_encoded_body(oauth_params, body): 
    110    """Prepare the Form-Encoded Body. 
    111 
    112    Per `section 3.5.2`_ of the spec. 
    113 
    114    .. _`section 3.5.2`: https://tools.ietf.org/html/rfc5849#section-3.5.2 
    115 
    116    """ 
    117    # append OAuth params to the existing body 
    118    return _append_params(oauth_params, body) 
    119 
    120 
    121def prepare_request_uri_query(oauth_params, uri): 
    122    """Prepare the Request URI Query. 
    123 
    124    Per `section 3.5.3`_ of the spec. 
    125 
    126    .. _`section 3.5.3`: https://tools.ietf.org/html/rfc5849#section-3.5.3 
    127 
    128    """ 
    129    # append OAuth params to the existing set of query components 
    130    sch, net, path, par, query, fra = urlparse(uri) 
    131    query = urlencode( 
    132        _append_params(oauth_params, extract_params(query) or [])) 
    133    return urlunparse((sch, net, path, par, query, fra))