Fixed compatibility for HTTPClient Library. (HTTPClient by Donatien Garnier)

Dependents:   FlashAir_Twitter CyaSSL-Twitter-OAuth4Tw TweetTest NetworkThermometer ... more

Fork of OAuth4Tw by Masayoshi Takahashi

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