// Helper for parameters in key-value pair lists that should only appear // once. Either replaces an existing entry or adds a new entry. static void ReplaceOrInsertKeyValuePair(KeyValuePairs& kvp, const std::string& key, const std::string& value) { assert(kvp.count(key) <= 1); KeyValuePairs::iterator it = kvp.find(key); if (it != kvp.end()) it->second = value; else kvp.insert(KeyValuePairs::value_type(key, value)); }
std::string Client::buildOAuthParameterString( ParameterStringType string_type, const Http::RequestType eType, const std::string& rawUrl, const std::string& rawData, const bool includeOAuthVerifierPin) { KeyValuePairs rawKeyValuePairs; std::string rawParams; std::string oauthSignature; std::string paramsSeperator; std::string pureUrl( rawUrl ); std::string separator; bool do_urlencode; if (string_type == AuthorizationHeaderString) { separator = ","; do_urlencode = false; } else { /*if (string_type == QueryStringString)*/ separator = "&"; do_urlencode = true; } /* Clear header string initially */ rawKeyValuePairs.clear(); /* If URL itself contains ?key=value, then extract and put them in map */ size_t nPos = rawUrl.find_first_of( "?" ); if( std::string::npos != nPos ) { /* Get only URL */ pureUrl = rawUrl.substr( 0, nPos ); /* Get only key=value data part */ std::string dataPart = rawUrl.substr( nPos + 1 ); rawKeyValuePairs = ParseKeyValuePairs(dataPart); } // We always request URL encoding on the first pass so that the // signature generation works properly. This *relies* on // buildOAuthTokenKeyValuePairs overwriting values when we do the second // pass to get the values in the form we actually want. The signature and // rawdata are the only things that change, but the signature is only used // in the second pass and the rawdata is already encoded, regardless of // request type. /* Build key-value pairs needed for OAuth request token, without signature */ buildOAuthTokenKeyValuePairs( includeOAuthVerifierPin, rawData, std::string( "" ), rawKeyValuePairs, true, true ); /* Get url encoded base64 signature using request type, url and parameters */ getSignature( eType, pureUrl, rawKeyValuePairs, oauthSignature ); /* Now, again build key-value pairs with signature this time */ buildOAuthTokenKeyValuePairs( includeOAuthVerifierPin, std::string( "" ), oauthSignature, rawKeyValuePairs, do_urlencode, false ); /* Get OAuth header in string format. If we're getting the Authorization * header, we need to filter out other parameters. */ if (string_type == AuthorizationHeaderString) { KeyValuePairs oauthKeyValuePairs; std::vector<std::string> oauth_keys; oauth_keys.push_back(Defaults::CONSUMERKEY_KEY); oauth_keys.push_back(Defaults::NONCE_KEY); oauth_keys.push_back(Defaults::SIGNATURE_KEY); oauth_keys.push_back(Defaults::SIGNATUREMETHOD_KEY); oauth_keys.push_back(Defaults::TIMESTAMP_KEY); oauth_keys.push_back(Defaults::TOKEN_KEY); oauth_keys.push_back(Defaults::VERIFIER_KEY); oauth_keys.push_back(Defaults::VERSION_KEY); for(size_t i = 0; i < oauth_keys.size(); i++) { assert(rawKeyValuePairs.count(oauth_keys[i]) <= 1); KeyValuePairs::iterator oauth_key_it = rawKeyValuePairs.find(oauth_keys[i]); if (oauth_key_it != rawKeyValuePairs.end()) ReplaceOrInsertKeyValuePair(oauthKeyValuePairs, oauth_keys[i], oauth_key_it->second); } getStringFromOAuthKeyValuePairs( oauthKeyValuePairs, rawParams, separator ); } else if (string_type == QueryStringString) { getStringFromOAuthKeyValuePairs( rawKeyValuePairs, rawParams, separator ); } /* Build authorization header */ return rawParams; }