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

Dependencies:   mbed HTTPClient NTPClient_NetServices EthernetNetIf

Committer:
soramimi
Date:
Thu Nov 15 00:51:45 2012 +0000
Revision:
1:c3f74457cad4
Twitter API address changed.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
soramimi0:7ddb56bfde0c 1/*
soramimi0:7ddb56bfde0c 2 * OAuth string functions in POSIX-C.
soramimi0:7ddb56bfde0c 3 *
soramimi0:7ddb56bfde0c 4 * Copyright 2007-2010 Robin Gareus <robin@gareus.org>
soramimi0:7ddb56bfde0c 5 *
soramimi0:7ddb56bfde0c 6 * The base64 functions are by Jan-Henrik Haukeland, <hauk@tildeslash.com>
soramimi0:7ddb56bfde0c 7 * and un/escape_url() was inspired by libcurl's curl_escape under ISC-license
soramimi0:7ddb56bfde0c 8 * many thanks to Daniel Stenberg <daniel@haxx.se>.
soramimi0:7ddb56bfde0c 9 *
soramimi0:7ddb56bfde0c 10 * Permission is hereby granted, free of charge, to any person obtaining a copy
soramimi0:7ddb56bfde0c 11 * of this software and associated documentation files (the "Software"), to deal
soramimi0:7ddb56bfde0c 12 * in the Software without restriction, including without limitation the rights
soramimi0:7ddb56bfde0c 13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
soramimi0:7ddb56bfde0c 14 * copies of the Software, and to permit persons to whom the Software is
soramimi0:7ddb56bfde0c 15 * furnished to do so, subject to the following conditions:
soramimi0:7ddb56bfde0c 16 *
soramimi0:7ddb56bfde0c 17 * The above copyright notice and this permission notice shall be included in
soramimi0:7ddb56bfde0c 18 * all copies or substantial portions of the Software.
soramimi0:7ddb56bfde0c 19 *
soramimi0:7ddb56bfde0c 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
soramimi0:7ddb56bfde0c 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
soramimi0:7ddb56bfde0c 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
soramimi0:7ddb56bfde0c 23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
soramimi0:7ddb56bfde0c 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
soramimi0:7ddb56bfde0c 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
soramimi0:7ddb56bfde0c 26 * THE SOFTWARE.
soramimi0:7ddb56bfde0c 27 *
soramimi0:7ddb56bfde0c 28 */
soramimi0:7ddb56bfde0c 29#if HAVE_CONFIG_H
soramimi0:7ddb56bfde0c 30# include <config.h>
soramimi0:7ddb56bfde0c 31#endif
soramimi0:7ddb56bfde0c 32
soramimi0:7ddb56bfde0c 33#define WIPE_MEMORY ///< overwrite sensitve data before free()ing it.
soramimi0:7ddb56bfde0c 34
soramimi0:7ddb56bfde0c 35#include <stdio.h>
soramimi0:7ddb56bfde0c 36#include <stdarg.h>
soramimi0:7ddb56bfde0c 37#include <stdlib.h>
soramimi0:7ddb56bfde0c 38#include <string.h>
soramimi0:7ddb56bfde0c 39#include <time.h>
soramimi0:7ddb56bfde0c 40#include <math.h>
soramimi0:7ddb56bfde0c 41#include <ctype.h> // isxdigit
soramimi0:7ddb56bfde0c 42
soramimi0:7ddb56bfde0c 43#include "oauth.h"
soramimi0:7ddb56bfde0c 44
soramimi0:7ddb56bfde0c 45#include <vector>
soramimi0:7ddb56bfde0c 46#include <algorithm>
soramimi0:7ddb56bfde0c 47#include <sstream>
soramimi0:7ddb56bfde0c 48
soramimi0:7ddb56bfde0c 49/**
soramimi0:7ddb56bfde0c 50 * Base64 encode one byte
soramimi0:7ddb56bfde0c 51 */
soramimi0:7ddb56bfde0c 52char oauth_b64_encode(unsigned char u)
soramimi0:7ddb56bfde0c 53{
soramimi0:7ddb56bfde0c 54 if (u < 26) return 'A' + u;
soramimi0:7ddb56bfde0c 55 if (u < 52) return 'a' + (u - 26);
soramimi0:7ddb56bfde0c 56 if (u < 62) return '0' + (u - 52);
soramimi0:7ddb56bfde0c 57 if (u == 62) return '+';
soramimi0:7ddb56bfde0c 58 return '/';
soramimi0:7ddb56bfde0c 59}
soramimi0:7ddb56bfde0c 60
soramimi0:7ddb56bfde0c 61/**
soramimi0:7ddb56bfde0c 62 * Decode a single base64 character.
soramimi0:7ddb56bfde0c 63 */
soramimi0:7ddb56bfde0c 64unsigned char oauth_b64_decode(char c)
soramimi0:7ddb56bfde0c 65{
soramimi0:7ddb56bfde0c 66 if (c >= 'A' && c <= 'Z') return(c - 'A');
soramimi0:7ddb56bfde0c 67 if (c >= 'a' && c <= 'z') return(c - 'a' + 26);
soramimi0:7ddb56bfde0c 68 if (c >= '0' && c <= '9') return(c - '0' + 52);
soramimi0:7ddb56bfde0c 69 if (c == '+') return 62;
soramimi0:7ddb56bfde0c 70 return 63;
soramimi0:7ddb56bfde0c 71}
soramimi0:7ddb56bfde0c 72
soramimi0:7ddb56bfde0c 73/**
soramimi0:7ddb56bfde0c 74 * Return TRUE if 'c' is a valid base64 character, otherwise FALSE
soramimi0:7ddb56bfde0c 75 */
soramimi0:7ddb56bfde0c 76bool oauth_b64_is_base64(char c)
soramimi0:7ddb56bfde0c 77{
soramimi0:7ddb56bfde0c 78 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '+') || (c == '/') || (c == '='));
soramimi0:7ddb56bfde0c 79}
soramimi0:7ddb56bfde0c 80
soramimi0:7ddb56bfde0c 81/**
soramimi0:7ddb56bfde0c 82 * Base64 encode and return size data in 'src'. The caller must free the
soramimi0:7ddb56bfde0c 83 * returned string.
soramimi0:7ddb56bfde0c 84 *
soramimi0:7ddb56bfde0c 85 * @param size The size of the data in src
soramimi0:7ddb56bfde0c 86 * @param src The data to be base64 encode
soramimi0:7ddb56bfde0c 87 * @return encoded string otherwise NULL
soramimi0:7ddb56bfde0c 88 */
soramimi0:7ddb56bfde0c 89std::string oauth_encode_base64(const unsigned char *src, int size)
soramimi0:7ddb56bfde0c 90{
soramimi0:7ddb56bfde0c 91 int i;
soramimi0:7ddb56bfde0c 92 std::stringbuf sb;
soramimi0:7ddb56bfde0c 93
soramimi0:7ddb56bfde0c 94 if (!src) return NULL;
soramimi0:7ddb56bfde0c 95 if (!size) size= strlen((char *)src);
soramimi0:7ddb56bfde0c 96
soramimi0:7ddb56bfde0c 97 for (i = 0; i < size; i += 3) {
soramimi0:7ddb56bfde0c 98 unsigned char b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0;
soramimi0:7ddb56bfde0c 99 b1= src[i];
soramimi0:7ddb56bfde0c 100 if (i + 1 < size) b2 = src[i + 1];
soramimi0:7ddb56bfde0c 101 if (i + 2 < size) b3 = src[i + 2];
soramimi0:7ddb56bfde0c 102
soramimi0:7ddb56bfde0c 103 b4= b1 >> 2;
soramimi0:7ddb56bfde0c 104 b5= ((b1 & 0x3) << 4) | (b2 >> 4);
soramimi0:7ddb56bfde0c 105 b6= ((b2 & 0xf) << 2) | (b3 >> 6);
soramimi0:7ddb56bfde0c 106 b7= b3 & 0x3f;
soramimi0:7ddb56bfde0c 107
soramimi0:7ddb56bfde0c 108 sb.sputc(oauth_b64_encode(b4));
soramimi0:7ddb56bfde0c 109 sb.sputc(oauth_b64_encode(b5));
soramimi0:7ddb56bfde0c 110
soramimi0:7ddb56bfde0c 111 if (i + 1 < size) {
soramimi0:7ddb56bfde0c 112 sb.sputc(oauth_b64_encode(b6));
soramimi0:7ddb56bfde0c 113 } else {
soramimi0:7ddb56bfde0c 114 sb.sputc('=');
soramimi0:7ddb56bfde0c 115 }
soramimi0:7ddb56bfde0c 116
soramimi0:7ddb56bfde0c 117 if (i + 2 < size) {
soramimi0:7ddb56bfde0c 118 sb.sputc(oauth_b64_encode(b7));
soramimi0:7ddb56bfde0c 119 } else {
soramimi0:7ddb56bfde0c 120 sb.sputc('=');
soramimi0:7ddb56bfde0c 121 }
soramimi0:7ddb56bfde0c 122 }
soramimi0:7ddb56bfde0c 123 return sb.str();
soramimi0:7ddb56bfde0c 124}
soramimi0:7ddb56bfde0c 125
soramimi0:7ddb56bfde0c 126/**
soramimi0:7ddb56bfde0c 127 * Decode the base64 encoded string 'src' into the memory pointed to by
soramimi0:7ddb56bfde0c 128 * 'dest'.
soramimi0:7ddb56bfde0c 129 *
soramimi0:7ddb56bfde0c 130 * @param dest Pointer to memory for holding the decoded string.
soramimi0:7ddb56bfde0c 131 * Must be large enough to receive the decoded string.
soramimi0:7ddb56bfde0c 132 * @param src A base64 encoded string.
soramimi0:7ddb56bfde0c 133 * @return the length of the decoded string if decode
soramimi0:7ddb56bfde0c 134 * succeeded otherwise 0.
soramimi0:7ddb56bfde0c 135 */
soramimi0:7ddb56bfde0c 136std::string oauth_decode_base64(const char *src)
soramimi0:7ddb56bfde0c 137{
soramimi0:7ddb56bfde0c 138 if (src && *src) {
soramimi0:7ddb56bfde0c 139 std::stringbuf sb;
soramimi0:7ddb56bfde0c 140 //unsigned char *p= dest;
soramimi0:7ddb56bfde0c 141 int k, l= strlen(src)+1;
soramimi0:7ddb56bfde0c 142 std::vector<unsigned char> buf(l);
soramimi0:7ddb56bfde0c 143
soramimi0:7ddb56bfde0c 144 /* Ignore non base64 chars as per the POSIX standard */
soramimi0:7ddb56bfde0c 145 for (k = 0, l = 0; src[k]; k++) {
soramimi0:7ddb56bfde0c 146 if (oauth_b64_is_base64(src[k])) {
soramimi0:7ddb56bfde0c 147 buf[l++]= src[k];
soramimi0:7ddb56bfde0c 148 }
soramimi0:7ddb56bfde0c 149 }
soramimi0:7ddb56bfde0c 150
soramimi0:7ddb56bfde0c 151 for (k = 0; k < l; k += 4) {
soramimi0:7ddb56bfde0c 152 char c1='A', c2='A', c3='A', c4='A';
soramimi0:7ddb56bfde0c 153 unsigned char b1 = 0, b2 = 0, b3 = 0, b4 = 0;
soramimi0:7ddb56bfde0c 154 c1= buf[k];
soramimi0:7ddb56bfde0c 155
soramimi0:7ddb56bfde0c 156 if (k + 1 < l) c2 = buf[k + 1];
soramimi0:7ddb56bfde0c 157 if (k + 2 < l) c3 = buf[k + 2];
soramimi0:7ddb56bfde0c 158 if (k + 3 < l) c4 = buf[k + 3];
soramimi0:7ddb56bfde0c 159
soramimi0:7ddb56bfde0c 160 b1 = oauth_b64_decode(c1);
soramimi0:7ddb56bfde0c 161 b2 = oauth_b64_decode(c2);
soramimi0:7ddb56bfde0c 162 b3 = oauth_b64_decode(c3);
soramimi0:7ddb56bfde0c 163 b4 = oauth_b64_decode(c4);
soramimi0:7ddb56bfde0c 164
soramimi0:7ddb56bfde0c 165 sb.sputc((b1 << 2) | (b2 >> 4));
soramimi0:7ddb56bfde0c 166
soramimi0:7ddb56bfde0c 167 if (c3 != '=') sb.sputc(((b2 & 0xf) << 4) | (b3 >> 2));
soramimi0:7ddb56bfde0c 168 if (c4 != '=') sb.sputc(((b3 & 0x3) << 6) | b4);
soramimi0:7ddb56bfde0c 169 }
soramimi0:7ddb56bfde0c 170
soramimi0:7ddb56bfde0c 171 return sb.str();
soramimi0:7ddb56bfde0c 172 }
soramimi0:7ddb56bfde0c 173 return 0;
soramimi0:7ddb56bfde0c 174}
soramimi0:7ddb56bfde0c 175
soramimi0:7ddb56bfde0c 176/**
soramimi0:7ddb56bfde0c 177 * Escape 'string' according to RFC3986 and
soramimi0:7ddb56bfde0c 178 * http://oauth.net/core/1.0/#encoding_parameters.
soramimi0:7ddb56bfde0c 179 *
soramimi0:7ddb56bfde0c 180 * @param string The data to be encoded
soramimi0:7ddb56bfde0c 181 * @return encoded string otherwise NULL
soramimi0:7ddb56bfde0c 182 * The caller must free the returned string.
soramimi0:7ddb56bfde0c 183 */
soramimi0:7ddb56bfde0c 184std::string oauth_url_escape(const char *string)
soramimi0:7ddb56bfde0c 185{
soramimi0:7ddb56bfde0c 186 unsigned char in;
soramimi0:7ddb56bfde0c 187 size_t length;
soramimi0:7ddb56bfde0c 188
soramimi0:7ddb56bfde0c 189 if (!string) {
soramimi0:7ddb56bfde0c 190 return std::string();
soramimi0:7ddb56bfde0c 191 }
soramimi0:7ddb56bfde0c 192
soramimi0:7ddb56bfde0c 193 length = strlen(string);
soramimi0:7ddb56bfde0c 194
soramimi0:7ddb56bfde0c 195 std::stringbuf sb;
soramimi0:7ddb56bfde0c 196
soramimi0:7ddb56bfde0c 197 while (length--) {
soramimi0:7ddb56bfde0c 198 in = *string;
soramimi0:7ddb56bfde0c 199 if (strchr("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_~.-", in)) {
soramimi0:7ddb56bfde0c 200 sb.sputc(in);
soramimi0:7ddb56bfde0c 201 } else {
soramimi0:7ddb56bfde0c 202 char tmp[10];
soramimi0:7ddb56bfde0c 203 snprintf(tmp, 4, "%%%02X", in);
soramimi0:7ddb56bfde0c 204 sb.sputc(tmp[0]);
soramimi0:7ddb56bfde0c 205 sb.sputc(tmp[1]);
soramimi0:7ddb56bfde0c 206 sb.sputc(tmp[2]);
soramimi0:7ddb56bfde0c 207 }
soramimi0:7ddb56bfde0c 208 string++;
soramimi0:7ddb56bfde0c 209 }
soramimi0:7ddb56bfde0c 210 return sb.str();
soramimi0:7ddb56bfde0c 211}
soramimi0:7ddb56bfde0c 212
soramimi0:7ddb56bfde0c 213#ifndef ISXDIGIT
soramimi0:7ddb56bfde0c 214# define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
soramimi0:7ddb56bfde0c 215#endif
soramimi0:7ddb56bfde0c 216
soramimi0:7ddb56bfde0c 217/**
soramimi0:7ddb56bfde0c 218 * Parse RFC3986 encoded 'string' back to unescaped version.
soramimi0:7ddb56bfde0c 219 *
soramimi0:7ddb56bfde0c 220 * @param string The data to be unescaped
soramimi0:7ddb56bfde0c 221 * @param olen unless NULL the length of the returned string is stored there.
soramimi0:7ddb56bfde0c 222 * @return decoded string or NULL
soramimi0:7ddb56bfde0c 223 * The caller must free the returned string.
soramimi0:7ddb56bfde0c 224 */
soramimi0:7ddb56bfde0c 225std::string oauth_url_unescape(const char *string)
soramimi0:7ddb56bfde0c 226{
soramimi0:7ddb56bfde0c 227 size_t alloc, strindex=0;
soramimi0:7ddb56bfde0c 228 unsigned char in;
soramimi0:7ddb56bfde0c 229 long hex;
soramimi0:7ddb56bfde0c 230
soramimi0:7ddb56bfde0c 231 if (!string) return NULL;
soramimi0:7ddb56bfde0c 232
soramimi0:7ddb56bfde0c 233 alloc = strlen(string)+1;
soramimi0:7ddb56bfde0c 234 std::vector<char> ns(alloc);
soramimi0:7ddb56bfde0c 235
soramimi0:7ddb56bfde0c 236 while(--alloc > 0) {
soramimi0:7ddb56bfde0c 237 in = *string;
soramimi0:7ddb56bfde0c 238 if (('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
soramimi0:7ddb56bfde0c 239 char hexstr[3]; // '%XX'
soramimi0:7ddb56bfde0c 240 hexstr[0] = string[1];
soramimi0:7ddb56bfde0c 241 hexstr[1] = string[2];
soramimi0:7ddb56bfde0c 242 hexstr[2] = 0;
soramimi0:7ddb56bfde0c 243 hex = strtol(hexstr, NULL, 16);
soramimi0:7ddb56bfde0c 244 in = (unsigned char)hex; /* hex is always < 256 */
soramimi0:7ddb56bfde0c 245 string += 2;
soramimi0:7ddb56bfde0c 246 alloc -= 2;
soramimi0:7ddb56bfde0c 247 }
soramimi0:7ddb56bfde0c 248 ns[strindex++] = in;
soramimi0:7ddb56bfde0c 249 string++;
soramimi0:7ddb56bfde0c 250 }
soramimi0:7ddb56bfde0c 251 ns[strindex]=0;
soramimi0:7ddb56bfde0c 252 return &ns[0];
soramimi0:7ddb56bfde0c 253}
soramimi0:7ddb56bfde0c 254
soramimi0:7ddb56bfde0c 255/**
soramimi0:7ddb56bfde0c 256 * returns plaintext signature for the given key.
soramimi0:7ddb56bfde0c 257 *
soramimi0:7ddb56bfde0c 258 * the returned string needs to be freed by the caller
soramimi0:7ddb56bfde0c 259 *
soramimi0:7ddb56bfde0c 260 * @param m message to be signed
soramimi0:7ddb56bfde0c 261 * @param k key used for signing
soramimi0:7ddb56bfde0c 262 * @return signature string
soramimi0:7ddb56bfde0c 263 */
soramimi0:7ddb56bfde0c 264std::string oauth_sign_plaintext (const char *m, const char *k)
soramimi0:7ddb56bfde0c 265{
soramimi0:7ddb56bfde0c 266 return oauth_url_escape(k);
soramimi0:7ddb56bfde0c 267}
soramimi0:7ddb56bfde0c 268
soramimi0:7ddb56bfde0c 269/**
soramimi0:7ddb56bfde0c 270 * encode strings and concatenate with '&' separator.
soramimi0:7ddb56bfde0c 271 * The number of strings to be concatenated must be
soramimi0:7ddb56bfde0c 272 * given as first argument.
soramimi0:7ddb56bfde0c 273 * all arguments thereafter must be of type (char *)
soramimi0:7ddb56bfde0c 274 *
soramimi0:7ddb56bfde0c 275 * @param len the number of arguments to follow this parameter
soramimi0:7ddb56bfde0c 276 * @param ... string to escape and added (may be NULL)
soramimi0:7ddb56bfde0c 277 *
soramimi0:7ddb56bfde0c 278 * @return pointer to memory holding the concatenated
soramimi0:7ddb56bfde0c 279 * strings - needs to be free(d) by the caller. or NULL
soramimi0:7ddb56bfde0c 280 * in case we ran out of memory.
soramimi0:7ddb56bfde0c 281 */
soramimi0:7ddb56bfde0c 282std::string oauth_catenc(int len, ...)
soramimi0:7ddb56bfde0c 283{
soramimi0:7ddb56bfde0c 284 va_list va;
soramimi0:7ddb56bfde0c 285 std::string str;
soramimi0:7ddb56bfde0c 286 va_start(va, len);
soramimi0:7ddb56bfde0c 287 for (int i = 0; i < len; i++) {
soramimi0:7ddb56bfde0c 288 char *arg = va_arg(va, char *);
soramimi0:7ddb56bfde0c 289 std::string enc = oauth_url_escape(arg);
soramimi0:7ddb56bfde0c 290 if (i > 0) str += "&";
soramimi0:7ddb56bfde0c 291 str += enc;
soramimi0:7ddb56bfde0c 292 }
soramimi0:7ddb56bfde0c 293 va_end(va);
soramimi0:7ddb56bfde0c 294 return str;
soramimi0:7ddb56bfde0c 295}
soramimi0:7ddb56bfde0c 296
soramimi0:7ddb56bfde0c 297/**
soramimi0:7ddb56bfde0c 298 * splits the given url into a parameter array.
soramimi0:7ddb56bfde0c 299 * (see \ref oauth_serialize_url and \ref oauth_serialize_url_parameters for the reverse)
soramimi0:7ddb56bfde0c 300 *
soramimi0:7ddb56bfde0c 301 * NOTE: Request-parameters-values may include an ampersand character.
soramimi0:7ddb56bfde0c 302 * However if unescaped this function will use them as parameter delimiter.
soramimi0:7ddb56bfde0c 303 * If you need to make such a request, this function since version 0.3.5 allows
soramimi0:7ddb56bfde0c 304 * to use the ASCII SOH (0x01) character as alias for '&' (0x26).
soramimi0:7ddb56bfde0c 305 * (the motivation is convenience: SOH is /untypeable/ and much more
soramimi0:7ddb56bfde0c 306 * unlikely to appear than '&' - If you plan to sign fancy URLs you
soramimi0:7ddb56bfde0c 307 * should not split a query-string, but rather provide the parameter array
soramimi0:7ddb56bfde0c 308 * directly to \ref oauth_serialize_url)
soramimi0:7ddb56bfde0c 309 *
soramimi0:7ddb56bfde0c 310 * @param url the url or query-string to parse.
soramimi0:7ddb56bfde0c 311 * @param argv pointer to a (char *) array where the results are stored.
soramimi0:7ddb56bfde0c 312 * The array is re-allocated to match the number of parameters and each
soramimi0:7ddb56bfde0c 313 * parameter-string is allocated with strdup. - The memory needs to be freed
soramimi0:7ddb56bfde0c 314 * by the caller.
soramimi0:7ddb56bfde0c 315 * @param qesc use query parameter escape (vs post-param-escape) - if set
soramimi0:7ddb56bfde0c 316 * to 1 all '+' are treated as spaces ' '
soramimi0:7ddb56bfde0c 317 *
soramimi0:7ddb56bfde0c 318 * @return number of parameter(s) in array.
soramimi0:7ddb56bfde0c 319 */
soramimi0:7ddb56bfde0c 320void oauth_split_post_paramters(const char *url, std::vector<std::string> *argv, short qesc)
soramimi0:7ddb56bfde0c 321{
soramimi0:7ddb56bfde0c 322 int argc=0;
soramimi0:7ddb56bfde0c 323 char *token, *tmp;
soramimi0:7ddb56bfde0c 324 if (!argv) return;
soramimi0:7ddb56bfde0c 325 if (!url) return;
soramimi0:7ddb56bfde0c 326 std::vector<char> t1(strlen(url) + 1);
soramimi0:7ddb56bfde0c 327 strcpy(&t1[0], url);
soramimi0:7ddb56bfde0c 328
soramimi0:7ddb56bfde0c 329 // '+' represents a space, in a URL query string
soramimi0:7ddb56bfde0c 330 while ((qesc&1) && (tmp = strchr(&t1[0],'+'))) *tmp = ' ';
soramimi0:7ddb56bfde0c 331
soramimi0:7ddb56bfde0c 332 tmp = &t1[0];
soramimi0:7ddb56bfde0c 333 while ((token = strtok(tmp,"&?"))) {
soramimi0:7ddb56bfde0c 334 if (!strncasecmp("oauth_signature=", token, 16)) continue;
soramimi0:7ddb56bfde0c 335 while (!(qesc & 2) && (tmp = strchr(token, '\001'))) *tmp = '&';
soramimi0:7ddb56bfde0c 336 argv->push_back(oauth_url_unescape(token));
soramimi0:7ddb56bfde0c 337 if (argc == 0 && strstr(token, ":/")) {
soramimi0:7ddb56bfde0c 338 // HTTP does not allow empty absolute paths, so the URL
soramimi0:7ddb56bfde0c 339 // 'http://example.com' is equivalent to 'http://example.com/' and should
soramimi0:7ddb56bfde0c 340 // be treated as such for the purposes of OAuth signing (rfc2616, section 3.2.1)
soramimi0:7ddb56bfde0c 341 // see http://groups.google.com/group/oauth/browse_thread/thread/c44b6f061bfd98c?hl=en
soramimi0:7ddb56bfde0c 342 char *slash = strstr(token, ":/");
soramimi0:7ddb56bfde0c 343 while (slash && *(++slash) == '/') ; // skip slashes eg /xxx:[\/]*/
soramimi0:7ddb56bfde0c 344#if 0
soramimi0:7ddb56bfde0c 345 // skip possibly unescaped slashes in the userinfo - they're not allowed by RFC2396 but have been seen.
soramimi0:7ddb56bfde0c 346 // the hostname/IP may only contain alphanumeric characters - so we're safe there.
soramimi0:7ddb56bfde0c 347 if (slash && strchr(slash,'@')) slash=strchr(slash, '@');
soramimi0:7ddb56bfde0c 348#endif
soramimi0:7ddb56bfde0c 349 if (slash && !strchr(slash,'/')) {
soramimi0:7ddb56bfde0c 350#ifdef DEBUG_OAUTH
soramimi0:7ddb56bfde0c 351 fprintf(stderr, "\nliboauth: added trailing slash to URL: '%s'\n\n", token);
soramimi0:7ddb56bfde0c 352#endif
soramimi0:7ddb56bfde0c 353 argv->push_back(std::string(token) + "/");
soramimi0:7ddb56bfde0c 354 }
soramimi0:7ddb56bfde0c 355 }
soramimi0:7ddb56bfde0c 356 if (argc == 0 && (tmp = strstr((char *)argv->at(argc).c_str(), ":80/"))) {
soramimi0:7ddb56bfde0c 357 memmove(tmp, tmp + 3, strlen(tmp + 2));
soramimi0:7ddb56bfde0c 358 }
soramimi0:7ddb56bfde0c 359 tmp = NULL;
soramimi0:7ddb56bfde0c 360 argc++;
soramimi0:7ddb56bfde0c 361 }
soramimi0:7ddb56bfde0c 362}
soramimi0:7ddb56bfde0c 363
soramimi0:7ddb56bfde0c 364void oauth_split_url_parameters(const char *url, std::vector<std::string> *argv)
soramimi0:7ddb56bfde0c 365{
soramimi0:7ddb56bfde0c 366 oauth_split_post_paramters(url, argv, 1);
soramimi0:7ddb56bfde0c 367}
soramimi0:7ddb56bfde0c 368
soramimi0:7ddb56bfde0c 369/**
soramimi0:7ddb56bfde0c 370 * build a url query string from an array.
soramimi0:7ddb56bfde0c 371 *
soramimi0:7ddb56bfde0c 372 * @param argc the total number of elements in the array
soramimi0:7ddb56bfde0c 373 * @param start element in the array at which to start concatenating.
soramimi0:7ddb56bfde0c 374 * @param argv parameter-array to concatenate.
soramimi0:7ddb56bfde0c 375 * @return url string needs to be freed by the caller.
soramimi0:7ddb56bfde0c 376 *
soramimi0:7ddb56bfde0c 377 */
soramimi0:7ddb56bfde0c 378std::string oauth_serialize_url (std::vector<std::string> const &argv, int start)
soramimi0:7ddb56bfde0c 379{
soramimi0:7ddb56bfde0c 380 return oauth_serialize_url_sep(argv, start, "&", 0);
soramimi0:7ddb56bfde0c 381}
soramimi0:7ddb56bfde0c 382
soramimi0:7ddb56bfde0c 383/**
soramimi0:7ddb56bfde0c 384 * encode query parameters from an array.
soramimi0:7ddb56bfde0c 385 *
soramimi0:7ddb56bfde0c 386 * @param argc the total number of elements in the array
soramimi0:7ddb56bfde0c 387 * @param start element in the array at which to start concatenating.
soramimi0:7ddb56bfde0c 388 * @param argv parameter-array to concatenate.
soramimi0:7ddb56bfde0c 389 * @param sep separator for parameters (usually "&")
soramimi0:7ddb56bfde0c 390 * @param mod - bitwise modifiers:
soramimi0:7ddb56bfde0c 391 * 1: skip all values that start with "oauth_"
soramimi0:7ddb56bfde0c 392 * 2: skip all values that don't start with "oauth_"
soramimi0:7ddb56bfde0c 393 * 4: add double quotation marks around values (use with sep=", " to generate HTTP Authorization header).
soramimi0:7ddb56bfde0c 394 * @return url string needs to be freed by the caller.
soramimi0:7ddb56bfde0c 395 */
soramimi0:7ddb56bfde0c 396std::string oauth_serialize_url_sep(std::vector<std::string> const &argv, int start, char const *sep, int mod)
soramimi0:7ddb56bfde0c 397{
soramimi0:7ddb56bfde0c 398 int i;
soramimi0:7ddb56bfde0c 399 int first = 0;
soramimi0:7ddb56bfde0c 400 int seplen = strlen(sep);
soramimi0:7ddb56bfde0c 401 std::string query;
soramimi0:7ddb56bfde0c 402 for (i = start; i < (int)argv.size(); i++) {
soramimi0:7ddb56bfde0c 403 std::string tmp;
soramimi0:7ddb56bfde0c 404
soramimi0:7ddb56bfde0c 405 if ((mod & 1) == 1 && (strncmp(argv[i].c_str(), "oauth_", 6) == 0 || strncmp(argv[i].c_str(), "x_oauth_", 8) == 0)) continue;
soramimi0:7ddb56bfde0c 406 if ((mod & 2) == 2 && (strncmp(argv[i].c_str(), "oauth_", 6) != 0 && strncmp(argv[i].c_str(), "x_oauth_", 8) != 0) && i != 0) continue;
soramimi0:7ddb56bfde0c 407
soramimi0:7ddb56bfde0c 408 if (i == start && i == 0 && strstr(argv[i].c_str(), ":/")) {
soramimi0:7ddb56bfde0c 409 tmp = argv[i];
soramimi0:7ddb56bfde0c 410 } else {
soramimi0:7ddb56bfde0c 411 char *p = strchr((char *)argv[i].c_str(), '=');
soramimi0:7ddb56bfde0c 412 if (p) {
soramimi0:7ddb56bfde0c 413 tmp = oauth_url_escape(std::string(argv[i].c_str(), (char const *)p).c_str());
soramimi0:7ddb56bfde0c 414 std::string t2 = oauth_url_escape(p + 1);
soramimi0:7ddb56bfde0c 415 tmp += "=";
soramimi0:7ddb56bfde0c 416 if (mod & 4) tmp += "\"";
soramimi0:7ddb56bfde0c 417 tmp += t2;
soramimi0:7ddb56bfde0c 418 if (mod & 4) tmp += "\"";
soramimi0:7ddb56bfde0c 419 } else {
soramimi0:7ddb56bfde0c 420 // see http://oauth.net/core/1.0/#anchor14
soramimi0:7ddb56bfde0c 421 // escape parameter names and arguments but not the '='
soramimi0:7ddb56bfde0c 422 tmp=argv[i];
soramimi0:7ddb56bfde0c 423 tmp += "=";
soramimi0:7ddb56bfde0c 424 }
soramimi0:7ddb56bfde0c 425 }
soramimi0:7ddb56bfde0c 426 query += ((i == start || first) ? "" : sep);
soramimi0:7ddb56bfde0c 427 query += tmp;
soramimi0:7ddb56bfde0c 428 first = 0;
soramimi0:7ddb56bfde0c 429 if (i == start && i == 0 && strstr((char *)tmp.c_str(), ":/")) {
soramimi0:7ddb56bfde0c 430 query += "?";
soramimi0:7ddb56bfde0c 431 first = 1;
soramimi0:7ddb56bfde0c 432 }
soramimi0:7ddb56bfde0c 433 }
soramimi0:7ddb56bfde0c 434 return (query);
soramimi0:7ddb56bfde0c 435}
soramimi0:7ddb56bfde0c 436
soramimi0:7ddb56bfde0c 437/**
soramimi0:7ddb56bfde0c 438 * build a query parameter string from an array.
soramimi0:7ddb56bfde0c 439 *
soramimi0:7ddb56bfde0c 440 * This function is a shortcut for \ref oauth_serialize_url (argc, 1, argv).
soramimi0:7ddb56bfde0c 441 * It strips the leading host/path, which is usually the first
soramimi0:7ddb56bfde0c 442 * element when using oauth_split_url_parameters on an URL.
soramimi0:7ddb56bfde0c 443 *
soramimi0:7ddb56bfde0c 444 * @param argc the total number of elements in the array
soramimi0:7ddb56bfde0c 445 * @param argv parameter-array to concatenate.
soramimi0:7ddb56bfde0c 446 * @return url string needs to be freed by the caller.
soramimi0:7ddb56bfde0c 447 */
soramimi0:7ddb56bfde0c 448std::string oauth_serialize_url_parameters (std::vector<std::string> const &argv)
soramimi0:7ddb56bfde0c 449{
soramimi0:7ddb56bfde0c 450 return oauth_serialize_url(argv, 1);
soramimi0:7ddb56bfde0c 451}
soramimi0:7ddb56bfde0c 452
soramimi0:7ddb56bfde0c 453/**
soramimi0:7ddb56bfde0c 454 * generate a random string between 15 and 32 chars length
soramimi0:7ddb56bfde0c 455 * and return a pointer to it. The value needs to be freed by the
soramimi0:7ddb56bfde0c 456 * caller
soramimi0:7ddb56bfde0c 457 *
soramimi0:7ddb56bfde0c 458 * @return zero terminated random string.
soramimi0:7ddb56bfde0c 459 */
soramimi0:7ddb56bfde0c 460std::string oauth_gen_nonce()
soramimi0:7ddb56bfde0c 461{
soramimi0:7ddb56bfde0c 462 static const char *chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
soramimi0:7ddb56bfde0c 463 const unsigned int max = 26 + 26 + 10 + 1; //strlen(chars);
soramimi0:7ddb56bfde0c 464 char tmp[50];
soramimi0:7ddb56bfde0c 465 int i, len;
soramimi0:7ddb56bfde0c 466
soramimi0:7ddb56bfde0c 467 srand((unsigned int)time(0));
soramimi0:7ddb56bfde0c 468 len = 15 + rand() % 16;
soramimi0:7ddb56bfde0c 469 for (i = 0; i < len; i++) {
soramimi0:7ddb56bfde0c 470 tmp[i] = chars[rand() % max];
soramimi0:7ddb56bfde0c 471 }
soramimi0:7ddb56bfde0c 472 tmp[i]='\0';
soramimi0:7ddb56bfde0c 473 return &tmp[0];
soramimi0:7ddb56bfde0c 474}
soramimi0:7ddb56bfde0c 475
soramimi0:7ddb56bfde0c 476/**
soramimi0:7ddb56bfde0c 477 * string compare function for oauth parameters.
soramimi0:7ddb56bfde0c 478 *
soramimi0:7ddb56bfde0c 479 * used with qsort. needed to normalize request parameters.
soramimi0:7ddb56bfde0c 480 * see http://oauth.net/core/1.0/#anchor14
soramimi0:7ddb56bfde0c 481 */
soramimi0:7ddb56bfde0c 482int oauth_cmpstringp(const void *p1, const void *p2)
soramimi0:7ddb56bfde0c 483{
soramimi0:7ddb56bfde0c 484 char const *e1;
soramimi0:7ddb56bfde0c 485 char const *e2;
soramimi0:7ddb56bfde0c 486 e1 = strchr((char *)p1, '=');
soramimi0:7ddb56bfde0c 487 e2 = strchr((char *)p2, '=');
soramimi0:7ddb56bfde0c 488 if (e1 && e2) {
soramimi0:7ddb56bfde0c 489 std::string left((char const *)p1, e1);
soramimi0:7ddb56bfde0c 490 std::string right((char const *)p2, e2);
soramimi0:7ddb56bfde0c 491 return strcmp(left.c_str(), right.c_str());
soramimi0:7ddb56bfde0c 492 }
soramimi0:7ddb56bfde0c 493
soramimi0:7ddb56bfde0c 494 std::string left = oauth_url_escape((char const *)p1);
soramimi0:7ddb56bfde0c 495 std::string right = oauth_url_escape((char const *)p2);
soramimi0:7ddb56bfde0c 496 return strcmp(left.c_str(), right.c_str());
soramimi0:7ddb56bfde0c 497}
soramimi0:7ddb56bfde0c 498
soramimi0:7ddb56bfde0c 499bool oauth_cmpstringp_ex(std::string const &left, std::string const &right)
soramimi0:7ddb56bfde0c 500{
soramimi0:7ddb56bfde0c 501 return oauth_cmpstringp(left.c_str(), right.c_str()) < 0;
soramimi0:7ddb56bfde0c 502}
soramimi0:7ddb56bfde0c 503
soramimi0:7ddb56bfde0c 504/**
soramimi0:7ddb56bfde0c 505 * search array for parameter key.
soramimi0:7ddb56bfde0c 506 * @param argv length of array to search
soramimi0:7ddb56bfde0c 507 * @param argc parameter array to search
soramimi0:7ddb56bfde0c 508 * @param key key of parameter to check.
soramimi0:7ddb56bfde0c 509 *
soramimi0:7ddb56bfde0c 510 * @return FALSE (0) if array does not contain a parameter with given key, TRUE (1) otherwise.
soramimi0:7ddb56bfde0c 511 */
soramimi0:7ddb56bfde0c 512bool oauth_param_exists(std::vector<std::string> const &argv, char const *key)
soramimi0:7ddb56bfde0c 513{
soramimi0:7ddb56bfde0c 514 int i;
soramimi0:7ddb56bfde0c 515 size_t l = strlen(key);
soramimi0:7ddb56bfde0c 516 for (i = 0; i < (int)argv.size(); i++) {
soramimi0:7ddb56bfde0c 517 if (!strncmp(argv[i].c_str(), key, l) && argv[i][l] == '=') {
soramimi0:7ddb56bfde0c 518 return true;
soramimi0:7ddb56bfde0c 519 }
soramimi0:7ddb56bfde0c 520 }
soramimi0:7ddb56bfde0c 521 return false;
soramimi0:7ddb56bfde0c 522}
soramimi0:7ddb56bfde0c 523
soramimi0:7ddb56bfde0c 524/**
soramimi0:7ddb56bfde0c 525 *
soramimi0:7ddb56bfde0c 526 */
soramimi0:7ddb56bfde0c 527void oauth_add_protocol(
soramimi0:7ddb56bfde0c 528 std::vector<std::string> *argvp,
soramimi0:7ddb56bfde0c 529 OAuthMethod method,
soramimi0:7ddb56bfde0c 530 const char *c_key, //< consumer key - posted plain text
soramimi0:7ddb56bfde0c 531 const char *t_key //< token key - posted plain text in URL
soramimi0:7ddb56bfde0c 532)
soramimi0:7ddb56bfde0c 533{
soramimi0:7ddb56bfde0c 534 char oarg[1024];
soramimi0:7ddb56bfde0c 535
soramimi0:7ddb56bfde0c 536 // add OAuth specific arguments
soramimi0:7ddb56bfde0c 537 if (!oauth_param_exists(*argvp,"oauth_nonce")) {
soramimi0:7ddb56bfde0c 538 std::string tmp = oauth_gen_nonce();
soramimi0:7ddb56bfde0c 539 snprintf(oarg, 1024, "oauth_nonce=%s", tmp.c_str());
soramimi0:7ddb56bfde0c 540 argvp->push_back(oarg);
soramimi0:7ddb56bfde0c 541 }
soramimi0:7ddb56bfde0c 542
soramimi0:7ddb56bfde0c 543 if (!oauth_param_exists(*argvp,"oauth_timestamp")) {
soramimi0:7ddb56bfde0c 544 long t = time(0);
soramimi0:7ddb56bfde0c 545 snprintf(oarg, 1024, "oauth_timestamp=%u", t);
soramimi0:7ddb56bfde0c 546 argvp->push_back(oarg);
soramimi0:7ddb56bfde0c 547 }
soramimi0:7ddb56bfde0c 548
soramimi0:7ddb56bfde0c 549 if (t_key) {
soramimi0:7ddb56bfde0c 550 snprintf(oarg, 1024, "oauth_token=%s", t_key);
soramimi0:7ddb56bfde0c 551 argvp->push_back(oarg);
soramimi0:7ddb56bfde0c 552 }
soramimi0:7ddb56bfde0c 553
soramimi0:7ddb56bfde0c 554 snprintf(oarg, 1024, "oauth_consumer_key=%s", c_key);
soramimi0:7ddb56bfde0c 555 argvp->push_back(oarg);
soramimi0:7ddb56bfde0c 556
soramimi0:7ddb56bfde0c 557 snprintf(oarg, 1024, "oauth_signature_method=%s", method==0?"HMAC-SHA1":method==1?"RSA-SHA1":"PLAINTEXT");
soramimi0:7ddb56bfde0c 558 argvp->push_back(oarg);
soramimi0:7ddb56bfde0c 559
soramimi0:7ddb56bfde0c 560 if (!oauth_param_exists(*argvp,"oauth_version")) {
soramimi0:7ddb56bfde0c 561 snprintf(oarg, 1024, "oauth_version=1.0");
soramimi0:7ddb56bfde0c 562 argvp->push_back(oarg);
soramimi0:7ddb56bfde0c 563 }
soramimi0:7ddb56bfde0c 564
soramimi0:7ddb56bfde0c 565#if 0 // oauth_version 1.0 Rev A
soramimi0:7ddb56bfde0c 566 if (!oauth_param_exists(argv,argc,"oauth_callback")) {
soramimi0:7ddb56bfde0c 567 snprintf(oarg, 1024, "oauth_callback=oob");
soramimi0:7ddb56bfde0c 568 argvp->push_back(oarg);
soramimi0:7ddb56bfde0c 569 }
soramimi0:7ddb56bfde0c 570#endif
soramimi0:7ddb56bfde0c 571
soramimi0:7ddb56bfde0c 572}
soramimi0:7ddb56bfde0c 573
soramimi0:7ddb56bfde0c 574std::string oauth_sign_url(
soramimi0:7ddb56bfde0c 575 const char *url,
soramimi0:7ddb56bfde0c 576 std::string *postargs,
soramimi0:7ddb56bfde0c 577 OAuthMethod method,
soramimi0:7ddb56bfde0c 578 const char *c_key, //< consumer key - posted plain text
soramimi0:7ddb56bfde0c 579 const char *c_secret, //< consumer secret - used as 1st part of secret-key
soramimi0:7ddb56bfde0c 580 const char *t_key, //< token key - posted plain text in URL
soramimi0:7ddb56bfde0c 581 const char *t_secret //< token secret - used as 2st part of secret-key
soramimi0:7ddb56bfde0c 582)
soramimi0:7ddb56bfde0c 583{
soramimi0:7ddb56bfde0c 584 return oauth_sign_url2(url, postargs, method, NULL, c_key, c_secret, t_key, t_secret);
soramimi0:7ddb56bfde0c 585}
soramimi0:7ddb56bfde0c 586
soramimi0:7ddb56bfde0c 587std::string oauth_sign_url2(
soramimi0:7ddb56bfde0c 588 const char *url,
soramimi0:7ddb56bfde0c 589 std::string *postargs,
soramimi0:7ddb56bfde0c 590 OAuthMethod method,
soramimi0:7ddb56bfde0c 591 const char *http_method, //< HTTP request method
soramimi0:7ddb56bfde0c 592 const char *c_key, //< consumer key - posted plain text
soramimi0:7ddb56bfde0c 593 const char *c_secret, //< consumer secret - used as 1st part of secret-key
soramimi0:7ddb56bfde0c 594 const char *t_key, //< token key - posted plain text in URL
soramimi0:7ddb56bfde0c 595 const char *t_secret //< token secret - used as 2st part of secret-key
soramimi0:7ddb56bfde0c 596)
soramimi0:7ddb56bfde0c 597{
soramimi0:7ddb56bfde0c 598 //char **argv = NULL;
soramimi0:7ddb56bfde0c 599 std::vector<std::string> argv;
soramimi0:7ddb56bfde0c 600 std::string rv;
soramimi0:7ddb56bfde0c 601
soramimi0:7ddb56bfde0c 602 if (postargs) {
soramimi0:7ddb56bfde0c 603 oauth_split_post_paramters(url, &argv, 0);
soramimi0:7ddb56bfde0c 604 } else {
soramimi0:7ddb56bfde0c 605 oauth_split_url_parameters(url, &argv);
soramimi0:7ddb56bfde0c 606 }
soramimi0:7ddb56bfde0c 607
soramimi0:7ddb56bfde0c 608 rv = oauth_sign_array2(&argv, postargs, method, http_method, c_key, c_secret, t_key, t_secret);
soramimi0:7ddb56bfde0c 609
soramimi0:7ddb56bfde0c 610 return(rv);
soramimi0:7ddb56bfde0c 611}
soramimi0:7ddb56bfde0c 612
soramimi0:7ddb56bfde0c 613std::string oauth_sign_array(
soramimi0:7ddb56bfde0c 614 std::vector<std::string> *argvp,
soramimi0:7ddb56bfde0c 615 std::string *postargs,
soramimi0:7ddb56bfde0c 616 OAuthMethod method,
soramimi0:7ddb56bfde0c 617 const char *c_key, //< consumer key - posted plain text
soramimi0:7ddb56bfde0c 618 const char *c_secret, //< consumer secret - used as 1st part of secret-key
soramimi0:7ddb56bfde0c 619 const char *t_key, //< token key - posted plain text in URL
soramimi0:7ddb56bfde0c 620 const char *t_secret //< token secret - used as 2st part of secret-key
soramimi0:7ddb56bfde0c 621)
soramimi0:7ddb56bfde0c 622{
soramimi0:7ddb56bfde0c 623 return oauth_sign_array2(
soramimi0:7ddb56bfde0c 624 argvp,
soramimi0:7ddb56bfde0c 625 postargs, method,
soramimi0:7ddb56bfde0c 626 NULL,
soramimi0:7ddb56bfde0c 627 c_key, c_secret,
soramimi0:7ddb56bfde0c 628 t_key, t_secret
soramimi0:7ddb56bfde0c 629 );
soramimi0:7ddb56bfde0c 630}
soramimi0:7ddb56bfde0c 631
soramimi0:7ddb56bfde0c 632void oauth_sign_array2_process(
soramimi0:7ddb56bfde0c 633 std::vector<std::string> *argvp,
soramimi0:7ddb56bfde0c 634 std::string *postargs,
soramimi0:7ddb56bfde0c 635 OAuthMethod method,
soramimi0:7ddb56bfde0c 636 const char *http_method, //< HTTP request method
soramimi0:7ddb56bfde0c 637 const char *c_key, //< consumer key - posted plain text
soramimi0:7ddb56bfde0c 638 const char *c_secret, //< consumer secret - used as 1st part of secret-key
soramimi0:7ddb56bfde0c 639 const char *t_key, //< token key - posted plain text in URL
soramimi0:7ddb56bfde0c 640 const char *t_secret //< token secret - used as 2st part of secret-key
soramimi0:7ddb56bfde0c 641)
soramimi0:7ddb56bfde0c 642{
soramimi0:7ddb56bfde0c 643 char oarg[1024];
soramimi0:7ddb56bfde0c 644 std::string query;
soramimi0:7ddb56bfde0c 645 std::string sign;
soramimi0:7ddb56bfde0c 646 std::string http_request_method;
soramimi0:7ddb56bfde0c 647
soramimi0:7ddb56bfde0c 648 if (!http_method) {
soramimi0:7ddb56bfde0c 649 http_request_method = postargs ? "POST" : "GET";
soramimi0:7ddb56bfde0c 650 } else {
soramimi0:7ddb56bfde0c 651 std::vector<char> tmp(strlen(http_method) + 1);
soramimi0:7ddb56bfde0c 652 int i;
soramimi0:7ddb56bfde0c 653 for (i = 0; http_method[i]; i++) {
soramimi0:7ddb56bfde0c 654 tmp[i] = toupper(http_method[i]);
soramimi0:7ddb56bfde0c 655 }
soramimi0:7ddb56bfde0c 656 tmp[i] = 0;
soramimi0:7ddb56bfde0c 657 http_request_method = &tmp[0];
soramimi0:7ddb56bfde0c 658 }
soramimi0:7ddb56bfde0c 659
soramimi0:7ddb56bfde0c 660 // add required OAuth protocol parameters
soramimi0:7ddb56bfde0c 661 oauth_add_protocol(argvp, method, c_key, t_key);
soramimi0:7ddb56bfde0c 662
soramimi0:7ddb56bfde0c 663 // sort parameters
soramimi0:7ddb56bfde0c 664 //qsort(&(*argvp)[1], (*argcp)-1, sizeof(char *), oauth_cmpstringp);
soramimi0:7ddb56bfde0c 665 std::sort(argvp->begin() + 1, argvp->end(), oauth_cmpstringp_ex);
soramimi0:7ddb56bfde0c 666
soramimi0:7ddb56bfde0c 667 // serialize URL - base-url
soramimi0:7ddb56bfde0c 668 query= oauth_serialize_url_parameters(*argvp);
soramimi0:7ddb56bfde0c 669
soramimi0:7ddb56bfde0c 670 // generate signature
soramimi0:7ddb56bfde0c 671 std::string okey = oauth_catenc(2, c_secret, t_secret);
soramimi0:7ddb56bfde0c 672 std::string odat = oauth_catenc(3, http_request_method.c_str(), (*argvp)[0].c_str(), query.c_str()); // base-string
soramimi0:7ddb56bfde0c 673#ifdef DEBUG_OAUTH
soramimi0:7ddb56bfde0c 674 fprintf (stderr, "\nliboauth: data to sign='%s'\n\n", odat.c_str());
soramimi0:7ddb56bfde0c 675 fprintf (stderr, "\nliboauth: key='%s'\n\n", okey.c_str());
soramimi0:7ddb56bfde0c 676#endif
soramimi0:7ddb56bfde0c 677 switch(method) {
soramimi0:7ddb56bfde0c 678 //case OA_RSA:
soramimi0:7ddb56bfde0c 679 // sign = oauth_sign_rsa_sha1(odat.c_str(), okey.c_str()); // XXX okey needs to be RSA key!
soramimi0:7ddb56bfde0c 680 // break;
soramimi0:7ddb56bfde0c 681 case OA_PLAINTEXT:
soramimi0:7ddb56bfde0c 682 sign = oauth_sign_plaintext(odat.c_str(), okey.c_str()).c_str();
soramimi0:7ddb56bfde0c 683 break;
soramimi0:7ddb56bfde0c 684 default:
soramimi0:7ddb56bfde0c 685 sign = oauth_sign_hmac_sha1(odat.c_str(), okey.c_str());
soramimi0:7ddb56bfde0c 686 break;
soramimi0:7ddb56bfde0c 687 }
soramimi0:7ddb56bfde0c 688
soramimi0:7ddb56bfde0c 689 // append signature to query args.
soramimi0:7ddb56bfde0c 690 snprintf(oarg, 1024, "oauth_signature=%s",sign.c_str());
soramimi0:7ddb56bfde0c 691 argvp->push_back(oarg);
soramimi0:7ddb56bfde0c 692}
soramimi0:7ddb56bfde0c 693
soramimi0:7ddb56bfde0c 694std::string oauth_sign_array2(
soramimi0:7ddb56bfde0c 695 std::vector<std::string> *argvp,
soramimi0:7ddb56bfde0c 696 std::string *postargs,
soramimi0:7ddb56bfde0c 697 OAuthMethod method,
soramimi0:7ddb56bfde0c 698 const char *http_method, //< HTTP request method
soramimi0:7ddb56bfde0c 699 const char *c_key, //< consumer key - posted plain text
soramimi0:7ddb56bfde0c 700 const char *c_secret, //< consumer secret - used as 1st part of secret-key
soramimi0:7ddb56bfde0c 701 const char *t_key, //< token key - posted plain text in URL
soramimi0:7ddb56bfde0c 702 const char *t_secret //< token secret - used as 2st part of secret-key
soramimi0:7ddb56bfde0c 703)
soramimi0:7ddb56bfde0c 704{
soramimi0:7ddb56bfde0c 705
soramimi0:7ddb56bfde0c 706 std::string result;
soramimi0:7ddb56bfde0c 707 oauth_sign_array2_process(argvp, postargs, method, http_method, c_key, c_secret, t_key, t_secret);
soramimi0:7ddb56bfde0c 708
soramimi0:7ddb56bfde0c 709 // build URL params
soramimi0:7ddb56bfde0c 710 result = oauth_serialize_url(*argvp, (postargs?1:0));
soramimi0:7ddb56bfde0c 711
soramimi0:7ddb56bfde0c 712 if (postargs) {
soramimi0:7ddb56bfde0c 713 *postargs = result;
soramimi0:7ddb56bfde0c 714 result = argvp->at(0);
soramimi0:7ddb56bfde0c 715 }
soramimi0:7ddb56bfde0c 716
soramimi0:7ddb56bfde0c 717 return result;
soramimi0:7ddb56bfde0c 718}
soramimi0:7ddb56bfde0c 719