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