Twitter with OAuth Example.\\ see also http://www.soramimi.jp/twicpp/index.html

Dependencies:   mbed HTTPClient NTPClient_NetServices EthernetNetIf

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers oauth.cpp Source File

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