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