OAuth library for twitter. Original: http://mbed.org/users/soramimi/programs/Twitter/
Embed:
(wiki syntax)
Show/hide line numbers
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