Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
oauth.cpp
00001 /* 00002 * OAuth string functions in POSIX-C. 00003 * 00004 * Copyright 2007-2010 Robin Gareus <robin@gareus.org> 00005 * 00006 * The base64 functions are by Jan-Henrik Haukeland, <hauk@tildeslash.com> 00007 * and un/escape_url() was inspired by libcurl's curl_escape under ISC-license 00008 * many thanks to Daniel Stenberg <daniel@haxx.se>. 00009 * 00010 * Permission is hereby granted, free of charge, to any person obtaining a copy 00011 * of this software and associated documentation files (the "Software"), to deal 00012 * in the Software without restriction, including without limitation the rights 00013 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00014 * copies of the Software, and to permit persons to whom the Software is 00015 * furnished to do so, subject to the following conditions: 00016 * 00017 * The above copyright notice and this permission notice shall be included in 00018 * all copies or substantial portions of the Software. 00019 * 00020 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00021 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00022 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00023 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00024 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00025 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00026 * THE SOFTWARE. 00027 * 00028 */ 00029 #if HAVE_CONFIG_H 00030 # include <config.h> 00031 #endif 00032 00033 #define WIPE_MEMORY ///< overwrite sensitve data before free()ing it. 00034 00035 #include <stdio.h> 00036 #include <stdarg.h> 00037 #include <stdlib.h> 00038 #include <string.h> 00039 #include <time.h> 00040 #include <math.h> 00041 #include <ctype.h> // isxdigit 00042 00043 #include "oauth.h" 00044 00045 #include <vector> 00046 #include <algorithm> 00047 #include <sstream> 00048 00049 /** 00050 * Base64 encode one byte 00051 */ 00052 char oauth_b64_encode(unsigned char u) 00053 { 00054 if (u < 26) return 'A' + u; 00055 if (u < 52) return 'a' + (u - 26); 00056 if (u < 62) return '0' + (u - 52); 00057 if (u == 62) return '+'; 00058 return '/'; 00059 } 00060 00061 /** 00062 * Decode a single base64 character. 00063 */ 00064 unsigned char oauth_b64_decode(char c) 00065 { 00066 if (c >= 'A' && c <= 'Z') return(c - 'A'); 00067 if (c >= 'a' && c <= 'z') return(c - 'a' + 26); 00068 if (c >= '0' && c <= '9') return(c - '0' + 52); 00069 if (c == '+') return 62; 00070 return 63; 00071 } 00072 00073 /** 00074 * Return TRUE if 'c' is a valid base64 character, otherwise FALSE 00075 */ 00076 bool oauth_b64_is_base64(char c) 00077 { 00078 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '+') || (c == '/') || (c == '=')); 00079 } 00080 00081 /** 00082 * Base64 encode and return size data in 'src'. The caller must free the 00083 * returned string. 00084 * 00085 * @param size The size of the data in src 00086 * @param src The data to be base64 encode 00087 * @return encoded string otherwise NULL 00088 */ 00089 std::string oauth_encode_base64(const unsigned char *src, int size) 00090 { 00091 int i; 00092 std::stringbuf sb; 00093 00094 if (!src) return NULL; 00095 if (!size) size= strlen((char *)src); 00096 00097 for (i = 0; i < size; i += 3) { 00098 unsigned char b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0; 00099 b1= src[i]; 00100 if (i + 1 < size) b2 = src[i + 1]; 00101 if (i + 2 < size) b3 = src[i + 2]; 00102 00103 b4= b1 >> 2; 00104 b5= ((b1 & 0x3) << 4) | (b2 >> 4); 00105 b6= ((b2 & 0xf) << 2) | (b3 >> 6); 00106 b7= b3 & 0x3f; 00107 00108 sb.sputc(oauth_b64_encode(b4)); 00109 sb.sputc(oauth_b64_encode(b5)); 00110 00111 if (i + 1 < size) { 00112 sb.sputc(oauth_b64_encode(b6)); 00113 } else { 00114 sb.sputc('='); 00115 } 00116 00117 if (i + 2 < size) { 00118 sb.sputc(oauth_b64_encode(b7)); 00119 } else { 00120 sb.sputc('='); 00121 } 00122 } 00123 return sb.str(); 00124 } 00125 00126 /** 00127 * Decode the base64 encoded string 'src' into the memory pointed to by 00128 * 'dest'. 00129 * 00130 * @param dest Pointer to memory for holding the decoded string. 00131 * Must be large enough to receive the decoded string. 00132 * @param src A base64 encoded string. 00133 * @return the length of the decoded string if decode 00134 * succeeded otherwise 0. 00135 */ 00136 std::string oauth_decode_base64(const char *src) 00137 { 00138 if (src && *src) { 00139 std::stringbuf sb; 00140 //unsigned char *p= dest; 00141 int k, l= strlen(src)+1; 00142 std::vector<unsigned char> buf(l); 00143 00144 /* Ignore non base64 chars as per the POSIX standard */ 00145 for (k = 0, l = 0; src[k]; k++) { 00146 if (oauth_b64_is_base64(src[k])) { 00147 buf[l++]= src[k]; 00148 } 00149 } 00150 00151 for (k = 0; k < l; k += 4) { 00152 char c1='A', c2='A', c3='A', c4='A'; 00153 unsigned char b1 = 0, b2 = 0, b3 = 0, b4 = 0; 00154 c1= buf[k]; 00155 00156 if (k + 1 < l) c2 = buf[k + 1]; 00157 if (k + 2 < l) c3 = buf[k + 2]; 00158 if (k + 3 < l) c4 = buf[k + 3]; 00159 00160 b1 = oauth_b64_decode(c1); 00161 b2 = oauth_b64_decode(c2); 00162 b3 = oauth_b64_decode(c3); 00163 b4 = oauth_b64_decode(c4); 00164 00165 sb.sputc((b1 << 2) | (b2 >> 4)); 00166 00167 if (c3 != '=') sb.sputc(((b2 & 0xf) << 4) | (b3 >> 2)); 00168 if (c4 != '=') sb.sputc(((b3 & 0x3) << 6) | b4); 00169 } 00170 00171 return sb.str(); 00172 } 00173 return 0; 00174 } 00175 00176 /** 00177 * Escape 'string' according to RFC3986 and 00178 * http://oauth.net/core/1.0/#encoding_parameters. 00179 * 00180 * @param string The data to be encoded 00181 * @return encoded string otherwise NULL 00182 * The caller must free the returned string. 00183 */ 00184 std::string oauth_url_escape(const char *string) 00185 { 00186 unsigned char in; 00187 size_t length; 00188 00189 if (!string) { 00190 return std::string(); 00191 } 00192 00193 length = strlen(string); 00194 00195 std::stringbuf sb; 00196 00197 while (length--) { 00198 in = *string; 00199 if (strchr("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_~.-", in)) { 00200 sb.sputc(in); 00201 } else { 00202 char tmp[10]; 00203 snprintf(tmp, 4, "%%%02X", in); 00204 sb.sputc(tmp[0]); 00205 sb.sputc(tmp[1]); 00206 sb.sputc(tmp[2]); 00207 } 00208 string++; 00209 } 00210 return sb.str(); 00211 } 00212 00213 #ifndef ISXDIGIT 00214 # define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) 00215 #endif 00216 00217 /** 00218 * Parse RFC3986 encoded 'string' back to unescaped version. 00219 * 00220 * @param string The data to be unescaped 00221 * @param olen unless NULL the length of the returned string is stored there. 00222 * @return decoded string or NULL 00223 * The caller must free the returned string. 00224 */ 00225 std::string oauth_url_unescape(const char *string) 00226 { 00227 size_t alloc, strindex=0; 00228 unsigned char in; 00229 long hex; 00230 00231 if (!string) return NULL; 00232 00233 alloc = strlen(string)+1; 00234 std::vector<char> ns(alloc); 00235 00236 while(--alloc > 0) { 00237 in = *string; 00238 if (('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { 00239 char hexstr[3]; // '%XX' 00240 hexstr[0] = string[1]; 00241 hexstr[1] = string[2]; 00242 hexstr[2] = 0; 00243 hex = strtol(hexstr, NULL, 16); 00244 in = (unsigned char)hex; /* hex is always < 256 */ 00245 string += 2; 00246 alloc -= 2; 00247 } 00248 ns[strindex++] = in; 00249 string++; 00250 } 00251 ns[strindex]=0; 00252 return &ns[0]; 00253 } 00254 00255 /** 00256 * returns plaintext signature for the given key. 00257 * 00258 * the returned string needs to be freed by the caller 00259 * 00260 * @param m message to be signed 00261 * @param k key used for signing 00262 * @return signature string 00263 */ 00264 std::string oauth_sign_plaintext (const char *m, const char *k) 00265 { 00266 return oauth_url_escape(k); 00267 } 00268 00269 /** 00270 * encode strings and concatenate with '&' separator. 00271 * The number of strings to be concatenated must be 00272 * given as first argument. 00273 * all arguments thereafter must be of type (char *) 00274 * 00275 * @param len the number of arguments to follow this parameter 00276 * @param ... string to escape and added (may be NULL) 00277 * 00278 * @return pointer to memory holding the concatenated 00279 * strings - needs to be free(d) by the caller. or NULL 00280 * in case we ran out of memory. 00281 */ 00282 std::string oauth_catenc(int len, ...) 00283 { 00284 va_list va; 00285 std::string str; 00286 va_start(va, len); 00287 for (int i = 0; i < len; i++) { 00288 char *arg = va_arg(va, char *); 00289 std::string enc = oauth_url_escape(arg); 00290 if (i > 0) str += "&"; 00291 str += enc; 00292 } 00293 va_end(va); 00294 return str; 00295 } 00296 00297 /** 00298 * splits the given url into a parameter array. 00299 * (see \ref oauth_serialize_url and \ref oauth_serialize_url_parameters for the reverse) 00300 * 00301 * NOTE: Request-parameters-values may include an ampersand character. 00302 * However if unescaped this function will use them as parameter delimiter. 00303 * If you need to make such a request, this function since version 0.3.5 allows 00304 * to use the ASCII SOH (0x01) character as alias for '&' (0x26). 00305 * (the motivation is convenience: SOH is /untypeable/ and much more 00306 * unlikely to appear than '&' - If you plan to sign fancy URLs you 00307 * should not split a query-string, but rather provide the parameter array 00308 * directly to \ref oauth_serialize_url) 00309 * 00310 * @param url the url or query-string to parse. 00311 * @param argv pointer to a (char *) array where the results are stored. 00312 * The array is re-allocated to match the number of parameters and each 00313 * parameter-string is allocated with strdup. - The memory needs to be freed 00314 * by the caller. 00315 * @param qesc use query parameter escape (vs post-param-escape) - if set 00316 * to 1 all '+' are treated as spaces ' ' 00317 * 00318 * @return number of parameter(s) in array. 00319 */ 00320 void oauth_split_post_paramters(const char *url, std::vector<std::string> *argv, short qesc) 00321 { 00322 int argc=0; 00323 char *token, *tmp; 00324 if (!argv) return; 00325 if (!url) return; 00326 std::vector<char> t1(strlen(url) + 1); 00327 strcpy(&t1[0], url); 00328 00329 // '+' represents a space, in a URL query string 00330 while ((qesc&1) && (tmp = strchr(&t1[0],'+'))) *tmp = ' '; 00331 00332 tmp = &t1[0]; 00333 while ((token = strtok(tmp,"&?"))) { 00334 if (!strncasecmp("oauth_signature=", token, 16)) continue; 00335 while (!(qesc & 2) && (tmp = strchr(token, '\001'))) *tmp = '&'; 00336 argv->push_back(oauth_url_unescape(token)); 00337 if (argc == 0 && strstr(token, ":/")) { 00338 // HTTP does not allow empty absolute paths, so the URL 00339 // 'http://example.com' is equivalent to 'http://example.com/' and should 00340 // be treated as such for the purposes of OAuth signing (rfc2616, section 3.2.1) 00341 // see http://groups.google.com/group/oauth/browse_thread/thread/c44b6f061bfd98c?hl=en 00342 char *slash = strstr(token, ":/"); 00343 while (slash && *(++slash) == '/') ; // skip slashes eg /xxx:[\/]*/ 00344 #if 0 00345 // skip possibly unescaped slashes in the userinfo - they're not allowed by RFC2396 but have been seen. 00346 // the hostname/IP may only contain alphanumeric characters - so we're safe there. 00347 if (slash && strchr(slash,'@')) slash=strchr(slash, '@'); 00348 #endif 00349 if (slash && !strchr(slash,'/')) { 00350 #ifdef DEBUG_OAUTH 00351 fprintf(stderr, "\nliboauth: added trailing slash to URL: '%s'\n\n", token); 00352 #endif 00353 argv->push_back(std::string(token) + "/"); 00354 } 00355 } 00356 if (argc == 0 && (tmp = strstr((char *)argv->at(argc).c_str(), ":80/"))) { 00357 memmove(tmp, tmp + 3, strlen(tmp + 2)); 00358 } 00359 tmp = NULL; 00360 argc++; 00361 } 00362 } 00363 00364 void oauth_split_url_parameters(const char *url, std::vector<std::string> *argv) 00365 { 00366 oauth_split_post_paramters(url, argv, 1); 00367 } 00368 00369 /** 00370 * build a url query string from an array. 00371 * 00372 * @param argc the total number of elements in the array 00373 * @param start element in the array at which to start concatenating. 00374 * @param argv parameter-array to concatenate. 00375 * @return url string needs to be freed by the caller. 00376 * 00377 */ 00378 std::string oauth_serialize_url (std::vector<std::string> const &argv, int start) 00379 { 00380 return oauth_serialize_url_sep(argv, start, "&", 0); 00381 } 00382 00383 /** 00384 * encode query parameters from an array. 00385 * 00386 * @param argc the total number of elements in the array 00387 * @param start element in the array at which to start concatenating. 00388 * @param argv parameter-array to concatenate. 00389 * @param sep separator for parameters (usually "&") 00390 * @param mod - bitwise modifiers: 00391 * 1: skip all values that start with "oauth_" 00392 * 2: skip all values that don't start with "oauth_" 00393 * 4: add double quotation marks around values (use with sep=", " to generate HTTP Authorization header). 00394 * @return url string needs to be freed by the caller. 00395 */ 00396 std::string oauth_serialize_url_sep(std::vector<std::string> const &argv, int start, char const *sep, int mod) 00397 { 00398 int i; 00399 int first = 0; 00400 int seplen = strlen(sep); 00401 std::string query; 00402 for (i = start; i < (int)argv.size(); i++) { 00403 std::string tmp; 00404 00405 if ((mod & 1) == 1 && (strncmp(argv[i].c_str(), "oauth_", 6) == 0 || strncmp(argv[i].c_str(), "x_oauth_", 8) == 0)) continue; 00406 if ((mod & 2) == 2 && (strncmp(argv[i].c_str(), "oauth_", 6) != 0 && strncmp(argv[i].c_str(), "x_oauth_", 8) != 0) && i != 0) continue; 00407 00408 if (i == start && i == 0 && strstr(argv[i].c_str(), ":/")) { 00409 tmp = argv[i]; 00410 } else { 00411 char *p = strchr((char *)argv[i].c_str(), '='); 00412 if (p) { 00413 tmp = oauth_url_escape(std::string(argv[i].c_str(), (char const *)p).c_str()); 00414 std::string t2 = oauth_url_escape(p + 1); 00415 tmp += "="; 00416 if (mod & 4) tmp += "\""; 00417 tmp += t2; 00418 if (mod & 4) tmp += "\""; 00419 } else { 00420 // see http://oauth.net/core/1.0/#anchor14 00421 // escape parameter names and arguments but not the '=' 00422 tmp=argv[i]; 00423 tmp += "="; 00424 } 00425 } 00426 query += ((i == start || first) ? "" : sep); 00427 query += tmp; 00428 first = 0; 00429 if (i == start && i == 0 && strstr((char *)tmp.c_str(), ":/")) { 00430 query += "?"; 00431 first = 1; 00432 } 00433 } 00434 return (query); 00435 } 00436 00437 /** 00438 * build a query parameter string from an array. 00439 * 00440 * This function is a shortcut for \ref oauth_serialize_url (argc, 1, argv). 00441 * It strips the leading host/path, which is usually the first 00442 * element when using oauth_split_url_parameters on an URL. 00443 * 00444 * @param argc the total number of elements in the array 00445 * @param argv parameter-array to concatenate. 00446 * @return url string needs to be freed by the caller. 00447 */ 00448 std::string oauth_serialize_url_parameters (std::vector<std::string> const &argv) 00449 { 00450 return oauth_serialize_url(argv, 1); 00451 } 00452 00453 /** 00454 * generate a random string between 15 and 32 chars length 00455 * and return a pointer to it. The value needs to be freed by the 00456 * caller 00457 * 00458 * @return zero terminated random string. 00459 */ 00460 std::string oauth_gen_nonce() 00461 { 00462 static const char *chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 00463 const unsigned int max = 26 + 26 + 10 + 1; //strlen(chars); 00464 char tmp[50]; 00465 int i, len; 00466 00467 srand((unsigned int)time(0)); 00468 len = 15 + rand() % 16; 00469 for (i = 0; i < len; i++) { 00470 tmp[i] = chars[rand() % max]; 00471 } 00472 tmp[i]='\0'; 00473 return &tmp[0]; 00474 } 00475 00476 /** 00477 * string compare function for oauth parameters. 00478 * 00479 * used with qsort. needed to normalize request parameters. 00480 * see http://oauth.net/core/1.0/#anchor14 00481 */ 00482 int oauth_cmpstringp(const void *p1, const void *p2) 00483 { 00484 char const *e1; 00485 char const *e2; 00486 e1 = strchr((char *)p1, '='); 00487 e2 = strchr((char *)p2, '='); 00488 if (e1 && e2) { 00489 std::string left((char const *)p1, e1); 00490 std::string right((char const *)p2, e2); 00491 return strcmp(left.c_str(), right.c_str()); 00492 } 00493 00494 std::string left = oauth_url_escape((char const *)p1); 00495 std::string right = oauth_url_escape((char const *)p2); 00496 return strcmp(left.c_str(), right.c_str()); 00497 } 00498 00499 bool oauth_cmpstringp_ex(std::string const &left, std::string const &right) 00500 { 00501 return oauth_cmpstringp(left.c_str(), right.c_str()) < 0; 00502 } 00503 00504 /** 00505 * search array for parameter key. 00506 * @param argv length of array to search 00507 * @param argc parameter array to search 00508 * @param key key of parameter to check. 00509 * 00510 * @return FALSE (0) if array does not contain a parameter with given key, TRUE (1) otherwise. 00511 */ 00512 bool oauth_param_exists(std::vector<std::string> const &argv, char const *key) 00513 { 00514 int i; 00515 size_t l = strlen(key); 00516 for (i = 0; i < (int)argv.size(); i++) { 00517 if (!strncmp(argv[i].c_str(), key, l) && argv[i][l] == '=') { 00518 return true; 00519 } 00520 } 00521 return false; 00522 } 00523 00524 /** 00525 * 00526 */ 00527 void oauth_add_protocol( 00528 std::vector<std::string> *argvp, 00529 OAuthMethod method, 00530 const char *c_key, //< consumer key - posted plain text 00531 const char *t_key //< token key - posted plain text in URL 00532 ) 00533 { 00534 char oarg[1024]; 00535 00536 // add OAuth specific arguments 00537 if (!oauth_param_exists(*argvp,"oauth_nonce")) { 00538 std::string tmp = oauth_gen_nonce(); 00539 snprintf(oarg, 1024, "oauth_nonce=%s", tmp.c_str()); 00540 argvp->push_back(oarg); 00541 } 00542 00543 if (!oauth_param_exists(*argvp,"oauth_timestamp")) { 00544 long t = time(0); 00545 snprintf(oarg, 1024, "oauth_timestamp=%u", t); 00546 argvp->push_back(oarg); 00547 } 00548 00549 if (t_key) { 00550 snprintf(oarg, 1024, "oauth_token=%s", t_key); 00551 argvp->push_back(oarg); 00552 } 00553 00554 snprintf(oarg, 1024, "oauth_consumer_key=%s", c_key); 00555 argvp->push_back(oarg); 00556 00557 snprintf(oarg, 1024, "oauth_signature_method=%s", method==0?"HMAC-SHA1":method==1?"RSA-SHA1":"PLAINTEXT"); 00558 argvp->push_back(oarg); 00559 00560 if (!oauth_param_exists(*argvp,"oauth_version")) { 00561 snprintf(oarg, 1024, "oauth_version=1.0"); 00562 argvp->push_back(oarg); 00563 } 00564 00565 #if 0 // oauth_version 1.0 Rev A 00566 if (!oauth_param_exists(argv,argc,"oauth_callback")) { 00567 snprintf(oarg, 1024, "oauth_callback=oob"); 00568 argvp->push_back(oarg); 00569 } 00570 #endif 00571 00572 } 00573 00574 std::string oauth_sign_url( 00575 const char *url, 00576 std::string *postargs, 00577 OAuthMethod method, 00578 const char *c_key, //< consumer key - posted plain text 00579 const char *c_secret, //< consumer secret - used as 1st part of secret-key 00580 const char *t_key, //< token key - posted plain text in URL 00581 const char *t_secret //< token secret - used as 2st part of secret-key 00582 ) 00583 { 00584 return oauth_sign_url2(url, postargs, method, NULL, c_key, c_secret, t_key, t_secret); 00585 } 00586 00587 std::string oauth_sign_url2( 00588 const char *url, 00589 std::string *postargs, 00590 OAuthMethod method, 00591 const char *http_method, //< HTTP request method 00592 const char *c_key, //< consumer key - posted plain text 00593 const char *c_secret, //< consumer secret - used as 1st part of secret-key 00594 const char *t_key, //< token key - posted plain text in URL 00595 const char *t_secret //< token secret - used as 2st part of secret-key 00596 ) 00597 { 00598 //char **argv = NULL; 00599 std::vector<std::string> argv; 00600 std::string rv; 00601 00602 if (postargs) { 00603 oauth_split_post_paramters(url, &argv, 0); 00604 } else { 00605 oauth_split_url_parameters(url, &argv); 00606 } 00607 00608 rv = oauth_sign_array2(&argv, postargs, method, http_method, c_key, c_secret, t_key, t_secret); 00609 00610 return(rv); 00611 } 00612 00613 std::string oauth_sign_array ( 00614 std::vector<std::string> *argvp, 00615 std::string *postargs, 00616 OAuthMethod method, 00617 const char *c_key, //< consumer key - posted plain text 00618 const char *c_secret, //< consumer secret - used as 1st part of secret-key 00619 const char *t_key, //< token key - posted plain text in URL 00620 const char *t_secret //< token secret - used as 2st part of secret-key 00621 ) 00622 { 00623 return oauth_sign_array2( 00624 argvp, 00625 postargs, method, 00626 NULL, 00627 c_key, c_secret, 00628 t_key, t_secret 00629 ); 00630 } 00631 00632 void oauth_sign_array2_process( 00633 std::vector<std::string> *argvp, 00634 std::string *postargs, 00635 OAuthMethod method, 00636 const char *http_method, //< HTTP request method 00637 const char *c_key, //< consumer key - posted plain text 00638 const char *c_secret, //< consumer secret - used as 1st part of secret-key 00639 const char *t_key, //< token key - posted plain text in URL 00640 const char *t_secret //< token secret - used as 2st part of secret-key 00641 ) 00642 { 00643 char oarg[1024]; 00644 std::string query; 00645 std::string sign; 00646 std::string http_request_method; 00647 00648 if (!http_method) { 00649 http_request_method = postargs ? "POST" : "GET"; 00650 } else { 00651 std::vector<char> tmp(strlen(http_method) + 1); 00652 int i; 00653 for (i = 0; http_method[i]; i++) { 00654 tmp[i] = toupper(http_method[i]); 00655 } 00656 tmp[i] = 0; 00657 http_request_method = &tmp[0]; 00658 } 00659 00660 // add required OAuth protocol parameters 00661 oauth_add_protocol(argvp, method, c_key, t_key); 00662 00663 // sort parameters 00664 //qsort(&(*argvp)[1], (*argcp)-1, sizeof(char *), oauth_cmpstringp); 00665 std::sort(argvp->begin() + 1, argvp->end(), oauth_cmpstringp_ex); 00666 00667 // serialize URL - base-url 00668 query= oauth_serialize_url_parameters(*argvp); 00669 00670 // generate signature 00671 std::string okey = oauth_catenc(2, c_secret, t_secret); 00672 std::string odat = oauth_catenc(3, http_request_method.c_str(), (*argvp)[0].c_str(), query.c_str()); // base-string 00673 #ifdef DEBUG_OAUTH 00674 fprintf (stderr, "\nliboauth: data to sign='%s'\n\n", odat.c_str()); 00675 fprintf (stderr, "\nliboauth: key='%s'\n\n", okey.c_str()); 00676 #endif 00677 switch(method) { 00678 //case OA_RSA: 00679 // sign = oauth_sign_rsa_sha1(odat.c_str(), okey.c_str()); // XXX okey needs to be RSA key! 00680 // break; 00681 case OA_PLAINTEXT: 00682 sign = oauth_sign_plaintext(odat.c_str(), okey.c_str()).c_str(); 00683 break; 00684 default: 00685 sign = oauth_sign_hmac_sha1(odat.c_str(), okey.c_str()); 00686 break; 00687 } 00688 00689 // append signature to query args. 00690 snprintf(oarg, 1024, "oauth_signature=%s",sign.c_str()); 00691 argvp->push_back(oarg); 00692 } 00693 00694 std::string oauth_sign_array2( 00695 std::vector<std::string> *argvp, 00696 std::string *postargs, 00697 OAuthMethod method, 00698 const char *http_method, //< HTTP request method 00699 const char *c_key, //< consumer key - posted plain text 00700 const char *c_secret, //< consumer secret - used as 1st part of secret-key 00701 const char *t_key, //< token key - posted plain text in URL 00702 const char *t_secret //< token secret - used as 2st part of secret-key 00703 ) 00704 { 00705 00706 std::string result; 00707 oauth_sign_array2_process(argvp, postargs, method, http_method, c_key, c_secret, t_key, t_secret); 00708 00709 // build URL params 00710 result = oauth_serialize_url(*argvp, (postargs?1:0)); 00711 00712 if (postargs) { 00713 *postargs = result; 00714 result = argvp->at(0); 00715 } 00716 00717 return result; 00718 } 00719
Generated on Wed Jul 20 2022 04:19:30 by
1.7.2