1 /*
2 +----------------------------------------------------------------------+
3 | See LICENSE file for further copyright information |
4 +----------------------------------------------------------------------+
5 | Authors: John Jawed <jawed@php.net> |
6 | Felipe Pena <felipe@php.net> |
7 | Rasmus Lerdorf <rasmus@php.net> |
8 | Tjerk Meesters <datibbaw@php.net> |
9 +----------------------------------------------------------------------+
10 */
11
12 #include "php_oauth.h"
13 #include "provider.h"
14
15 static zend_class_entry *soo_class_entry;
16 static zend_class_entry *soo_exception_ce;
17 static zend_object_handlers so_object_handlers;
18
php_so_object_new(zend_class_entry * ce)19 static zend_object* php_so_object_new(zend_class_entry *ce) /* {{{ */
20 {
21 php_so_object *nos;
22
23 nos = ecalloc(1, sizeof(php_so_object) + zend_object_properties_size(ce));
24 nos->signature = NULL;
25 nos->timeout = 0;
26
27 zend_object_std_init(&nos->zo, ce);
28 object_properties_init(&nos->zo, ce);
29
30 nos->zo.handlers = &so_object_handlers;
31
32 return &nos->zo;
33 }
34 /* }}} */
35
36 #if PHP_VERSION_ID < 80000
oauth_clone_obj(zval * this_ptr)37 static zend_object *oauth_clone_obj(zval *this_ptr) /* {{{ */
38 {
39 php_so_object *old_obj = Z_SOO_P(this_ptr);
40 #else
41 static zend_object *oauth_clone_obj(zend_object *this_ptr) /* {{{ */
42 {
43 php_so_object *old_obj = so_object_from_obj(this_ptr);
44 #endif
45 php_so_object *new_obj = so_object_from_obj(php_so_object_new(old_obj->zo.ce));
46
47 zend_objects_clone_members(&new_obj->zo, &old_obj->zo);
48
49 return &new_obj->zo;
50 }
51 /* }}} */
52
53 static int oauth_parse_str(char *params, zval *dest_array) /* {{{ */
54 {
55 char *res = NULL, *var, *val, *separator = NULL;
56 char *strtok_buf = NULL;
57
58 if (!params) {
59 return FAILURE;
60 }
61
62 res = params;
63 separator = (char *) estrdup(PG(arg_separator).input);
64 var = php_strtok_r(res, separator, &strtok_buf);
65 while (var) {
66 val = strchr(var, '=');
67
68 if (val) { /* have a value */
69 int val_len;
70
71 *val++ = '\0';
72 php_url_decode(var, strlen(var));
73 val_len = php_url_decode(val, strlen(val));
74 val = estrndup(val, val_len);
75 } else {
76 int val_len;
77
78 php_url_decode(var, strlen(var));
79 val_len = 0;
80 val = estrndup("", val_len);
81 }
82 add_assoc_string(dest_array, var, val);
83 efree(val);
84 var = php_strtok_r(NULL, separator, &strtok_buf);
85 }
86
87 efree(separator);
88 return SUCCESS;
89 }
90 /* }}} */
91
92 static int so_set_response_args(HashTable *hasht, zval *data, zval *retarray) /* {{{ */
93 {
94 if (data && Z_TYPE_P(data) == IS_STRING) {
95
96 if (retarray) {
97 char *res = NULL;
98
99 res = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
100 /* do not use oauth_parse_str here, we want the result to pass through input filters */
101 sapi_module.treat_data(PARSE_STRING, res, retarray);
102 }
103
104 return (zend_hash_str_update(hasht, OAUTH_RAW_LAST_RES, sizeof(OAUTH_RAW_LAST_RES) -1, data) == NULL) ? FAILURE : SUCCESS;
105 }
106 return FAILURE;
107 }
108 /* }}} */
109
110 static zval *so_set_response_info(HashTable *hasht, zval *info) /* {{{ */
111 {
112 return zend_hash_str_update(hasht, OAUTH_ATTR_LAST_RES_INFO, sizeof(OAUTH_ATTR_LAST_RES_INFO) - 1, info);
113 }
114 /* }}} */
115
116 static void oauth_prop_hash_dtor(php_so_object *soo) /* {{{ */
117 {
118 HashTable *ht;
119
120 ht = soo->properties;
121
122 FREE_ARGS_HASH(ht);
123 }
124 /* }}} */
125
126 static void so_object_free_storage(zend_object *obj) /* {{{ */
127 {
128 php_so_object *soo;
129
130 soo = so_object_from_obj(obj);
131 zend_object_std_dtor(&soo->zo);
132
133 if (soo->lastresponse.c) {
134 smart_string_free(&soo->lastresponse);
135 }
136 if (soo->headers_in.c) {
137 smart_string_free(&soo->headers_in);
138 }
139 if (soo->headers_out.c) {
140 smart_string_free(&soo->headers_out);
141 }
142 if (soo->signature) {
143 zend_string_release(soo->signature);
144 }
145
146 oauth_prop_hash_dtor(soo);
147
148 if (soo->debug_info) {
149 FREE_DEBUG_INFO(soo->debug_info);
150 if (soo->debug_info->sbs) {
151 efree(soo->debug_info->sbs);
152 }
153 efree(soo->debug_info);
154 soo->debug_info = NULL;
155 }
156
157 smart_string_free(&soo->headers_in);
158 if (soo->headers_out.c) {
159 smart_string_free(&soo->headers_out);
160 }
161 if(Z_TYPE(soo->debugArr) != IS_UNDEF) {
162 zval_ptr_dtor(&soo->debugArr);
163 }
164 OAUTH_SIGCTX_FREE(soo->sig_ctx);
165 if (soo->nonce) {
166 efree(soo->nonce);
167 }
168 if (soo->timestamp) {
169 efree(soo->timestamp);
170 }
171
172 }
173 /* }}} */
174
175 void soo_handle_error(php_so_object *soo, long errorCode, char *msg, char *response, char *additional_info) /* {{{ */
176 {
177 zval ex;
178 zend_class_entry *dex = zend_exception_get_default(), *soox = soo_exception_ce;
179
180 object_init_ex(&ex, soox);
181
182 if (!errorCode) {
183 php_error(E_WARNING, "caller did not pass an errorcode!");
184 } else {
185 zend_update_property_long(dex, OBJ_FOR_PROP(&ex), "code", sizeof("code")-1, errorCode);
186 }
187 if (response) {
188 zend_update_property_string(dex, OBJ_FOR_PROP(&ex), "lastResponse", sizeof("lastResponse")-1, response);
189 }
190 if(soo && soo->debug && Z_TYPE(soo->debugArr) != IS_UNDEF) {
191 zend_update_property(dex, OBJ_FOR_PROP(&ex), "debugInfo", sizeof("debugInfo") - 1, &soo->debugArr);
192 }
193
194 if(additional_info) {
195 zend_update_property_string(dex, OBJ_FOR_PROP(&ex), "additionalInfo", sizeof("additionalInfo")-1, additional_info);
196 }
197
198 zend_update_property_string(dex, OBJ_FOR_PROP(&ex), "message", sizeof("message")-1, msg);
199 zend_throw_exception_object(&ex);
200 }
201 /* }}} */
202
203 zend_string *soo_sign_hmac(php_so_object *soo, char *message, const char *cs, const char *ts, const oauth_sig_context *ctx) /* {{{ */
204 {
205 zval args[4], retval, func;
206 char *tret;
207 zend_string *result;
208
209 ZVAL_STRING(&func, "hash_hmac");
210
211 if (!zend_is_callable(&func, 0, NULL)) {
212 zval_ptr_dtor(&func);
213 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "HMAC signature generation failed, is ext/hash installed?", NULL, NULL);
214 return NULL;
215 }
216
217 /* cs and ts would at best be empty, so this should be safe ;-) */
218 spprintf(&tret, 0, "%s&%s", cs, ts);
219
220 ZVAL_STRING(&args[0], ctx->hash_algo);
221 ZVAL_STRING(&args[1], message);
222 ZVAL_STRING(&args[2], tret);
223 ZVAL_BOOL(&args[3], 1);
224
225 call_user_function(EG(function_table), NULL, &func, &retval, 4, args);
226 result = php_base64_encode((unsigned char *)Z_STRVAL(retval), Z_STRLEN(retval));
227
228 efree(tret);
229 zval_ptr_dtor(&retval);
230 zval_ptr_dtor(&func);
231 zval_ptr_dtor(&args[0]);
232 zval_ptr_dtor(&args[1]);
233 zval_ptr_dtor(&args[2]);
234 zval_ptr_dtor(&args[3]);
235
236 return result;
237 }
238 /* }}} */
239
240 zend_string *soo_sign_rsa(php_so_object *soo, char *message, const oauth_sig_context *ctx) /* {{{ */
241 {
242 zval args[3], func, retval;
243 zend_string *result;
244
245 /* check for empty private key */
246 if (Z_TYPE(ctx->privatekey) == IS_UNDEF) {
247 return NULL;
248 }
249
250 ZVAL_STRING(&func, "openssl_sign");
251
252 /* TODO: add support for other algorithms instead of OPENSSL_ALGO_SHA1 */
253
254 ZVAL_STRING(&args[0], message);
255 ZVAL_NULL(&args[1]);
256 ZVAL_MAKE_REF(&args[1]);
257 ZVAL_DUP(&args[2], &ctx->privatekey);
258
259 call_user_function(EG(function_table), NULL, &func, &retval, 3, args);
260
261 if (Z_TYPE(retval) == IS_TRUE || Z_TYPE(retval) == IS_FALSE) {
262 zend_string *sig_str = zval_get_string(&args[1]);
263 result = php_base64_encode((unsigned char *) sig_str->val, sig_str->len);
264 zend_string_release(sig_str);
265 zval_ptr_dtor(&args[1]);
266 } else {
267 result = NULL;
268 }
269
270 zval_ptr_dtor(&retval);
271 zval_ptr_dtor(&func);
272 zval_ptr_dtor(&args[0]);
273
274 return result;
275 }
276 /* }}} */
277
278 zend_string *soo_sign_plain(php_so_object *soo, const char *cs, const char *ts) /* {{{ */
279 {
280 return strpprintf(0, "%s&%s", cs, ts);
281 }
282 /* }}} */
283
284 oauth_sig_context *oauth_create_sig_context(const char *sigmethod) /* {{{ */
285 {
286 oauth_sig_context *ctx;
287
288 OAUTH_SIGCTX_INIT(ctx);
289 if (0==strcmp(sigmethod, OAUTH_SIG_METHOD_HMACSHA1)) {
290 OAUTH_SIGCTX_HMAC(ctx, "sha1");
291 } else if (0==strcmp(sigmethod, OAUTH_SIG_METHOD_HMACSHA256)) {
292 OAUTH_SIGCTX_HMAC(ctx, "sha256");
293 } else if (0==strcmp(sigmethod, OAUTH_SIG_METHOD_RSASHA1)) {
294 OAUTH_SIGCTX_RSA(ctx, "sha1");
295 } else if (0==strcmp(sigmethod, OAUTH_SIG_METHOD_PLAINTEXT)) {
296 OAUTH_SIGCTX_PLAIN(ctx);
297 }
298
299 return ctx;
300 }
301 /* }}} */
302
303 zend_string *soo_sign(php_so_object *soo, char *message, zval *cs, zval *ts, const oauth_sig_context *ctx) /* {{{ */
304 {
305 const char *csec = cs?Z_STRVAL_P(cs):"", *tsec = ts?Z_STRVAL_P(ts):"";
306
307 if (OAUTH_SIGCTX_TYPE_HMAC==ctx->type) {
308 return soo_sign_hmac(soo, message, csec, tsec, ctx);
309 } else if (OAUTH_SIGCTX_TYPE_RSA==ctx->type) {
310 return soo_sign_rsa(soo, message, ctx);
311 } else if(OAUTH_SIGCTX_TYPE_PLAIN==ctx->type) {
312 return soo_sign_plain(soo, csec, tsec);
313 }
314 return NULL;
315 }
316 /* }}} */
317
318 static inline zval *soo_get_property(php_so_object *soo, char *prop_name) /* {{{ */
319 {
320 return zend_hash_str_find(soo->properties, prop_name, strlen(prop_name));
321 }
322 /* }}} */
323
324 /* XXX for auth type, need to make sure that the auth type is actually supported before setting */
325 static inline int soo_set_property(php_so_object *soo, zval *prop, char *prop_name) /* {{{ */
326 {
327 return (zend_hash_str_update(soo->properties, prop_name, strlen(prop_name), prop) == NULL) ? FAILURE : SUCCESS;
328 }
329 /* }}} */
330
331 zend_string *oauth_url_encode(char *url, int url_len) /* {{{ */
332 {
333 zend_string *urlencoded = NULL;
334 zend_string *ret = NULL;
335
336 if (url) {
337 if (url_len < 0) {
338 url_len = strlen(url);
339 }
340 urlencoded = php_raw_url_encode(url, url_len);
341 }
342
343 if (urlencoded) {
344 ret = php_str_to_str(ZSTR_VAL(urlencoded), ZSTR_LEN(urlencoded), "%7E", sizeof("%7E")-1, "~", sizeof("~")-1);
345 zend_string_free(urlencoded);
346 return ret;
347 }
348 return NULL;
349 }
350 /* }}} */
351
352 zend_string *oauth_http_encode_value(zval *v) /* {{{ */
353 {
354 zend_string *param_value = NULL;
355
356 switch (Z_TYPE_P(v)) {
357 case IS_STRING:
358 param_value = oauth_url_encode(Z_STRVAL_P(v), Z_STRLEN_P(v));
359 break;
360 default:
361 SEPARATE_ZVAL(v);
362 convert_to_string_ex(v);
363 param_value = oauth_url_encode(Z_STRVAL_P(v), Z_STRLEN_P(v));
364 }
365
366 return param_value;
367 }
368 /* }}} */
369
370 static int oauth_strcmp(zval *first, zval *second) /* {{{ */
371 {
372 int result;
373 result = string_compare_function(first, second);
374
375 if (result < 0) {
376 return -1;
377 } else if (result > 0) {
378 return 1;
379 }
380
381 return 0;
382 }
383 /* }}} */
384
385 #if PHP_VERSION_ID < 80000
386 static int oauth_compare_value(const void *a, const void *b) /* {{{ */
387 {
388 Bucket *f, *s;
389 f = (Bucket *)a;
390 s = (Bucket *)b;
391
392 #else
393 static int oauth_compare_value(Bucket *f, Bucket *s) /* {{{ */
394 {
395 #endif
396 return oauth_strcmp(&f->val, &s->val);
397 }
398 /* }}} */
399
400 #if PHP_VERSION_ID < 80000
401 static int oauth_compare_key(const void *a, const void *b) /* {{{ */
402 {
403 Bucket *f = (Bucket *)a, *s = (Bucket *)b;
404 #else
405 static int oauth_compare_key(Bucket *f, Bucket *s) /* {{{ */
406 {
407 #endif
408 zval first, second;
409 int result;
410
411 if (f->key == NULL) {
412 ZVAL_LONG(&first, f->h);
413 } else {
414 ZVAL_STRINGL(&first, ZSTR_VAL(f->key), ZSTR_LEN(f->key));
415 }
416
417 if (s->key == NULL) {
418 ZVAL_LONG(&second, s->h);
419 } else {
420 ZVAL_STRINGL(&second, ZSTR_VAL(s->key), ZSTR_LEN(s->key));
421 }
422
423 result = oauth_strcmp(&first, &second);
424 zval_ptr_dtor(&first);
425 zval_ptr_dtor(&second);
426 return result;
427 }
428 /* }}} */
429
430 /* build url-encoded string from args, optionally starting with & */
431 int oauth_http_build_query(php_so_object *soo, smart_string *s, HashTable *args, zend_bool prepend_amp) /* {{{ */
432 {
433 zval *cur_val;
434 zend_string *cur_key, *arg_key, *param_value;
435 int numargs = 0, hash_key_type, skip_append = 0, i, found;
436 zend_ulong num_index;
437 HashPosition pos;
438 smart_string keyname;
439
440 smart_string_0(s);
441 if (args) {
442 if (soo && !soo->is_multipart) {
443 for (zend_hash_internal_pointer_reset_ex(args, &pos);
444 HASH_KEY_NON_EXISTENT != (hash_key_type = zend_hash_get_current_key_ex(args, &cur_key, &num_index, &pos));
445 zend_hash_move_forward_ex(args, &pos)) {
446 cur_val = zend_hash_get_current_data_ex(args, &pos);
447 if (hash_key_type == HASH_KEY_IS_STRING &&
448 *ZSTR_VAL(cur_key) =='@' && *Z_STRVAL_P(cur_val) =='@') {
449 soo->is_multipart = 1;
450 break;
451 }
452 }
453 }
454
455 for (zend_hash_internal_pointer_reset_ex(args, &pos);
456 HASH_KEY_NON_EXISTENT != (hash_key_type = zend_hash_get_current_key_ex(args, &cur_key, &num_index, &pos));
457 zend_hash_move_forward_ex(args, &pos)) {
458 (cur_val = zend_hash_get_current_data_ex(args, &pos));
459
460 skip_append = 0;
461
462 switch (hash_key_type) {
463 case HASH_KEY_IS_STRING:
464 if (soo && soo->is_multipart && strncmp(ZSTR_VAL(cur_key), "oauth_", 6) != 0) {
465 found = 0;
466 for (i=0; i<soo->multipart_files_num; ++i) {
467 if (0 == strcmp(soo->multipart_params[i], ZSTR_VAL(cur_key))) {
468 found = 1;
469 break;
470 }
471 }
472
473 if (found) {
474 continue;
475 }
476
477 soo->multipart_files = erealloc(soo->multipart_files, sizeof(char *) * (soo->multipart_files_num + 1));
478 soo->multipart_params = erealloc(soo->multipart_params, sizeof(char *) * (soo->multipart_files_num + 1));
479
480 convert_to_string_ex(cur_val);
481 soo->multipart_files[soo->multipart_files_num] = Z_STRVAL_P(cur_val);
482 soo->multipart_params[soo->multipart_files_num] = ZSTR_VAL(cur_key);
483
484 ++soo->multipart_files_num;
485 /* we don't add multipart files to the params */
486 skip_append = 1;
487 } else {
488 arg_key = oauth_url_encode(ZSTR_VAL(cur_key), ZSTR_LEN(cur_key));
489 }
490 break;
491
492 case HASH_KEY_IS_LONG:
493 /* take value of num_index instead */
494 arg_key = NULL;
495 break;
496
497 default:
498 continue;
499 }
500
501 if (skip_append) {
502 continue;
503 }
504
505 INIT_smart_string(keyname);
506 if (arg_key) {
507 smart_string_appends(&keyname, ZSTR_VAL(arg_key));
508 zend_string_release(arg_key);
509 } else {
510 smart_string_append_unsigned(&keyname, num_index);
511 }
512 if (IS_ARRAY == Z_TYPE_P(cur_val)) {
513 HashPosition val_pos;
514 zval *val_cur_val;
515
516 /* make shallow copy */
517 SEPARATE_ZVAL(cur_val);
518 /* sort array based on string comparison */
519 zend_hash_sort(Z_ARRVAL_P(cur_val), oauth_compare_value, 1);
520
521 /* traverse array */
522 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(cur_val), &val_pos);
523 while ((val_cur_val = zend_hash_get_current_data_ex(Z_ARRVAL_P(cur_val), &val_pos)) != NULL) {
524 if (prepend_amp) {
525 smart_string_appendc(s, '&');
526 }
527
528 smart_string_append(s, &keyname);
529 param_value = oauth_http_encode_value(val_cur_val);
530 if (param_value) {
531 smart_string_appendc(s, '=');
532 smart_string_appends(s, ZSTR_VAL(param_value));
533 zend_string_release(param_value);
534 }
535 prepend_amp = TRUE;
536 ++numargs;
537 zend_hash_move_forward_ex(Z_ARRVAL_P(cur_val), &val_pos);
538 }
539 /* clean up */
540 } else {
541 if (prepend_amp) {
542 smart_string_appendc(s, '&');
543 }
544 smart_string_append(s, &keyname);
545 param_value = oauth_http_encode_value(cur_val);
546 if (param_value) {
547 smart_string_appendc(s, '=');
548 smart_string_appends(s, ZSTR_VAL(param_value));
549 zend_string_release(param_value);
550 }
551 prepend_amp = TRUE;
552 ++numargs;
553 }
554 smart_string_free(&keyname);
555
556 smart_string_0(s);
557 }
558 }
559 return numargs;
560 }
561 /* }}} */
562
563 /* retrieves parameter value from the _GET or _POST superglobal */
564 void get_request_param(char *arg_name, char **return_val, int *return_len) /* {{{ */
565 {
566 zval *ptr;
567 if (
568 (Z_TYPE(PG(http_globals)[TRACK_VARS_GET]) != IS_UNDEF && (ptr = zend_hash_str_find(HASH_OF(&(PG(http_globals)[TRACK_VARS_GET])), arg_name, strlen(arg_name))) != NULL && IS_STRING == Z_TYPE_P(ptr)) ||
569 (Z_TYPE(PG(http_globals)[TRACK_VARS_POST])!= IS_UNDEF && (ptr = zend_hash_str_find(HASH_OF(&(PG(http_globals)[TRACK_VARS_POST])), arg_name, strlen(arg_name))) != NULL && IS_STRING == Z_TYPE_P(ptr))
570 ) {
571 *return_val = Z_STRVAL_P(ptr);
572 *return_len = Z_STRLEN_P(ptr);
573 return;
574 }
575 *return_val = NULL;
576 *return_len = 0;
577 }
578 /* }}} */
579
580 /*
581 * This function does not currently care to respect parameter precedence, in the sense that if a common param is defined
582 * in POST/GET or Authorization header, the precendence is defined by: OAuth Core 1.0 section 9.1.1
583 */
584 zend_string *oauth_generate_sig_base(php_so_object *soo, const char *http_method, const char *uri, HashTable *post_args, HashTable *extra_args) /* {{{ */
585 {
586 zval params;
587 char *query;
588 char *s_port = NULL;
589 zend_string *bufz = NULL;
590 zend_string *sbs_query_part = NULL, *sbs_scheme_part = NULL;
591 php_url *urlparts;
592 smart_string sbuf = {0};
593
594 urlparts = php_url_parse_ex(uri, strlen(uri));
595
596 if (urlparts) {
597 if (!urlparts->host || !urlparts->scheme) {
598 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid url when trying to build base signature string", NULL, NULL);
599 php_url_free(urlparts);
600 return NULL;
601 }
602 php_strtolower(OAUTH_URL_STR(urlparts->scheme), OAUTH_URL_LEN(urlparts->scheme));
603 php_strtolower(OAUTH_URL_STR(urlparts->host), OAUTH_URL_LEN(urlparts->host));
604 smart_string_appends(&sbuf, OAUTH_URL_STR(urlparts->scheme));
605 smart_string_appends(&sbuf, "://");
606 smart_string_appends(&sbuf, OAUTH_URL_STR(urlparts->host));
607
608 if (urlparts->port && ((!strcmp("http", OAUTH_URL_STR(urlparts->scheme)) && OAUTH_HTTP_PORT != urlparts->port)
609 || (!strcmp("https", OAUTH_URL_STR(urlparts->scheme)) && OAUTH_HTTPS_PORT != urlparts->port))) {
610 spprintf(&s_port, 0, "%d", urlparts->port);
611 smart_string_appendc(&sbuf, ':');
612 smart_string_appends(&sbuf, s_port);
613 efree(s_port);
614 }
615
616 if (urlparts->path) {
617 smart_string squery = {0};
618 smart_string_appends(&sbuf, OAUTH_URL_STR(urlparts->path));
619 smart_string_0(&sbuf);
620
621 array_init(¶ms);
622
623 /* merge order = oauth_args - extra_args - query */
624 if (post_args) {
625 zend_hash_merge(Z_ARRVAL(params), post_args, (copy_ctor_func_t) zval_add_ref, 0);
626 }
627
628 if (extra_args) {
629 zend_hash_merge(Z_ARRVAL(params), extra_args, (copy_ctor_func_t) zval_add_ref, 0);
630 }
631
632 if (urlparts->query) {
633 query = estrdup(OAUTH_URL_STR(urlparts->query));
634 oauth_parse_str(query, ¶ms);
635 efree(query);
636 }
637
638 /* remove oauth_signature if it's in the hash */
639 zend_hash_str_del(Z_ARRVAL(params), OAUTH_PARAM_SIGNATURE, sizeof(OAUTH_PARAM_SIGNATURE) - 1);
640
641 /* exret2 = uksort(&exargs2[0], "strnatcmp") */
642 zend_hash_sort(Z_ARRVAL(params), oauth_compare_key, 0);
643
644 oauth_http_build_query(soo, &squery, Z_ARRVAL(params), FALSE);
645 smart_string_0(&squery);
646 zval_ptr_dtor(¶ms);
647
648 sbs_query_part = oauth_url_encode(squery.c, squery.len);
649 sbs_scheme_part = oauth_url_encode(sbuf.c, sbuf.len);
650
651 bufz = strpprintf(0, "%s&%s&%s", http_method, ZSTR_VAL(sbs_scheme_part), sbs_query_part ? ZSTR_VAL(sbs_query_part) : "");
652 /* TODO move this into oauth_get_http_method()
653 soo_handle_error(OAUTH_ERR_INTERNAL_ERROR, "Invalid auth type", NULL);
654 */
655 if(sbs_query_part) {
656 zend_string_release(sbs_query_part);
657 }
658 if(sbs_scheme_part) {
659 zend_string_release(sbs_scheme_part);
660 }
661 smart_string_free(&squery);
662 } else {
663 /* Bug 22630 - throw exception if no path given */
664 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid path (perhaps you only specified the hostname? try adding a slash at the end)", NULL, NULL);
665 return NULL;
666 }
667
668 smart_string_free(&sbuf);
669
670 php_url_free(urlparts);
671
672 if(soo && soo->debug) {
673 if(soo->debug_info->sbs) {
674 zend_string_release(soo->debug_info->sbs);
675 }
676
677 if (bufz) {
678 soo->debug_info->sbs = bufz;
679 zend_string_addref(soo->debug_info->sbs);
680 } else {
681 soo->debug_info->sbs = NULL;
682 }
683 }
684 return bufz;
685 }
686 return NULL;
687 }
688 /* }}} */
689
690 static void oauth_set_debug_info(php_so_object *soo) /* {{{ */
691 {
692 zval *debugInfo;
693 if (soo->debug_info) {
694 debugInfo = &soo->debugArr;
695
696 if (Z_TYPE_P(debugInfo) != IS_UNDEF) {
697 zval_ptr_dtor(debugInfo);
698 }
699 array_init(debugInfo);
700
701 if(soo->debug_info->sbs) {
702 add_assoc_string(debugInfo, "sbs", ZSTR_VAL(soo->debug_info->sbs));
703 }
704
705 ADD_DEBUG_INFO(debugInfo, "headers_sent", soo->debug_info->headers_out, 1);
706 ADD_DEBUG_INFO(debugInfo, "headers_recv", soo->headers_in, 1);
707 ADD_DEBUG_INFO(debugInfo, "body_sent", soo->debug_info->body_out, 0);
708 ADD_DEBUG_INFO(debugInfo, "body_recv", soo->debug_info->body_in, 0);
709 ADD_DEBUG_INFO(debugInfo, "info", soo->debug_info->curl_info, 0);
710
711 zend_update_property(soo_class_entry, OBJ_FOR_PROP(soo->this_ptr), "debugInfo", sizeof("debugInfo") - 1, debugInfo);
712 } else {
713 ZVAL_UNDEF(&soo->debugArr);
714 }
715 }
716 /* }}} */
717
718 static int add_arg_for_req(HashTable *ht, const char *arg, const char *val) /* {{{ */
719 {
720 zval varg;
721
722 ZVAL_STRING(&varg, (char *)val);
723 zend_hash_str_update(ht, (char *)arg, strlen(arg), &varg);
724
725 return SUCCESS;
726 }
727 /* }}} */
728
729 void oauth_add_signature_header(HashTable *request_headers, HashTable *oauth_args, smart_string *header) /* {{{ */
730 {
731 smart_string sheader = {0};
732 zend_bool prepend_comma = FALSE;
733
734 zval *curval;
735 zend_string *param_name, *param_val;
736 zend_string *cur_key;
737 zend_ulong num_key;
738 HashPosition pos;
739
740 smart_string_appends(&sheader, "OAuth ");
741
742 for (zend_hash_internal_pointer_reset_ex(oauth_args, &pos);
743 (curval = zend_hash_get_current_data_ex(oauth_args, &pos)) != NULL;
744 zend_hash_move_forward_ex(oauth_args, &pos)) {
745 zend_hash_get_current_key_ex(oauth_args, &cur_key, &num_key, &pos);
746
747 if (prepend_comma) {
748 smart_string_appendc(&sheader, ',');
749 }
750 param_name = oauth_url_encode(ZSTR_VAL(cur_key), ZSTR_LEN(cur_key));
751 param_val = oauth_url_encode(Z_STRVAL_P(curval), Z_STRLEN_P(curval));
752
753 smart_string_appends(&sheader, ZSTR_VAL(param_name));
754 smart_string_appendc(&sheader, '=');
755 smart_string_appends(&sheader, "\"");
756 smart_string_appends(&sheader, ZSTR_VAL(param_val));
757 smart_string_appends(&sheader, "\"");
758
759 efree(param_name);
760 efree(param_val);
761 prepend_comma = TRUE;
762 }
763 smart_string_0(&sheader);
764
765 if (!header) {
766 add_arg_for_req(request_headers, "Authorization", sheader.c);
767 } else {
768 smart_string_appends(header, sheader.c);
769 }
770 smart_string_free(&sheader);
771 }
772 /* }}} */
773
774 #define HTTP_RESPONSE_CAAS(zvalp, header, storkey) { \
775 if (0==strncasecmp(Z_STRVAL_P(zvalp),header,sizeof(header)-1)) { \
776 CAAS(storkey, (Z_STRVAL_P(zvalp)+sizeof(header)-1)); \
777 } \
778 }
779
780 #define HTTP_RESPONSE_CAAD(zvalp, header, storkey) { \
781 if (0==strncasecmp(Z_STRVAL_P(zvalp),header,sizeof(header)-1)) { \
782 CAAD(storkey, strtoul(Z_STRVAL_P(zvalp)+sizeof(header)-1,NULL,10)); \
783 } \
784 }
785
786 #define HTTP_RESPONSE_CODE(zvalp) \
787 if (response_code < 0 && 0==strncasecmp(Z_STRVAL_P(zvalp),"HTTP/", 5) && Z_STRLEN_P(zvalp)>=12) { \
788 response_code = strtol(Z_STRVAL_P(zvalp)+9, NULL, 10); \
789 CAAL("http_code", response_code); \
790 }
791
792 #define HTTP_RESPONSE_LOCATION(zvalp) \
793 if (0==strncasecmp(Z_STRVAL_P(zvalp), "Location: ", 10)) { \
794 strlcpy(soo->last_location_header, Z_STRVAL_P(zvalp)+10, OAUTH_MAX_HEADER_LEN); \
795 }
796
797 static long make_req_streams(php_so_object *soo, const char *url, const smart_string *payload, const char *http_method, HashTable *request_headers) /* {{{ */
798 {
799 php_stream_context *sc;
800 zval zpayload, zmethod, zredirects, zerrign;
801 long response_code = -1;
802 php_stream *s;
803 int set_form_content_type = 0;
804 php_netstream_data_t *sock;
805 struct timeval tv;
806 int secs = 0;
807
808 sc = php_stream_context_alloc();
809
810 if (payload->len) {
811 ZVAL_STRINGL(&zpayload, payload->c, payload->len);
812 Z_STRVAL(zpayload)[Z_STRLEN(zpayload)] = '\0';
813 php_stream_context_set_option(sc, "http", "content", &zpayload);
814 zval_ptr_dtor(&zpayload);
815 /**
816 * remember to set application/x-www-form-urlencoded content-type later on
817 * lest the php streams guys come and beat you up
818 */
819 set_form_content_type = 1;
820 }
821
822 if (request_headers) {
823 HashPosition pos;
824 zval *cur_val, zheaders;
825 zend_string *cur_key;
826 zend_ulong num_key;
827 smart_string sheaders = {0};
828 int first = 1;
829
830 for (zend_hash_internal_pointer_reset_ex(request_headers, &pos);
831 (cur_val = zend_hash_get_current_data_ex(request_headers, &pos)) != NULL;
832 zend_hash_move_forward_ex(request_headers, &pos)) {
833 /* check if a string based key is used */
834 smart_string sheaderline = {0};
835 switch ((int)zend_hash_get_current_key_ex(request_headers, &cur_key, &num_key, &pos)) {
836 case HASH_KEY_IS_STRING:
837 smart_string_appendl(&sheaderline, ZSTR_VAL(cur_key), ZSTR_LEN(cur_key));
838 break;
839 default:
840 continue;
841 }
842 smart_string_0(&sheaderline);
843 if (!strcasecmp(sheaderline.c,"content-type")) {
844 set_form_content_type = 0;
845 }
846 smart_string_appends(&sheaderline, ": ");
847 switch (Z_TYPE_P(cur_val)) {
848 case IS_STRING:
849 smart_string_appendl(&sheaderline, Z_STRVAL_P(cur_val), Z_STRLEN_P(cur_val));
850 break;
851 default:
852 smart_string_free(&sheaderline);
853 continue;
854 }
855 if (!first) {
856 smart_string_appends(&sheaders, "\r\n");
857 } else {
858 first = 0;
859 }
860 smart_string_append(&sheaders, &sheaderline);
861 smart_string_free(&sheaderline);
862 }
863 if (set_form_content_type) {
864 /* still need to add our own content-type? */
865 if (!first) {
866 smart_string_appends(&sheaders, "\r\n");
867 }
868 smart_string_appends(&sheaders, "Content-Type: application/x-www-form-urlencoded");
869 }
870 if (sheaders.len) {
871 smart_string_0(&sheaders);
872 ZVAL_STRINGL(&zheaders, sheaders.c, sheaders.len);
873 php_stream_context_set_option(sc, "http", "header", &zheaders);
874 zval_ptr_dtor(&zheaders);
875 if (soo->debug) {
876 smart_string_append(&soo->debug_info->headers_out, &sheaders);
877 }
878 }
879 smart_string_free(&sheaders);
880 }
881 /* set method */
882 ZVAL_STRING(&zmethod, http_method);
883 php_stream_context_set_option(sc, "http", "method", &zmethod);
884 zval_ptr_dtor(&zmethod);
885 /* set maximum redirects; who came up with the ridiculous logic of <= 1 means no redirects ?? */
886 ZVAL_LONG(&zredirects, 1L);
887 php_stream_context_set_option(sc, "http", "max_redirects", &zredirects);
888 /* using special extension to treat redirects as regular document (requires patch in php) */
889 ZVAL_BOOL(&zerrign, TRUE);
890 php_stream_context_set_option(sc, "http", "ignore_errors", &zerrign);
891
892 smart_string_free(&soo->lastresponse);
893 smart_string_free(&soo->headers_in);
894
895 if ((s = php_stream_open_wrapper_ex((char*)url, "rb", REPORT_ERRORS, NULL, sc))) {
896 zval info;
897 zend_string *buf;
898 size_t rb = 0;
899
900 array_init(&info);
901
902 CAAS("url", url);
903
904 if (Z_TYPE(s->wrapperdata) != IS_UNDEF) {
905 zval *tmp;
906 HashPosition pos;
907
908 zend_hash_internal_pointer_reset_ex(Z_ARRVAL(s->wrapperdata), &pos);
909 while ((tmp = zend_hash_get_current_data_ex(Z_ARRVAL(s->wrapperdata), &pos)) != NULL) {
910 smart_string_appendl(&soo->headers_in, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
911 smart_string_appends(&soo->headers_in, "\r\n");
912 HTTP_RESPONSE_CODE(tmp);
913 HTTP_RESPONSE_LOCATION(tmp);
914 HTTP_RESPONSE_CAAS(tmp, "Content-Type: ", "content_type");
915 HTTP_RESPONSE_CAAD(tmp, "Content-Length: ", "download_content_length");
916 zend_hash_move_forward_ex(Z_ARRVAL(s->wrapperdata), &pos);
917 }
918 if (HTTP_IS_REDIRECT(response_code) && soo->last_location_header) {
919 CAAS("redirect_url", soo->last_location_header);
920 }
921 }
922
923 if(soo->timeout) {
924 sock = (php_netstream_data_t*)s->abstract;
925 secs = soo->timeout / 1000;
926 tv.tv_sec = secs;
927 tv.tv_usec = ((soo->timeout - (secs * 1000)) * 1000) % 1000000;
928 sock->timeout = tv;
929 }
930
931 if ((buf = php_stream_copy_to_mem(s, PHP_STREAM_COPY_ALL, 0)) != NULL) {
932 smart_string_appendl(&soo->lastresponse, ZSTR_VAL(buf), ZSTR_LEN(buf));
933 rb = ZSTR_LEN(buf);
934 zend_string_release(buf);
935 }
936 smart_string_0(&soo->lastresponse);
937 smart_string_0(&soo->headers_in);
938
939 CAAD("size_download", rb);
940 CAAD("size_upload", payload->len);
941
942 so_set_response_info(soo->properties, &info);
943
944 php_stream_close(s);
945 } else {
946 char *bufz;
947
948 spprintf(&bufz, 0, "making the request failed (%s)", "dunno why");
949 soo_handle_error(soo, -1, bufz, soo->lastresponse.c, NULL);
950 efree(bufz);
951 }
952
953 if(soo->debug) {
954 smart_string_append(&soo->debug_info->body_in, &soo->lastresponse);
955 smart_string_append(&soo->debug_info->body_out, payload);
956 }
957
958 return response_code;
959 }
960 /* }}} */
961
962 #if OAUTH_USE_CURL
963 static size_t soo_read_response(char *ptr, size_t size, size_t nmemb, void *ctx) /* {{{ */
964 {
965 size_t relsize;
966 php_so_object *soo = (php_so_object *)ctx;
967
968 relsize = size * nmemb;
969 smart_string_appendl(&soo->lastresponse, ptr, relsize);
970
971 return relsize;
972 }
973 /* }}} */
974
975 int oauth_debug_handler(CURL *ch, curl_infotype type, char *data, size_t data_len, void *ctx) /* {{{ */
976 {
977 php_so_debug *sdbg;
978 char *z_data = NULL;
979 smart_string *dest;
980
981 if(data_len > 1 && data[0]=='\r' && data[1]=='\n') { /* ignore \r\n */
982 return 0;
983 }
984
985 sdbg = (php_so_debug *)ctx;
986 z_data = emalloc(data_len + 2);
987 memset(z_data, 0, data_len + 2);
988 memcpy(z_data, data, data_len);
989 z_data[data_len] = '\0';
990
991 switch(type) {
992 case CURLINFO_TEXT:
993 dest = &sdbg->curl_info;
994 break;
995 case CURLINFO_HEADER_OUT:
996 dest = &sdbg->headers_out;
997 break;
998 case CURLINFO_DATA_IN:
999 dest = &sdbg->body_in;
1000 break;
1001 case CURLINFO_DATA_OUT:
1002 dest = &sdbg->body_out;
1003 break;
1004 default:
1005 dest = NULL;
1006 }
1007
1008 if(dest) {
1009 smart_string_appends(dest, z_data);
1010 }
1011 efree(z_data);
1012
1013 return 0;
1014 }
1015 /* }}} */
1016
1017 static size_t soo_read_header(void *ptr, size_t size, size_t nmemb, void *ctx) /* {{{ */
1018 {
1019 char *header;
1020 size_t hlen, vpos = sizeof("Location:") - 1;
1021 php_so_object *soo;
1022
1023 header = (char *)ptr;
1024 hlen = nmemb * size;
1025 soo = (php_so_object *)ctx;
1026
1027 /* handle Location header */
1028 if (hlen > vpos && 0==strncasecmp(header, "Location:", vpos)) {
1029 size_t eol = hlen;
1030 /* find value start */
1031 while (vpos != eol && ' '==header[vpos]) {
1032 ++vpos;
1033 }
1034 /* POST: vpos == eol OR vpos < eol => value start found */
1035 while (vpos != eol && strchr("\r\n\0", header[eol - 1])) {
1036 --eol;
1037 }
1038 /* POST: vpos == eol OR vpos < eol => value end found */
1039 if (vpos != eol) {
1040 if (eol - vpos >= OAUTH_MAX_HEADER_LEN) {
1041 eol = vpos + OAUTH_MAX_HEADER_LEN - 1;
1042 }
1043 /* POST: eol - vpos <= OAUTH_MAX_HEADER_LEN */
1044 strncpy(soo->last_location_header, header + vpos, eol - vpos);
1045 }
1046 soo->last_location_header[eol - vpos] = '\0';
1047 }
1048 if(strncasecmp(header, "\r\n", 2)) {
1049 smart_string_appendl(&soo->headers_in, header, hlen);
1050 }
1051 return hlen;
1052 }
1053 /* }}} */
1054
1055 long make_req_curl(php_so_object *soo, const char *url, const smart_string *payload, const char *http_method, HashTable *request_headers) /* {{{ */
1056 {
1057 CURLcode cres, ctres, crres;
1058 CURL *curl;
1059 struct curl_slist *curl_headers = NULL;
1060 long l_code, response_code = -1;
1061 double d_code;
1062 zval info, *zca_info, *zca_path, *cur_val;
1063 char *s_code, *content_type = NULL, *bufz = NULL;
1064 uint32_t sslcheck;
1065 zend_ulong num_key;
1066 smart_string sheader = {0};
1067 zend_string *cur_key;
1068 HashPosition pos;
1069
1070 zca_info = soo_get_property(soo, OAUTH_ATTR_CA_INFO);
1071 zca_path = soo_get_property(soo, OAUTH_ATTR_CA_PATH);
1072 sslcheck = soo->sslcheck;
1073
1074 curl = curl_easy_init();
1075
1076 if (request_headers) {
1077 for (zend_hash_internal_pointer_reset_ex(request_headers, &pos);
1078 (cur_val = zend_hash_get_current_data_ex(request_headers, &pos)) != NULL;
1079 zend_hash_move_forward_ex(request_headers, &pos)) {
1080 /* check if a string based key is used */
1081 switch ((int)zend_hash_get_current_key_ex(request_headers, &cur_key, &num_key, &pos)) {
1082 case HASH_KEY_IS_STRING:
1083 smart_string_appendl(&sheader, ZSTR_VAL(cur_key), ZSTR_LEN(cur_key));
1084 break;
1085 default:
1086 continue;
1087 }
1088 smart_string_appends(&sheader, ": ");
1089 switch (Z_TYPE_P(cur_val)) {
1090 case IS_STRING:
1091 smart_string_appendl(&sheader, Z_STRVAL_P(cur_val), Z_STRLEN_P(cur_val));
1092 break;
1093 default:
1094 smart_string_free(&sheader);
1095 continue;
1096 }
1097
1098 smart_string_0(&sheader);
1099 curl_headers = curl_slist_append(curl_headers, sheader.c);
1100 smart_string_free(&sheader);
1101 }
1102 }
1103
1104 if(soo->is_multipart) {
1105 struct curl_httppost *ff = NULL;
1106 struct curl_httppost *lf = NULL;
1107 int i;
1108
1109 for(i=0; i < soo->multipart_files_num; i++) {
1110 char *type, *filename, *postval;
1111
1112 /* swiped from ext/curl/interface.c to help with consistency */
1113 postval = estrdup(soo->multipart_files[i]);
1114
1115 if (postval[0] == '@' && soo->multipart_params[i][0] == '@') {
1116 /* :< (chomp) @ */
1117 ++soo->multipart_params[i];
1118 ++postval;
1119
1120 if((type = (char *) php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) {
1121 *type = '\0';
1122 }
1123 if((filename = (char *) php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + strlen(soo->multipart_files[i]) - 1))) {
1124 *filename = '\0';
1125 }
1126
1127 /* open_basedir check */
1128 if(php_check_open_basedir(postval)) {
1129 char *em;
1130 spprintf(&em, 0, "failed to open file for multipart request: %s", postval);
1131 soo_handle_error(soo, -1, em, NULL, NULL);
1132 efree(em);
1133 return 1;
1134 }
1135
1136 curl_formadd(&ff, &lf,
1137 CURLFORM_COPYNAME, soo->multipart_params[i],
1138 CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]),
1139 CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : soo->multipart_files[i],
1140 CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream",
1141 CURLFORM_FILE, postval,
1142 CURLFORM_END);
1143 } else {
1144 curl_formadd(&ff, &lf,
1145 CURLFORM_COPYNAME, soo->multipart_params[i],
1146 CURLFORM_NAMELENGTH, (long)strlen(soo->multipart_params[i]),
1147 CURLFORM_COPYCONTENTS, postval,
1148 CURLFORM_CONTENTSLENGTH, (long)strlen(postval),
1149 CURLFORM_END);
1150 }
1151 }
1152
1153 curl_easy_setopt(curl, CURLOPT_HTTPPOST, ff);
1154 } else if (payload->len) {
1155 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload->c);
1156 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, payload->len);
1157 }
1158
1159 curl_easy_setopt(curl, CURLOPT_URL, url);
1160
1161 /* the fetch method takes precedence so figure it out after we've added the OAuth params */
1162 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_method);
1163
1164 /* Disable sending the 100 Expect header for POST requests */
1165 /* Other notes: if there is a redirect the POST becomes a GET request, see curl_easy_setopt(3) and the CURLOPT_POSTREDIR option for more information */
1166 curl_headers = curl_slist_append(curl_headers, "Expect:");
1167 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
1168 curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT);
1169 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, soo_read_response);
1170 curl_easy_setopt(curl, CURLOPT_WRITEDATA, soo);
1171 if(sslcheck == OAUTH_SSLCHECK_NONE) {
1172 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
1173 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
1174 } else {
1175 if (!(sslcheck & OAUTH_SSLCHECK_HOST)) {
1176 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
1177 }
1178 if (!(sslcheck & OAUTH_SSLCHECK_PEER)) {
1179 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
1180 }
1181 if(zca_path && Z_STRLEN_P(zca_path)) {
1182 curl_easy_setopt(curl, CURLOPT_CAPATH, Z_STRVAL_P(zca_path));
1183 }
1184 if(zca_info && Z_STRLEN_P(zca_info)) {
1185 curl_easy_setopt(curl, CURLOPT_CAINFO, Z_STRVAL_P(zca_info));
1186 }
1187 }
1188 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, soo_read_header);
1189 curl_easy_setopt(curl, CURLOPT_WRITEHEADER, soo);
1190 if(soo->debug) {
1191 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
1192 }
1193 #if defined(ZTS)
1194 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
1195 #endif
1196
1197 #if LIBCURL_VERSION_NUM >= 0x071304
1198 curl_easy_setopt(curl, CURLOPT_PROTOCOLS, OAUTH_PROTOCOLS_ALLOWED);
1199 #endif
1200
1201 #if LIBCURL_VERSION_NUM > 0x071002
1202 if(soo->timeout) {
1203 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, soo->timeout);
1204 curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, soo->timeout);
1205 }
1206 #endif
1207
1208 smart_string_free(&soo->lastresponse);
1209 smart_string_free(&soo->headers_in);
1210
1211 if(soo->debug) {
1212 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, oauth_debug_handler);
1213 curl_easy_setopt(curl, CURLOPT_DEBUGDATA, soo->debug_info);
1214 }
1215
1216 cres = curl_easy_perform(curl);
1217
1218 smart_string_0(&soo->lastresponse);
1219 smart_string_0(&soo->headers_in);
1220
1221 if (curl_headers) {
1222 curl_slist_free_all(curl_headers);
1223 }
1224
1225 if (CURLE_OK == cres) {
1226 ctres = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type);
1227 crres = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
1228
1229 if (CURLE_OK == crres && ctres == CURLE_OK) {
1230 array_init(&info);
1231
1232 CAAL("http_code", response_code);
1233
1234 if (HTTP_IS_REDIRECT(response_code) && soo->last_location_header) {
1235 CAAS("redirect_url", soo->last_location_header);
1236 }
1237
1238 if (content_type != NULL) {
1239 CAAS("content_type", content_type);
1240 }
1241 if (curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) {
1242 CAAS("url", s_code);
1243 }
1244
1245 if (curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) {
1246 CAAL("header_size", l_code);
1247 }
1248 if (curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) {
1249 CAAL("request_size", l_code);
1250 }
1251 if (curl_easy_getinfo(curl, CURLINFO_FILETIME, &l_code) == CURLE_OK) {
1252 CAAL("filetime", l_code);
1253 }
1254 if (curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
1255 CAAL("ssl_verify_result", l_code);
1256 }
1257 if (curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) {
1258 CAAL("redirect_count", l_code);
1259 }
1260 if (curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME,&d_code) == CURLE_OK) {
1261 CAAD("total_time", d_code);
1262 }
1263 if (curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) {
1264 CAAD("namelookup_time", d_code);
1265 }
1266 if (curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) {
1267 CAAD("connect_time", d_code);
1268 }
1269 if (curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) {
1270 CAAD("pretransfer_time", d_code);
1271 }
1272 if (curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK){
1273 CAAD("size_upload", d_code);
1274 }
1275 if (curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK){
1276 CAAD("size_download", d_code);
1277 }
1278 if (curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK){
1279 CAAD("speed_download", d_code);
1280 }
1281 if (curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK){
1282 CAAD("speed_upload", d_code);
1283 }
1284 if (curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) {
1285 CAAD("download_content_length", d_code);
1286 }
1287 if (curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) {
1288 CAAD("upload_content_length", d_code);
1289 }
1290 if (curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK){
1291 CAAD("starttransfer_time", d_code);
1292 }
1293 if (curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK){
1294 CAAD("redirect_time", d_code);
1295 }
1296
1297 CAAS("headers_recv", soo->headers_in.c);
1298
1299 so_set_response_info(soo->properties, &info);
1300 }
1301 } else {
1302 spprintf(&bufz, 0, "making the request failed (%s)", curl_easy_strerror(cres));
1303 soo_handle_error(soo, -1, bufz, soo->lastresponse.c, NULL);
1304 efree(bufz);
1305 }
1306 curl_easy_cleanup(curl);
1307 return response_code;
1308 }
1309 /* }}} */
1310 #endif
1311
1312 static void make_standard_query(HashTable *ht, php_so_object *soo) /* {{{ */
1313 {
1314 char *ts, *nonce;
1315
1316 if (soo->timestamp) {
1317 ts = estrdup(soo->timestamp);
1318 } else {
1319 time_t now = time(NULL);
1320 /* XXX allow caller to set timestamp, if none set, then default to "now" */
1321 spprintf(&ts, 0, "%d", (int)now);
1322 }
1323
1324 if (soo->nonce) {
1325 nonce = estrdup(soo->nonce);
1326 } else {
1327 struct timeval tv;
1328 int sec, usec;
1329 /* XXX maybe find a better way to generate a nonce... */
1330 gettimeofday((struct timeval *) &tv, (struct timezone *) NULL);
1331 sec = (int) tv.tv_sec;
1332 usec = (int) (tv.tv_usec % 0x100000);
1333 spprintf(&nonce, 0, "%ld%08x%05x%.8f", php_rand(), sec, usec, php_combined_lcg() * 10);
1334 }
1335
1336 add_arg_for_req(ht, OAUTH_PARAM_CONSUMER_KEY, Z_STRVAL_P(soo_get_property(soo, OAUTH_ATTR_CONSUMER_KEY)));
1337 add_arg_for_req(ht, OAUTH_PARAM_SIGNATURE_METHOD, Z_STRVAL_P(soo_get_property(soo, OAUTH_ATTR_SIGMETHOD)));
1338
1339 add_arg_for_req(ht, OAUTH_PARAM_NONCE, nonce);
1340
1341 add_arg_for_req(ht, OAUTH_PARAM_TIMESTAMP, ts);
1342 add_arg_for_req(ht, OAUTH_PARAM_VERSION, Z_STRVAL_P(soo_get_property(soo, OAUTH_ATTR_OAUTH_VERSION)));
1343
1344 efree(ts); efree(nonce);
1345 }
1346 /* }}} */
1347
1348 /*
1349 Returns the default http method to use with the different auth types
1350 */
1351 static const char *oauth_get_http_method(php_so_object *soo, const char *http_method) /* {{{ */
1352 {
1353 long auth_type = Z_LVAL_P(soo_get_property(soo, OAUTH_ATTR_AUTHMETHOD));
1354
1355 if (http_method) {
1356 /* TODO handle conflict with FORM auth and anything but POST or PUT */
1357 return http_method;
1358 }
1359 /* http method not explicitly given, choose default one */
1360 if (OAUTH_AUTH_TYPE_FORM == auth_type) {
1361 return OAUTH_HTTP_METHOD_POST;
1362 } else {
1363 return OAUTH_HTTP_METHOD_GET;
1364 }
1365 }
1366 /* }}} */
1367
1368 /*
1369 Modifies (and returns) passed url parameter to be used for additional parameter appending
1370 */
1371 static smart_string *http_prepare_url_concat(smart_string *surl) /* {{{ */
1372 {
1373 smart_string_0(surl);
1374 if (!strchr(surl->c, '?')) {
1375 smart_string_appendc(surl, '?');
1376 } else {
1377 smart_string_appendc(surl, '&');
1378 }
1379 return surl;
1380 }
1381 /* }}} */
1382
1383 /*
1384 Modifies passed url based on the location header that was received in the response headers, depending on whether the redirection was relative or absolute
1385 */
1386 static void oauth_apply_url_redirect(smart_string *surl, const char *location) /* {{{ */
1387 {
1388 php_url *urlparts;
1389
1390 /* determine whether location is relative */
1391 if ('/'==*location) {
1392 urlparts = php_url_parse_ex(surl->c, surl->len);
1393
1394 /* rebuild url from scratch */
1395 smart_string_free(surl);
1396 if (urlparts->scheme) {
1397 smart_string_appends(surl, OAUTH_URL_STR(urlparts->scheme));
1398 smart_string_appends(surl, "://");
1399 }
1400 if (urlparts->host) {
1401 smart_string_appends(surl, OAUTH_URL_STR(urlparts->host));
1402 }
1403 if (urlparts->port) {
1404 smart_string_appendc(surl, ':');
1405 smart_string_append_unsigned(surl, urlparts->port);
1406 }
1407 smart_string_appends(surl, location);
1408
1409 php_url_free(urlparts);
1410 } else {
1411 smart_string_free(surl);
1412 smart_string_appends(surl, location);
1413 }
1414 }
1415 /* }}} */
1416
1417 /*
1418 Prepares the request elements to be used by make_req(); this should allow for supporting streams in the future
1419 */
1420 static long oauth_fetch(php_so_object *soo, const char *url, const char *method, zval *request_params, zval *request_headers, HashTable *init_oauth_args, int fetch_flags) /* {{{ */
1421 {
1422 char *bufz = NULL;
1423 zend_string *sbs = NULL, *sig;
1424 const char *final_http_method;
1425 zval *token = NULL, *cs;
1426 zval *ts = NULL, *token_secret = NULL;
1427 zval zret;
1428 HashTable *oauth_args = NULL;
1429 HashTable *rargs = NULL, rheaders;
1430 long http_response_code, auth_type;
1431 smart_string surl = {0}, payload = {0}, postdata = {0};
1432 uint32_t is_redirect = FALSE, follow_redirects = 0;
1433
1434 auth_type = Z_LVAL_P(soo_get_property(soo, OAUTH_ATTR_AUTHMETHOD));
1435 if(fetch_flags & OAUTH_OVERRIDE_HTTP_METHOD) {
1436 final_http_method = method;
1437 } else {
1438 final_http_method = oauth_get_http_method(soo, method ? method : OAUTH_HTTP_METHOD_POST);
1439
1440 if (OAUTH_AUTH_TYPE_FORM==auth_type && strcasecmp(final_http_method, OAUTH_HTTP_METHOD_POST)) {
1441 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "auth type is set to HTTP POST with a non-POST http method, use setAuthType to put OAuth parameters somewhere else in the request", NULL, NULL);
1442 }
1443 }
1444
1445
1446 if(!final_http_method) {
1447 final_http_method = "GET";
1448 }
1449
1450 follow_redirects = soo->follow_redirects;
1451 soo->redirects = 0;
1452 soo->multipart_files = NULL;
1453 soo->multipart_params = NULL;
1454 soo->multipart_files_num = 0;
1455 soo->is_multipart = 0;
1456
1457 /* request_params can be either NULL, a string containing arbitrary text (such as XML) or an array */
1458 if (request_params) {
1459 switch (Z_TYPE_P(request_params)) {
1460 case IS_ARRAY:
1461 rargs = HASH_OF(request_params);
1462 oauth_http_build_query(soo, &postdata, rargs, FALSE);
1463 break;
1464 case IS_STRING:
1465 smart_string_appendl(&postdata, Z_STRVAL_P(request_params), Z_STRLEN_P(request_params));
1466 break;
1467 }
1468 }
1469
1470 /* additional http headers can be passed */
1471 zend_hash_init(&rheaders, 0, NULL, ZVAL_PTR_DTOR, 0);
1472 if (request_headers && zend_hash_num_elements(Z_ARRVAL_P(request_headers))) {
1473 zend_hash_copy(&rheaders, Z_ARRVAL_P(request_headers), (copy_ctor_func_t) zval_add_ref);
1474 }
1475
1476 /* initialize base url */
1477 smart_string_appends(&surl, url);
1478
1479 do {
1480 /* initialize response code */
1481 http_response_code = -1;
1482
1483 /* prepare oauth arguments to be signed */
1484 ALLOC_HASHTABLE(oauth_args);
1485 zend_hash_init(oauth_args, 0, NULL, ZVAL_PTR_DTOR, 0);
1486
1487 /* an array can be passed to prime special oauth parameters */
1488 if (init_oauth_args) {
1489 /* populate oauth_args with given parameters */
1490 zend_hash_copy(oauth_args, init_oauth_args, (copy_ctor_func_t) zval_add_ref);
1491 }
1492
1493 /* fill in the standard set of oauth parameters */
1494 make_standard_query(oauth_args, soo);
1495
1496 /* use token where applicable */
1497 if (fetch_flags & OAUTH_FETCH_USETOKEN) {
1498 token = soo_get_property(soo, OAUTH_ATTR_TOKEN);
1499 if (token) {
1500 add_arg_for_req(oauth_args, OAUTH_PARAM_TOKEN, Z_STRVAL_P(token));
1501 }
1502 }
1503
1504 /* generate sig base on the semi-final url */
1505 smart_string_0(&surl);
1506 sbs = oauth_generate_sig_base(soo, final_http_method, surl.c, oauth_args, rargs);
1507 if (!sbs) {
1508 FREE_ARGS_HASH(oauth_args);
1509 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid protected resource url, unable to generate signature base string", NULL, NULL);
1510 break;
1511 }
1512
1513 cs = soo_get_property(soo, OAUTH_ATTR_CONSUMER_SECRET);
1514 SEPARATE_ZVAL(cs);
1515
1516 /* determine whether token should be used to sign the request */
1517 if (fetch_flags & OAUTH_FETCH_USETOKEN) {
1518 token_secret = soo_get_property(soo, OAUTH_ATTR_TOKEN_SECRET);
1519 if (token_secret && Z_STRLEN_P(token_secret) > 0) {
1520 ts = token_secret;
1521 }
1522 }
1523
1524 if(soo->signature) {
1525 zend_string_release(soo->signature);
1526 }
1527 /* sign the request */
1528 sig = soo_sign(soo, ZSTR_VAL(sbs), cs, ts, soo->sig_ctx);
1529 soo->signature = sig;
1530 zend_string_release(sbs);
1531
1532 if(fetch_flags & OAUTH_FETCH_SIGONLY) {
1533 FREE_ARGS_HASH(oauth_args);
1534 smart_string_free(&surl);
1535 smart_string_free(&postdata);
1536 zend_hash_destroy(&rheaders);
1537 return SUCCESS;
1538 }
1539
1540 if (!sig) {
1541 FREE_ARGS_HASH(oauth_args);
1542 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Signature generation failed", NULL, NULL);
1543 break;
1544 }
1545
1546 /* and add signature to the oauth parameters */
1547 add_arg_for_req(oauth_args, OAUTH_PARAM_SIGNATURE, ZSTR_VAL(sig));
1548
1549 if(fetch_flags & OAUTH_FETCH_HEADONLY) {
1550 INIT_smart_string(soo->headers_out);
1551 oauth_add_signature_header(&rheaders, oauth_args, &soo->headers_out);
1552 smart_string_0(&payload);
1553 FREE_ARGS_HASH(oauth_args);
1554 smart_string_free(&surl);
1555 smart_string_free(&postdata);
1556 zend_hash_destroy(&rheaders);
1557 return SUCCESS;
1558 }
1559
1560 if (!strcmp(final_http_method, OAUTH_HTTP_METHOD_GET)) {
1561 /* GET request means to extend the url, but not for redirects obviously */
1562 if (!is_redirect && postdata.len) {
1563 smart_string_append(http_prepare_url_concat(&surl), &postdata);
1564 }
1565 } else {
1566 /* otherwise populate post data */
1567 smart_string_append(&payload, &postdata);
1568 }
1569
1570 switch (auth_type) {
1571 case OAUTH_AUTH_TYPE_FORM:
1572 /* append/set post data with oauth parameters */
1573 oauth_http_build_query(soo, &payload, oauth_args, payload.len);
1574 smart_string_0(&payload);
1575 break;
1576 case OAUTH_AUTH_TYPE_URI:
1577 /* extend url request with oauth parameters */
1578 if (!is_redirect) {
1579 oauth_http_build_query(soo, http_prepare_url_concat(&surl), oauth_args, FALSE);
1580 }
1581 /* TODO look into merging oauth parameters if they occur in the current url */
1582 break;
1583 case OAUTH_AUTH_TYPE_AUTHORIZATION:
1584 /* add http header with oauth parameters */
1585 oauth_add_signature_header(&rheaders, oauth_args, NULL);
1586 break;
1587 }
1588
1589 /* finalize endpoint url */
1590 smart_string_0(&surl);
1591
1592 if (soo->debug) {
1593 if(soo->debug_info->sbs) {
1594 FREE_DEBUG_INFO(soo->debug_info);
1595 }
1596 INIT_DEBUG_INFO(soo->debug_info);
1597 }
1598
1599 switch (soo->reqengine) {
1600 case OAUTH_REQENGINE_STREAMS:
1601 http_response_code = make_req_streams(soo, surl.c, &payload, final_http_method, &rheaders);
1602 break;
1603 #if OAUTH_USE_CURL
1604 case OAUTH_REQENGINE_CURL:
1605 http_response_code = make_req_curl(soo, surl.c, &payload, final_http_method, &rheaders);
1606 if (soo->multipart_files_num) {
1607 efree(soo->multipart_files);
1608 efree(soo->multipart_params);
1609 soo->multipart_files_num = 0;
1610 soo->is_multipart = 0;
1611 }
1612 break;
1613 #endif
1614 }
1615
1616 is_redirect = HTTP_IS_REDIRECT(http_response_code);
1617
1618 if(soo->debug) {
1619 oauth_set_debug_info(soo);
1620 }
1621
1622 FREE_ARGS_HASH(oauth_args);
1623 smart_string_free(&payload);
1624
1625 if (is_redirect) {
1626 if (follow_redirects) {
1627 if (soo->redirects >= OAUTH_MAX_REDIRS) {
1628 spprintf(&bufz, 0, "max redirections exceeded (max: %ld last redirect url: %s)", OAUTH_MAX_REDIRS, soo->last_location_header);
1629 if (soo->lastresponse.len) {
1630 ZVAL_STRING(&zret, soo->lastresponse.c);
1631 } else {
1632 ZVAL_STRING(&zret, "");
1633 }
1634 so_set_response_args(soo->properties, &zret, NULL);
1635 soo_handle_error(soo, http_response_code, bufz, soo->lastresponse.c, NULL);
1636 efree(bufz);
1637 /* set http_response_code to error value */
1638 http_response_code = -1;
1639 break;
1640 } else {
1641 ++soo->redirects;
1642 oauth_apply_url_redirect(&surl, soo->last_location_header);
1643 smart_string_0(&surl);
1644 /* bug 22628; keep same method when following redirects
1645 final_http_method = OAUTH_HTTP_METHOD_GET;
1646 */
1647 }
1648 }
1649 } else if (http_response_code < 0) {
1650 /* exception would have been thrown already */
1651 } else if (http_response_code < 200 || http_response_code > 209) {
1652 spprintf(&bufz, 0, "Invalid auth/bad request (got a %ld, expected HTTP/1.1 20X or a redirect)", http_response_code);
1653 if(soo->lastresponse.c) {
1654 ZVAL_STRING(&zret, soo->lastresponse.c);
1655 } else {
1656 ZVAL_STRING(&zret, "");
1657 }
1658 so_set_response_args(soo->properties, &zret, NULL);
1659 soo_handle_error(soo, http_response_code, bufz, soo->lastresponse.c, NULL);
1660 efree(bufz);
1661 /* set http_response_code to error value */
1662 http_response_code = -1;
1663 break;
1664 } else {
1665 /* valid response, time to get out of this loop */
1666 }
1667 } while (is_redirect && follow_redirects);
1668
1669 smart_string_free(&surl);
1670 smart_string_free(&postdata);
1671 zend_hash_destroy(&rheaders);
1672
1673 return http_response_code;
1674 }
1675 /* }}} */
1676
1677 /* {{{ proto bool setRSACertificate(string $cert)
1678 Sets the RSA certificate */
1679 SO_METHOD(setRSACertificate)
1680 {
1681 char *key;
1682 size_t key_len;
1683 zval args[1], func, retval;
1684
1685 php_so_object *soo;
1686
1687 soo = Z_SOO_P(getThis());
1688
1689 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &key_len) == FAILURE) {
1690 return;
1691 }
1692
1693 ZVAL_STRING(&func, "openssl_get_privatekey");
1694
1695 ZVAL_STRINGL(&args[0], key, key_len);
1696
1697
1698 call_user_function(EG(function_table), NULL, &func, &retval, 1, args);
1699
1700 zval_ptr_dtor(&args[0]);
1701 zval_ptr_dtor(&func);
1702
1703 switch (Z_TYPE(retval)) {
1704 case IS_RESOURCE:
1705 case IS_OBJECT:
1706 OAUTH_SIGCTX_SET_PRIVATEKEY(soo->sig_ctx, retval);
1707 RETURN_TRUE;
1708 break;
1709 default:
1710 zval_ptr_dtor(&retval);
1711 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Could not parse RSA certificate", NULL, NULL);
1712 return;
1713 }
1714 }
1715 /* }}} */
1716
1717 /* {{{ proto string oauth_urlencode(string uri)
1718 URI encoding according to RFC 3986, note: is not utf8 capable until the underlying phpapi is */
1719 PHP_FUNCTION(oauth_urlencode)
1720 {
1721 size_t uri_len;
1722 char *uri;
1723
1724 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &uri, &uri_len) == FAILURE) {
1725 return;
1726 }
1727
1728 if (uri_len < 1) {
1729 php_error_docref(NULL, E_WARNING, "Invalid uri length (0)");
1730 RETURN_FALSE;
1731 }
1732 RETURN_STR(oauth_url_encode(uri, uri_len));
1733 }
1734 /* }}} */
1735
1736 /* {{{ proto string oauth_get_sbs(string http_method, string uri, array parameters)
1737 Get a signature base string */
1738 PHP_FUNCTION(oauth_get_sbs)
1739 {
1740 char *uri, *http_method;
1741 zend_string *sbs;
1742 size_t uri_len, http_method_len;
1743 zval *req_params = NULL;
1744 HashTable *rparams = NULL;
1745
1746 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a", &http_method, &http_method_len, &uri, &uri_len, &req_params) == FAILURE) {
1747 return;
1748 }
1749
1750 if (uri_len < 1) {
1751 php_error_docref(NULL, E_WARNING, "Invalid uri length (0)");
1752 RETURN_FALSE;
1753 }
1754
1755 if (http_method_len < 1) {
1756 php_error_docref(NULL, E_WARNING, "Invalid http method length (0)");
1757 RETURN_FALSE;
1758 }
1759
1760 if (req_params) {
1761 rparams = HASH_OF(req_params);
1762 }
1763
1764 if ((sbs = oauth_generate_sig_base(NULL, http_method, uri, NULL, rparams))) {
1765 RETURN_STR(sbs);
1766 } else {
1767 RETURN_FALSE;
1768 }
1769 }
1770 /* }}} */
1771
1772 /* only hmac-sha1 is supported at the moment (it is the most common implementation), still need to lay down the ground work for supporting plaintext and others */
1773
1774 /* {{{ proto void OAuth::__construct(string consumer_key, string consumer_secret [, string signature_method, [, string auth_type ]])
1775 Instantiate a new OAuth object */
1776 SO_METHOD(__construct)
1777 {
1778 HashTable *hasht;
1779 char *ck, *cs, *sig_method = NULL;
1780 zend_long auth_method = 0;
1781 zval zck, zcs, zsm, zam, zver, *obj;
1782 size_t ck_len = 0, cs_len = 0, sig_method_len = 0;
1783 php_so_object *soo;
1784
1785 obj = getThis();
1786
1787 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sssl", &ck, &ck_len, &cs, &cs_len, &sig_method, &sig_method_len, &auth_method) == FAILURE) {
1788 return;
1789 }
1790
1791 soo = Z_SOO_P(obj);
1792
1793 if(ck_len == 0) {
1794 soo_handle_error(soo, -1, "The consumer key cannot be empty", NULL, NULL);
1795 return;
1796 }
1797
1798 if(cs_len == 0) {
1799 soo_handle_error(soo, -1, "The consumer secret cannot be empty", NULL, NULL);
1800 return;
1801 }
1802
1803 memset(soo->last_location_header, 0, OAUTH_MAX_HEADER_LEN);
1804 soo->redirects = 0;
1805 soo->debug = 0;
1806 soo->debug_info = emalloc(sizeof(php_so_debug));
1807 soo->debug_info->sbs = NULL;
1808 ZVAL_UNDEF(&soo->debugArr);
1809
1810 soo->nonce = NULL;
1811 soo->timestamp = NULL;
1812 soo->sig_ctx = NULL;
1813 soo->signature = NULL;
1814
1815 INIT_DEBUG_INFO(soo->debug_info);
1816
1817 INIT_smart_string(soo->headers_in);
1818
1819 /* set default class members */
1820 zend_update_property_null(soo_class_entry, OBJ_FOR_PROP(obj), "debugInfo", sizeof("debugInfo") - 1);
1821 zend_update_property_bool(soo_class_entry, OBJ_FOR_PROP(obj), "debug", sizeof("debug") - 1, soo->debug);
1822 zend_update_property_long(soo_class_entry, OBJ_FOR_PROP(obj), "sslChecks", sizeof("sslChecks") - 1, soo->sslcheck);
1823
1824 #if PHP_VERSION_ID < 80000
1825 TSRMLS_SET_CTX(soo->thread_ctx);
1826 #endif
1827
1828 if (!sig_method_len) {
1829 sig_method = OAUTH_SIG_METHOD_HMACSHA1;
1830 }
1831
1832 soo->sig_ctx = oauth_create_sig_context(sig_method);
1833
1834 if (!auth_method) {
1835 auth_method = OAUTH_AUTH_TYPE_AUTHORIZATION;
1836 }
1837
1838 if (soo->properties) {
1839 zend_hash_clean(soo->properties);
1840 hasht = soo->properties;
1841 } else {
1842 ALLOC_HASHTABLE(hasht);
1843 zend_hash_init(hasht, 0, NULL, ZVAL_PTR_DTOR, 0);
1844 soo->properties = hasht;
1845 }
1846
1847 ZVAL_STRING(&zck, ck);
1848 if (soo_set_property(soo, &zck, OAUTH_ATTR_CONSUMER_KEY) != SUCCESS) {
1849 return;
1850 }
1851
1852 if (cs_len > 0) {
1853 ZVAL_STR(&zcs, oauth_url_encode(cs, cs_len));
1854 } else {
1855 ZVAL_EMPTY_STRING(&zcs);
1856 }
1857 if (soo_set_property(soo, &zcs, OAUTH_ATTR_CONSUMER_SECRET) != SUCCESS) {
1858 return;
1859 }
1860
1861 ZVAL_STRING(&zsm, sig_method);
1862 if (soo_set_property(soo, &zsm, OAUTH_ATTR_SIGMETHOD) != SUCCESS) {
1863 return;
1864 }
1865
1866 ZVAL_LONG(&zam, auth_method);
1867 if (soo_set_property(soo, &zam, OAUTH_ATTR_AUTHMETHOD) != SUCCESS) {
1868 return;
1869 }
1870
1871 ZVAL_STRING(&zver, OAUTH_DEFAULT_VERSION);
1872 if (soo_set_property(soo, &zver, OAUTH_ATTR_OAUTH_VERSION) != SUCCESS) {
1873 return;
1874 }
1875
1876 soo->debug = 0;
1877 soo->sslcheck = OAUTH_SSLCHECK_BOTH;
1878 soo->follow_redirects = 1;
1879
1880 soo->lastresponse.c = NULL;
1881 #if OAUTH_USE_CURL
1882 soo->reqengine = OAUTH_REQENGINE_CURL;
1883 #else
1884 soo->reqengine = OAUTH_REQENGINE_STREAMS;
1885 #endif
1886 }
1887 /* }}} */
1888
1889 void oauth_free_privatekey(zval *privatekey) /* {{{ */
1890 {
1891 zval func, retval;
1892 zval args[1];
1893
1894 if (Z_TYPE_P(privatekey)==IS_RESOURCE) {
1895 ZVAL_STRING(&func, "openssl_freekey");
1896 ZVAL_DUP(&args[0], privatekey);
1897
1898 call_user_function(EG(function_table), NULL, &func, &retval, 1, args);
1899
1900 zval_ptr_dtor(&func);
1901 zval_ptr_dtor(&retval);
1902 }
1903
1904 zval_ptr_dtor(privatekey);
1905 }
1906 /* }}} */
1907
1908 /* {{{ proto array OAuth::setCAPath(string ca_path, string ca_info)
1909 Set the Certificate Authority information */
1910 SO_METHOD(setCAPath)
1911 {
1912 php_so_object *soo;
1913 char *ca_path, *ca_info;
1914 size_t ca_path_len = 0, ca_info_len = 0;
1915 zval zca_path, zca_info;
1916
1917 soo = Z_SOO_P(getThis());
1918
1919 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ss", &ca_path, &ca_path_len, &ca_info, &ca_info_len) == FAILURE) {
1920 return;
1921 }
1922
1923 if (ca_path_len) {
1924 ZVAL_STRINGL(&zca_path, ca_path, ca_path_len);
1925 if (soo_set_property(soo, &zca_path, OAUTH_ATTR_CA_PATH) != SUCCESS) {
1926 RETURN_FALSE;
1927 }
1928 }
1929
1930 if (ca_info_len) {
1931 ZVAL_STRINGL(&zca_info, ca_info, ca_info_len);
1932 if (soo_set_property(soo, &zca_info, OAUTH_ATTR_CA_INFO) != SUCCESS) {
1933 RETURN_FALSE;
1934 }
1935 }
1936 RETURN_TRUE;
1937 }
1938 /* }}} */
1939
1940 /* {{{ proto array OAuth::getCAPath(void)
1941 Get the Certificate Authority information */
1942 SO_METHOD(getCAPath)
1943 {
1944 /* perhaps make this information available via members too? */
1945 php_so_object *soo;
1946 zval *zca_path, *zca_info;
1947
1948 soo = Z_SOO_P(getThis());
1949
1950 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
1951 return;
1952 }
1953
1954 zca_info = soo_get_property(soo, OAUTH_ATTR_CA_INFO);
1955 zca_path = soo_get_property(soo, OAUTH_ATTR_CA_PATH);
1956
1957 array_init(return_value);
1958
1959 if (zca_info || zca_path) {
1960 if(zca_info) {
1961 add_assoc_stringl(return_value, "ca_info", Z_STRVAL_P(zca_info), Z_STRLEN_P(zca_info));
1962 }
1963
1964 if(zca_path) {
1965 add_assoc_stringl(return_value, "ca_path", Z_STRVAL_P(zca_path), Z_STRLEN_P(zca_path));
1966 }
1967 }
1968 }
1969 /* }}} */
1970
1971 /* {{{ proto array OAuth::getRequestToken(string request_token_url [, string callback_url [, http_method ] ])
1972 Get request token */
1973 SO_METHOD(getRequestToken)
1974 {
1975 php_so_object *soo;
1976 zval zret, *callback_url = NULL;
1977 char *url, *http_method = OAUTH_HTTP_METHOD_POST;
1978 size_t url_len = 0, http_method_len = sizeof(OAUTH_HTTP_METHOD_POST) - 1;
1979 long retcode;
1980 HashTable *args = NULL;
1981
1982 soo = Z_SOO_P(getThis());
1983
1984 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|zs", &url, &url_len, &callback_url, &http_method, &http_method_len) == FAILURE) {
1985 return;
1986 }
1987
1988 if (url_len < 1) {
1989 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid request token url length", NULL, NULL);
1990 RETURN_FALSE;
1991 }
1992
1993 if (callback_url && IS_STRING==Z_TYPE_P(callback_url)) {
1994 ALLOC_HASHTABLE(args);
1995 zend_hash_init(args, 0, NULL, ZVAL_PTR_DTOR, 0);
1996 if (Z_STRLEN_P(callback_url) > 0) {
1997 add_arg_for_req(args, OAUTH_PARAM_CALLBACK, Z_STRVAL_P(callback_url));
1998 } else {
1999 /* empty callback url specified, treat as 1.0a */
2000 add_arg_for_req(args, OAUTH_PARAM_CALLBACK, OAUTH_CALLBACK_OOB);
2001 }
2002 }
2003
2004 retcode = oauth_fetch(soo, url, oauth_get_http_method(soo, http_method), NULL, NULL, args, 0);
2005
2006 if (args) {
2007 FREE_ARGS_HASH(args);
2008 }
2009
2010 if (retcode != -1 && soo->lastresponse.c) {
2011 array_init(return_value);
2012 ZVAL_STRINGL(&zret, soo->lastresponse.c, soo->lastresponse.len);
2013 so_set_response_args(soo->properties, &zret, return_value);
2014 return;
2015 }
2016 RETURN_FALSE;
2017 }
2018 /* }}} */
2019
2020 /* {{{ proto bool OAuth::enableRedirects(void)
2021 Follow and sign redirects automatically (enabled by default) */
2022 SO_METHOD(enableRedirects)
2023 {
2024 php_so_object *soo;
2025
2026 soo = Z_SOO_P(getThis());
2027
2028 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
2029 return;
2030 }
2031
2032 soo->follow_redirects = 1;
2033
2034 RETURN_TRUE;
2035 }
2036 /* }}} */
2037
2038 /* {{{ proto bool OAuth::disableRedirects(void)
2039 Don't follow redirects automatically, thus allowing the request to be manually redirected (enabled by default) */
2040 SO_METHOD(disableRedirects)
2041 {
2042 php_so_object *soo;
2043
2044 soo = Z_SOO_P(getThis());
2045
2046 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
2047 return;
2048 }
2049
2050 soo->follow_redirects = 0;
2051
2052 RETURN_TRUE;
2053 }
2054 /* }}} */
2055
2056 /* {{{ proto bool OAuth::disableDebug(void)
2057 Disable debug mode */
2058 SO_METHOD(disableDebug)
2059 {
2060 php_so_object *soo;
2061 zval *obj;
2062
2063 obj = getThis();
2064 soo = Z_SOO_P(obj);
2065
2066 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
2067 return;
2068 }
2069
2070 soo->debug = 0;
2071 zend_update_property_bool(soo_class_entry, OBJ_FOR_PROP(obj), "debug", sizeof("debug") - 1, 0);
2072
2073 RETURN_TRUE;
2074 }
2075 /* }}} */
2076
2077 /* {{{ proto bool OAuth::enableDebug(void)
2078 Enable debug mode, will verbosely output http information about requests */
2079 SO_METHOD(enableDebug)
2080 {
2081 php_so_object *soo;
2082 zval *obj;
2083
2084 obj = getThis();
2085 soo = Z_SOO_P(obj);
2086
2087 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
2088 return;
2089 }
2090
2091 soo->debug = 1;
2092 zend_update_property_bool(soo_class_entry, OBJ_FOR_PROP(obj), "debug", sizeof("debug") - 1, 1);
2093
2094 RETURN_TRUE;
2095 }
2096 /* }}} */
2097
2098 /* {{{ proto bool OAuth::enableSSLChecks(void)
2099 Enable SSL verification for requests, enabled by default */
2100 SO_METHOD(enableSSLChecks)
2101 {
2102 php_so_object *soo;
2103 zval *obj;
2104
2105 obj = getThis();
2106 soo = Z_SOO_P(obj);
2107
2108 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
2109 return;
2110 }
2111
2112 soo->sslcheck = OAUTH_SSLCHECK_BOTH;
2113 zend_update_property_long(soo_class_entry, OBJ_FOR_PROP(obj), "sslChecks", sizeof("sslChecks") - 1, 1);
2114
2115 RETURN_TRUE;
2116 }
2117 /* }}} */
2118
2119 /* {{{ proto bool OAuth::disableSSLChecks(void)
2120 Disable SSL verification for requests (be careful using this for production) */
2121 SO_METHOD(disableSSLChecks)
2122 {
2123 php_so_object *soo;
2124 zval *obj;
2125
2126 obj = getThis();
2127 soo = Z_SOO_P(obj);
2128
2129 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
2130 return;
2131 }
2132
2133 soo->sslcheck = OAUTH_SSLCHECK_NONE;
2134 zend_update_property_long(soo_class_entry, OBJ_FOR_PROP(obj), "sslChecks", sizeof("sslChecks") - 1, 0);
2135
2136 RETURN_TRUE;
2137 }
2138 /* }}} */
2139
2140 /* {{{ proto bool OAuth::setSSLChecks(long sslcheck)
2141 Tweak specific SSL checks for requests (be careful using this for production) */
2142 SO_METHOD(setSSLChecks)
2143 {
2144 php_so_object *soo;
2145 zval *obj;
2146 zend_long sslcheck = OAUTH_SSLCHECK_BOTH;
2147
2148 obj = getThis();
2149 soo = Z_SOO_P(obj);
2150
2151 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &sslcheck) == FAILURE) {
2152 return;
2153 }
2154
2155 soo->sslcheck = sslcheck & OAUTH_SSLCHECK_BOTH;
2156
2157 zend_update_property_long(soo_class_entry, OBJ_FOR_PROP(obj), "sslChecks", sizeof("sslChecks") - 1,
2158 soo->sslcheck);
2159
2160 RETURN_TRUE;
2161 }
2162 /* }}} */
2163
2164 /* {{{ proto bool OAuth::setVersion(string version)
2165 Set oauth_version for requests (default 1.0) */
2166 SO_METHOD(setVersion)
2167 {
2168 php_so_object *soo;
2169 size_t ver_len = 0;
2170 char *vers;
2171 zval zver;
2172
2173 soo = Z_SOO_P(getThis());
2174
2175 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &vers, &ver_len) == FAILURE) {
2176 return;
2177 }
2178
2179 if (ver_len < 1) {
2180 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid version", NULL, NULL);
2181 RETURN_FALSE;
2182 }
2183
2184 ZVAL_STRING(&zver, vers);
2185 if (SUCCESS == soo_set_property(soo, &zver, OAUTH_ATTR_OAUTH_VERSION)) {
2186 RETURN_TRUE;
2187 }
2188
2189 RETURN_FALSE;
2190 }
2191 /* }}} */
2192
2193 /* {{{ proto bool OAuth::setAuthType(string auth_type)
2194 Set the manner in which to send oauth parameters */
2195 SO_METHOD(setAuthType)
2196 {
2197 php_so_object *soo;
2198 zend_long auth;
2199 zval zauth;
2200
2201 soo = Z_SOO_P(getThis());
2202
2203 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &auth) == FAILURE) {
2204 return;
2205 }
2206
2207 switch (auth) {
2208 case OAUTH_AUTH_TYPE_URI:
2209 case OAUTH_AUTH_TYPE_FORM:
2210 case OAUTH_AUTH_TYPE_AUTHORIZATION:
2211 case OAUTH_AUTH_TYPE_NONE:
2212 ZVAL_LONG(&zauth, auth);
2213 if (SUCCESS == soo_set_property(soo, &zauth, OAUTH_ATTR_AUTHMETHOD)) {
2214 RETURN_TRUE;
2215 }
2216 default:
2217 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid auth type", NULL, NULL);
2218 RETURN_FALSE;
2219 }
2220
2221 RETURN_FALSE;
2222 }
2223 /* }}} */
2224
2225 /* {{{ proto bool OAuth::setTimeout(int milliseconds)
2226 Set the timeout, in milliseconds, for requests */
2227 SO_METHOD(setTimeout)
2228 {
2229 php_so_object *soo;
2230 zend_long timeout;
2231
2232 soo = Z_SOO_P(getThis());
2233
2234 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &timeout) == FAILURE) {
2235 return;
2236 }
2237
2238 if (timeout < 0) {
2239 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid timeout", NULL, NULL);
2240 RETURN_FALSE;
2241 }
2242
2243 soo->timeout = timeout;
2244
2245 RETURN_TRUE;
2246 }
2247 /* }}} */
2248
2249 /* {{{ proto bool OAuth::setNonce(string nonce)
2250 Set oauth_nonce for subsequent requests, if none is set a random nonce will be generated using uniqid */
2251 SO_METHOD(setNonce)
2252 {
2253 php_so_object *soo;
2254 size_t nonce_len;
2255 char *nonce;
2256
2257 soo = Z_SOO_P(getThis());
2258
2259 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &nonce, &nonce_len) == FAILURE) {
2260 return;
2261 }
2262
2263 if (nonce_len < 1) {
2264 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid nonce", NULL, NULL);
2265 RETURN_FALSE;
2266 }
2267
2268 if (soo->nonce) {
2269 efree(soo->nonce);
2270 }
2271 soo->nonce = estrndup(nonce, nonce_len);
2272
2273 RETURN_TRUE;
2274 }
2275 /* }}} */
2276
2277 /* {{{ proto bool setTimestamp(string $timestamp)
2278 Sets the OAuth timestamp for subsequent requests */
2279 SO_METHOD(setTimestamp)
2280 {
2281 php_so_object *soo;
2282 size_t ts_len;
2283 char *ts;
2284
2285 soo = Z_SOO_P(getThis());
2286
2287 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &ts, &ts_len) == FAILURE) {
2288 return;
2289 }
2290
2291 if (ts_len < 1) {
2292 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid timestamp", NULL, NULL);
2293 RETURN_FALSE;
2294 }
2295
2296 if (soo->timestamp) {
2297 efree(soo->timestamp);
2298 }
2299 soo->timestamp = estrndup(ts, ts_len);
2300
2301 RETURN_TRUE;
2302 }
2303 /* }}} */
2304
2305 /* {{{ proto bool OAuth::setToken(string token, string token_secret)
2306 Set a request or access token and token secret to be used in subsequent requests */
2307 SO_METHOD(setToken)
2308 {
2309 php_so_object *soo;
2310 size_t token_len, token_secret_len;
2311 char *token, *token_secret;
2312 zval t,ts;
2313
2314 soo = Z_SOO_P(getThis());
2315
2316 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &token, &token_len, &token_secret, &token_secret_len) == FAILURE) {
2317 return;
2318 }
2319
2320 ZVAL_STRING(&t, token);
2321 soo_set_property(soo, &t, OAUTH_ATTR_TOKEN);
2322
2323 if (token_secret_len > 1) {
2324 ZVAL_STR(&ts, oauth_url_encode(token_secret, token_secret_len));
2325 soo_set_property(soo, &ts, OAUTH_ATTR_TOKEN_SECRET);
2326 }
2327 RETURN_TRUE;
2328 }
2329 /* }}} */
2330
2331 /* {{{ proto void OAuth::setRequestEngine(long reqengine) */
2332 SO_METHOD(setRequestEngine)
2333 {
2334 php_so_object *soo;
2335 zend_long reqengine;
2336
2337 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &reqengine) == FAILURE) {
2338 return;
2339 }
2340 soo = Z_SOO_P(getThis());
2341
2342 switch (reqengine) {
2343 case OAUTH_REQENGINE_STREAMS:
2344 #if OAUTH_USE_CURL
2345 case OAUTH_REQENGINE_CURL:
2346 #endif
2347 soo->reqengine = reqengine;
2348 break;
2349 default:
2350 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid request engine specified", NULL, NULL);
2351 }
2352 }
2353 /* }}} */
2354
2355 /* {{{ proto bool OAuth::generateSignature(string http_method, string url [, string|array extra_parameters ])
2356 Generate a signature based on the final HTTP method, URL and a string/array of parameters */
2357 SO_METHOD(generateSignature)
2358 {
2359 php_so_object *soo;
2360 size_t url_len, http_method_len = 0;
2361 char *url;
2362 zval *request_args = NULL;
2363 char *http_method = NULL;
2364
2365 soo = Z_SOO_P(getThis());
2366
2367 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|z", &http_method, &http_method_len, &url, &url_len, &request_args) == FAILURE) {
2368 return;
2369 }
2370
2371 if (url_len < 1) {
2372 RETURN_BOOL(FALSE);
2373 }
2374
2375 if (oauth_fetch(soo, url, http_method, request_args, NULL, NULL, (OAUTH_FETCH_USETOKEN | OAUTH_FETCH_SIGONLY)) < 0) {
2376 RETURN_BOOL(FALSE);
2377 } else {
2378 zend_string_addref(soo->signature);
2379 RETURN_STR(soo->signature);
2380 }
2381 }
2382 /* }}} */
2383
2384 /* {{{ proto bool OAuth::fetch(string protected_resource_url [, string|array extra_parameters [, string request_type [, array request_headers]]])
2385 fetch a protected resource, pass in extra_parameters (array(name => value) or "custom body") */
2386 SO_METHOD(fetch)
2387 {
2388 php_so_object *soo;
2389 size_t fetchurl_len, http_method_len = 0;
2390 char *fetchurl;
2391 zval zret, *request_args = NULL, *request_headers = NULL;
2392 char *http_method = NULL;
2393 long retcode;
2394
2395 soo = Z_SOO_P(getThis());
2396
2397 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|zsa", &fetchurl, &fetchurl_len, &request_args, &http_method, &http_method_len, &request_headers) == FAILURE) {
2398 return;
2399 }
2400
2401 if (fetchurl_len < 1) {
2402 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid protected resource url length", NULL, NULL);
2403 RETURN_FALSE;
2404 }
2405
2406 retcode = oauth_fetch(soo, fetchurl, http_method, request_args, request_headers, NULL, OAUTH_FETCH_USETOKEN | OAUTH_OVERRIDE_HTTP_METHOD);
2407
2408 ZVAL_STRINGL(&zret, soo->lastresponse.c, soo->lastresponse.len);
2409 so_set_response_args(soo->properties, &zret, NULL);
2410
2411 if ((retcode < 200 || retcode > 206)) {
2412 RETURN_FALSE;
2413 } else {
2414 RETURN_BOOL(TRUE);
2415 }
2416 }
2417 /* }}} */
2418
2419 /* {{{ proto array OAuth::getAccessToken(string access_token_url [, string auth_session_handle [, string auth_verifier [, http_method ]]])
2420 Get access token,
2421 If the server supports Scalable OAuth pass in the auth_session_handle to refresh the token (http://wiki.oauth.net/ScalableOAuth)
2422 For 1.0a implementation, a verifier token must be passed; this token is not passed unless a value is explicitly assigned via the function arguments or $_GET/$_POST['oauth_verifier'] is set
2423 */
2424 SO_METHOD(getAccessToken)
2425 {
2426 php_so_object *soo;
2427 size_t aturi_len = 0, ash_len = 0, verifier_len_size_t = 0, http_method_len = sizeof(OAUTH_HTTP_METHOD_POST) - 1;
2428 int verifier_len;
2429 char *aturi, *ash, *verifier, *http_method = OAUTH_HTTP_METHOD_POST;
2430 zval zret;
2431 HashTable *args = NULL;
2432 long retcode;
2433
2434 soo = Z_SOO_P(getThis());
2435
2436 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sss", &aturi, &aturi_len, &ash, &ash_len, &verifier, &verifier_len_size_t, &http_method, &http_method_len) == FAILURE) {
2437 return;
2438 }
2439 verifier_len = verifier_len_size_t;
2440
2441 if (aturi_len < 1) {
2442 soo_handle_error(soo, OAUTH_ERR_INTERNAL_ERROR, "Invalid access token url length", NULL, NULL);
2443 RETURN_FALSE;
2444 }
2445
2446 if (!verifier_len) {
2447 /* try to get from _GET/_POST */
2448 get_request_param(OAUTH_PARAM_VERIFIER, &verifier, &verifier_len);
2449 }
2450
2451 if (ash_len > 0 || verifier_len > 0) {
2452 ALLOC_HASHTABLE(args);
2453 zend_hash_init(args, 0, NULL, ZVAL_PTR_DTOR, 0);
2454 if (ash_len > 0) {
2455 add_arg_for_req(args, OAUTH_PARAM_ASH, ash);
2456 }
2457 if (verifier_len > 0) {
2458 add_arg_for_req(args, OAUTH_PARAM_VERIFIER, verifier);
2459 }
2460 }
2461
2462 retcode = oauth_fetch(soo, aturi, oauth_get_http_method(soo, http_method), NULL, NULL, args, OAUTH_FETCH_USETOKEN);
2463
2464 if (args) {
2465 FREE_ARGS_HASH(args);
2466 }
2467
2468 if (retcode != -1 && soo->lastresponse.c) {
2469 array_init(return_value);
2470 ZVAL_STRINGL(&zret, soo->lastresponse.c, soo->lastresponse.len);
2471 so_set_response_args(soo->properties, &zret, return_value);
2472 return;
2473 }
2474 RETURN_FALSE;
2475 }
2476 /* }}} */
2477
2478 /* {{{ proto array OAuth::getLastResponseInfo(void)
2479 Get information about the last response */
2480 SO_METHOD(getLastResponseInfo)
2481 {
2482 php_so_object *soo;
2483 zval *data_ptr;
2484
2485 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
2486 return;
2487 }
2488
2489 soo = Z_SOO_P(getThis());
2490
2491 if ((data_ptr = zend_hash_str_find(soo->properties, OAUTH_ATTR_LAST_RES_INFO, sizeof(OAUTH_ATTR_LAST_RES_INFO) - 1)) != NULL) {
2492 if (Z_TYPE_P(data_ptr) == IS_ARRAY) {
2493 convert_to_array_ex(data_ptr);
2494 }
2495 RETURN_ZVAL(data_ptr, 1, 0);
2496 }
2497 RETURN_FALSE;
2498 }
2499 /* }}} */
2500
2501 /* {{{ proto array OAuth::getLastResponse(void)
2502 Get last response */
2503 SO_METHOD(getLastResponse)
2504 {
2505 php_so_object *soo;
2506
2507 if (zend_parse_parameters(ZEND_NUM_ARGS(), "") == FAILURE) {
2508 return;
2509 }
2510
2511 soo = Z_SOO_P(getThis());
2512
2513 if (soo->lastresponse.c) {
2514 RETURN_STRINGL(soo->lastresponse.c, soo->lastresponse.len);
2515 }
2516 }
2517 /* }}} */
2518
2519 /* {{{ proto string getLastResponseHeaders(void)
2520 Get headers for last response */
2521 SO_METHOD(getLastResponseHeaders)
2522 {
2523 php_so_object *soo;
2524
2525 if (FAILURE==zend_parse_parameters(ZEND_NUM_ARGS(), "")) {
2526 return;
2527 }
2528
2529 soo = Z_SOO_P(getThis());
2530 if (soo->headers_in.c) {
2531 RETURN_STRINGL(soo->headers_in.c, soo->headers_in.len);
2532 }
2533 RETURN_FALSE;
2534 }
2535 /* }}} */
2536
2537 /* {{{ proto string OAuth::getRequestHeader(string http_method, string url [, string|array extra_parameters ])
2538 Generate OAuth header string signature based on the final HTTP method, URL and a string/array of parameters */
2539 SO_METHOD(getRequestHeader)
2540 {
2541 php_so_object *soo;
2542 size_t url_len, http_method_len = 0;
2543 char *url;
2544 zval *request_args = NULL;
2545 char *http_method = NULL;
2546
2547 soo = Z_SOO_P(getThis());
2548
2549 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|z", &http_method, &http_method_len, &url, &url_len, &request_args) == FAILURE) {
2550 return;
2551 }
2552
2553 if (url_len < 1) {
2554 RETURN_BOOL(FALSE);
2555 }
2556
2557 if (oauth_fetch(soo, url, http_method, request_args, NULL, NULL,
2558 (OAUTH_FETCH_USETOKEN | OAUTH_FETCH_HEADONLY)) < 0) {
2559 RETURN_BOOL(FALSE);
2560 } else {
2561 RETURN_STRINGL(soo->headers_out.c, soo->headers_out.len);
2562 }
2563
2564 RETURN_FALSE;
2565 }
2566
2567 /* {{{ arginfo */
2568 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_urlencode, 0, 0, 1)
2569 ZEND_ARG_INFO(0, uri)
2570 ZEND_END_ARG_INFO()
2571
2572 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_sbs, 0, 0, 3)
2573 ZEND_ARG_INFO(0, http_method)
2574 ZEND_ARG_INFO(0, uri)
2575 ZEND_ARG_INFO(0, parameters)
2576 ZEND_END_ARG_INFO()
2577
2578 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth__construct, 0, 0, 2)
2579 ZEND_ARG_INFO(0, consumer_key)
2580 ZEND_ARG_INFO(0, consumer_secret)
2581 ZEND_ARG_INFO(0, signature_method)
2582 ZEND_ARG_INFO(0, auth_type)
2583 ZEND_END_ARG_INFO()
2584
2585 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_getrequesttoken, 0, 0, 1)
2586 ZEND_ARG_INFO(0, request_token_url)
2587 ZEND_ARG_INFO(0, callback_url)
2588 ZEND_END_ARG_INFO()
2589
2590 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setversion, 0, 0, 1)
2591 ZEND_ARG_INFO(0, version)
2592 ZEND_END_ARG_INFO()
2593
2594 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_noparams, 0, 0, 0)
2595 ZEND_END_ARG_INFO()
2596
2597 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setauthtype, 0, 0, 1)
2598 ZEND_ARG_INFO(0, auth_type)
2599 ZEND_END_ARG_INFO()
2600
2601 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setnonce, 0, 0, 1)
2602 ZEND_ARG_INFO(0, nonce)
2603 ZEND_END_ARG_INFO()
2604
2605 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_settimestamp, 0, 0, 1)
2606 ZEND_ARG_INFO(0, ts)
2607 ZEND_END_ARG_INFO()
2608
2609 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_settimeout, 0, 0, 1)
2610 ZEND_ARG_INFO(0, timeout_in_milliseconds)
2611 ZEND_END_ARG_INFO()
2612
2613 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setcapath, 0, 0, 2)
2614 ZEND_ARG_INFO(0, ca_path)
2615 ZEND_ARG_INFO(0, ca_info)
2616 ZEND_END_ARG_INFO()
2617
2618 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_settoken, 0, 0, 2)
2619 ZEND_ARG_INFO(0, token)
2620 ZEND_ARG_INFO(0, token_secret)
2621 ZEND_END_ARG_INFO()
2622
2623 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setrequestengine, 0, 0, 1)
2624 ZEND_ARG_INFO(0, reqengine)
2625 ZEND_END_ARG_INFO()
2626
2627 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_fetch, 0, 0, 1)
2628 ZEND_ARG_INFO(0, protected_resource_url)
2629 ZEND_ARG_INFO(0, extra_parameters) /* ARRAY_INFO(1, arg, 0) */
2630 ZEND_ARG_INFO(0, http_method)
2631 ZEND_ARG_INFO(0, request_headers)
2632 ZEND_END_ARG_INFO()
2633
2634 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_getaccesstoken, 0, 0, 1)
2635 ZEND_ARG_INFO(0, access_token_url)
2636 ZEND_ARG_INFO(0, auth_session_handle)
2637 ZEND_ARG_INFO(0, auth_verifier)
2638 ZEND_END_ARG_INFO()
2639
2640 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setrsacertificate, 0, 0, 1)
2641 ZEND_ARG_INFO(0, cert)
2642 ZEND_END_ARG_INFO()
2643
2644 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_gensig, 0, 0, 2)
2645 ZEND_ARG_INFO(0, http_method)
2646 ZEND_ARG_INFO(0, url)
2647 ZEND_ARG_INFO(0, extra_parameters) /* ARRAY_INFO(1, arg, 0) */
2648 ZEND_END_ARG_INFO()
2649
2650 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_setsslchecks, 0, 0, 1)
2651 ZEND_ARG_INFO(0, sslcheck)
2652 ZEND_END_ARG_INFO()
2653
2654 ZEND_BEGIN_ARG_INFO_EX(arginfo_oauth_getrequestheader, 0, 0, 2)
2655 ZEND_ARG_INFO(0, http_method)
2656 ZEND_ARG_INFO(0, url)
2657 ZEND_ARG_INFO(0, extra_parameters) /* ARRAY_INFO(1, arg, 0) */
2658 ZEND_END_ARG_INFO()
2659
2660
2661 /* }}} */
2662
2663
2664 static zend_function_entry so_functions[] = { /* {{{ */
2665 SO_ME(__construct, arginfo_oauth__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
2666 SO_ME(setRSACertificate, arginfo_oauth_setrsacertificate, ZEND_ACC_PUBLIC)
2667 SO_ME(getRequestToken, arginfo_oauth_getrequesttoken, ZEND_ACC_PUBLIC)
2668 SO_ME(getAccessToken, arginfo_oauth_getaccesstoken, ZEND_ACC_PUBLIC)
2669 SO_ME(getLastResponse, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2670 SO_ME(getLastResponseInfo, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2671 SO_ME(getLastResponseHeaders, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2672 SO_ME(setToken, arginfo_oauth_settoken, ZEND_ACC_PUBLIC)
2673 SO_ME(setRequestEngine, arginfo_oauth_setrequestengine, ZEND_ACC_PUBLIC)
2674 SO_ME(setVersion, arginfo_oauth_setversion, ZEND_ACC_PUBLIC)
2675 SO_ME(setAuthType, arginfo_oauth_setauthtype, ZEND_ACC_PUBLIC)
2676 SO_ME(setNonce, arginfo_oauth_setnonce, ZEND_ACC_PUBLIC)
2677 SO_ME(setTimestamp, arginfo_oauth_settimestamp, ZEND_ACC_PUBLIC)
2678 SO_ME(fetch, arginfo_oauth_fetch, ZEND_ACC_PUBLIC)
2679 SO_ME(enableDebug, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2680 SO_ME(disableDebug, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2681 SO_ME(enableSSLChecks, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2682 SO_ME(disableSSLChecks, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2683 SO_ME(enableRedirects, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2684 SO_ME(disableRedirects, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2685 SO_ME(setCAPath, arginfo_oauth_setcapath, ZEND_ACC_PUBLIC)
2686 SO_ME(getCAPath, arginfo_oauth_noparams, ZEND_ACC_PUBLIC)
2687 SO_ME(generateSignature, arginfo_oauth_gensig, ZEND_ACC_PUBLIC)
2688 SO_ME(setTimeout, arginfo_oauth_settimeout, ZEND_ACC_PUBLIC)
2689 SO_ME(setSSLChecks, arginfo_oauth_setsslchecks, ZEND_ACC_PUBLIC)
2690 SO_ME(getRequestHeader, arginfo_oauth_getrequestheader, ZEND_ACC_PUBLIC)
2691 {NULL, NULL, NULL}
2692 };
2693 /* }}} */
2694
2695
2696 #if PHP_VERSION_ID < 80000
2697 zval *oauth_read_member(zval *obj, zval *mem, int type, void **cache_slot, zval *rv) /* {{{ */
2698 {
2699 php_so_object *soo = Z_SOO_P(obj);
2700 char *name = Z_STRVAL_P(mem);
2701 #else
2702 zval *oauth_read_member(zend_object *obj, zend_string *mem, int type, void **cache_slot, zval *rv) /* {{{ */
2703 {
2704 php_so_object *soo = so_object_from_obj(obj);
2705 char *name = ZSTR_VAL(mem);
2706 #endif
2707 zval *return_value = NULL;
2708
2709 return_value = std_object_handlers.read_property(obj, mem, type, cache_slot, rv);
2710
2711 if(!strcasecmp(name, "debug")) {
2712 convert_to_boolean(return_value);
2713 ZVAL_BOOL(return_value, soo->debug);
2714 } else if(!strcasecmp(name, "sslChecks")) {
2715 ZVAL_LONG(return_value, soo->sslcheck);
2716 }
2717 return return_value;
2718 } /* }}} */
2719
2720
2721 #if PHP_VERSION_ID < 80000
2722 static
2723 #if PHP_VERSION_ID >= 70400
2724 zval *
2725 #else
2726 void
2727 #endif
2728 oauth_write_member(zval *obj, zval *mem, zval *value, void **cache_slot) /* {{{ */
2729 {
2730 php_so_object *soo = Z_SOO_P(obj);
2731 char *property = Z_STRVAL_P(mem);
2732 #else
2733 static zval *oauth_write_member(zend_object *obj, zend_string *mem, zval *value, void **cache_slot) /* {{{ */
2734 {
2735 php_so_object *soo = so_object_from_obj(obj);
2736 char *property = ZSTR_VAL(mem);
2737 #endif
2738
2739 if(!strcmp(property,"debug")) {
2740 soo->debug = Z_TYPE_P(value) == IS_TRUE ? 1 : 0;
2741 } else if(!strcmp(property,"sslChecks")) {
2742 soo->sslcheck = Z_LVAL_P(value);
2743 }
2744 #if PHP_VERSION_ID >= 70400
2745 return
2746 #endif
2747 std_object_handlers.write_property(obj, mem, value, cache_slot);
2748 } /* }}} */
2749
2750 /* {{{ PHP_MINIT_FUNCTION
2751 */
2752 PHP_MINIT_FUNCTION(oauth)
2753 {
2754 zend_class_entry soce, soo_ex_ce;
2755
2756 #if OAUTH_USE_CURL
2757 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
2758 return FAILURE;
2759 }
2760 #endif
2761
2762 INIT_CLASS_ENTRY(soce, "OAuth", so_functions);
2763 soce.create_object = php_so_object_new;
2764
2765 soo_class_entry = zend_register_internal_class(&soce);
2766 memcpy(&so_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2767 so_object_handlers.offset = XtOffsetOf(php_so_object, zo);
2768
2769 so_object_handlers.read_property = oauth_read_member;
2770 so_object_handlers.write_property = oauth_write_member;
2771 so_object_handlers.clone_obj = oauth_clone_obj;
2772 so_object_handlers.free_obj = so_object_free_storage;
2773
2774
2775 zend_declare_property_long(soo_class_entry, "debug", sizeof("debug")-1, 0, ZEND_ACC_PUBLIC);
2776 zend_declare_property_long(soo_class_entry, "sslChecks", sizeof("sslChecks")-1, 1, ZEND_ACC_PUBLIC);
2777 zend_declare_property_string(soo_class_entry, "debugInfo", sizeof("debugInfo")-1, "", ZEND_ACC_PUBLIC);
2778
2779 INIT_CLASS_ENTRY(soo_ex_ce, "OAuthException", NULL);
2780
2781 soo_exception_ce = zend_register_internal_class_ex(&soo_ex_ce, zend_exception_get_default());
2782 zend_declare_property_null(soo_exception_ce, "lastResponse", sizeof("lastResponse")-1, ZEND_ACC_PUBLIC);
2783 zend_declare_property_null(soo_exception_ce, "debugInfo", sizeof("debugInfo")-1, ZEND_ACC_PUBLIC);
2784
2785 REGISTER_STRING_CONSTANT("OAUTH_SIG_METHOD_HMACSHA1", OAUTH_SIG_METHOD_HMACSHA1, CONST_CS | CONST_PERSISTENT);
2786 REGISTER_STRING_CONSTANT("OAUTH_SIG_METHOD_HMACSHA256", OAUTH_SIG_METHOD_HMACSHA256, CONST_CS | CONST_PERSISTENT);
2787 REGISTER_STRING_CONSTANT("OAUTH_SIG_METHOD_RSASHA1", OAUTH_SIG_METHOD_RSASHA1, CONST_CS | CONST_PERSISTENT);
2788 REGISTER_STRING_CONSTANT("OAUTH_SIG_METHOD_PLAINTEXT", OAUTH_SIG_METHOD_PLAINTEXT, CONST_CS | CONST_PERSISTENT);
2789 REGISTER_LONG_CONSTANT("OAUTH_AUTH_TYPE_AUTHORIZATION", OAUTH_AUTH_TYPE_AUTHORIZATION, CONST_CS | CONST_PERSISTENT);
2790 REGISTER_LONG_CONSTANT("OAUTH_AUTH_TYPE_URI", OAUTH_AUTH_TYPE_URI, CONST_CS | CONST_PERSISTENT);
2791 REGISTER_LONG_CONSTANT("OAUTH_AUTH_TYPE_FORM", OAUTH_AUTH_TYPE_FORM, CONST_CS | CONST_PERSISTENT);
2792 REGISTER_LONG_CONSTANT("OAUTH_AUTH_TYPE_NONE", OAUTH_AUTH_TYPE_NONE, CONST_CS | CONST_PERSISTENT);
2793 REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_GET", OAUTH_HTTP_METHOD_GET, CONST_CS | CONST_PERSISTENT);
2794 REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_POST", OAUTH_HTTP_METHOD_POST, CONST_CS | CONST_PERSISTENT);
2795 REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_PUT", OAUTH_HTTP_METHOD_PUT, CONST_CS | CONST_PERSISTENT);
2796 REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_HEAD", OAUTH_HTTP_METHOD_HEAD, CONST_CS | CONST_PERSISTENT);
2797 REGISTER_STRING_CONSTANT("OAUTH_HTTP_METHOD_DELETE", OAUTH_HTTP_METHOD_DELETE, CONST_CS | CONST_PERSISTENT);
2798 REGISTER_LONG_CONSTANT("OAUTH_REQENGINE_STREAMS", OAUTH_REQENGINE_STREAMS, CONST_CS | CONST_PERSISTENT);
2799 #ifdef OAUTH_USE_CURL
2800 REGISTER_LONG_CONSTANT("OAUTH_REQENGINE_CURL", OAUTH_REQENGINE_CURL, CONST_CS | CONST_PERSISTENT);
2801 #endif
2802 REGISTER_LONG_CONSTANT("OAUTH_SSLCHECK_NONE", OAUTH_SSLCHECK_NONE, CONST_CS | CONST_PERSISTENT);
2803 REGISTER_LONG_CONSTANT("OAUTH_SSLCHECK_HOST", OAUTH_SSLCHECK_HOST, CONST_CS | CONST_PERSISTENT);
2804 REGISTER_LONG_CONSTANT("OAUTH_SSLCHECK_PEER", OAUTH_SSLCHECK_PEER, CONST_CS | CONST_PERSISTENT);
2805 REGISTER_LONG_CONSTANT("OAUTH_SSLCHECK_BOTH", OAUTH_SSLCHECK_BOTH, CONST_CS | CONST_PERSISTENT);
2806
2807 oauth_provider_register_class();
2808 REGISTER_LONG_CONSTANT("OAUTH_OK", OAUTH_OK, CONST_CS | CONST_PERSISTENT);
2809 REGISTER_LONG_CONSTANT("OAUTH_BAD_NONCE", OAUTH_BAD_NONCE, CONST_CS | CONST_PERSISTENT);
2810 REGISTER_LONG_CONSTANT("OAUTH_BAD_TIMESTAMP", OAUTH_BAD_TIMESTAMP, CONST_CS | CONST_PERSISTENT);
2811 REGISTER_LONG_CONSTANT("OAUTH_CONSUMER_KEY_UNKNOWN", OAUTH_CONSUMER_KEY_UNKNOWN, CONST_CS | CONST_PERSISTENT);
2812 REGISTER_LONG_CONSTANT("OAUTH_CONSUMER_KEY_REFUSED", OAUTH_CONSUMER_KEY_REFUSED, CONST_CS | CONST_PERSISTENT);
2813 REGISTER_LONG_CONSTANT("OAUTH_INVALID_SIGNATURE", OAUTH_INVALID_SIGNATURE, CONST_CS | CONST_PERSISTENT);
2814 REGISTER_LONG_CONSTANT("OAUTH_TOKEN_USED", OAUTH_TOKEN_USED, CONST_CS | CONST_PERSISTENT);
2815 REGISTER_LONG_CONSTANT("OAUTH_TOKEN_EXPIRED", OAUTH_TOKEN_EXPIRED, CONST_CS | CONST_PERSISTENT);
2816 REGISTER_LONG_CONSTANT("OAUTH_TOKEN_REVOKED", OAUTH_TOKEN_REVOKED, CONST_CS | CONST_PERSISTENT);
2817 REGISTER_LONG_CONSTANT("OAUTH_TOKEN_REJECTED", OAUTH_TOKEN_REJECTED, CONST_CS | CONST_PERSISTENT);
2818 REGISTER_LONG_CONSTANT("OAUTH_VERIFIER_INVALID", OAUTH_VERIFIER_INVALID, CONST_CS | CONST_PERSISTENT);
2819 REGISTER_LONG_CONSTANT("OAUTH_PARAMETER_ABSENT", OAUTH_PARAMETER_ABSENT, CONST_CS | CONST_PERSISTENT);
2820 REGISTER_LONG_CONSTANT("OAUTH_SIGNATURE_METHOD_REJECTED", OAUTH_SIGNATURE_METHOD_REJECTED, CONST_CS | CONST_PERSISTENT);
2821 return SUCCESS;
2822 }
2823 /* }}} */
2824
2825 /* {{{ PHP_MSHUTDOWN_FUNCTION
2826 */
2827 PHP_MSHUTDOWN_FUNCTION(oauth)
2828 {
2829 soo_class_entry = NULL;
2830 soo_exception_ce = NULL;
2831 #if OAUTH_USE_CURL
2832 curl_global_cleanup();
2833 #endif
2834 return SUCCESS;
2835 }
2836 /* }}} */
2837
2838 /* {{{ PHP_MINFO_FUNCTION
2839 */
2840 PHP_MINFO_FUNCTION(oauth)
2841 {
2842 php_info_print_table_start();
2843 php_info_print_table_header(2, "OAuth support", "enabled");
2844 php_info_print_table_row(2, "PLAINTEXT support", "enabled");
2845 #if HAVE_OPENSSL_EXT
2846 php_info_print_table_row(2, "RSA-SHA1 support", "enabled");
2847 #else
2848 php_info_print_table_row(2, "RSA-SHA1 support", "not supported");
2849 #endif
2850 php_info_print_table_row(2, "HMAC-SHA1 support", "enabled");
2851 #if OAUTH_USE_CURL
2852 php_info_print_table_row(2, "Request engine support", "php_streams, curl");
2853 #else
2854 php_info_print_table_row(2, "Request engine support", "php_streams");
2855 #endif
2856 php_info_print_table_row(2, "version", OAUTH_EXT_VER);
2857 php_info_print_table_end();
2858 }
2859 /* }}} */
2860
2861 /* TODO expose a function for base sig string */
2862 zend_function_entry oauth_functions[] = { /* {{{ */
2863 PHP_FE(oauth_urlencode, arginfo_oauth_urlencode)
2864 PHP_FE(oauth_get_sbs, arginfo_oauth_sbs)
2865 { NULL, NULL, NULL }
2866 };
2867 /* }}} */
2868
2869 /* {{{ oauth_module_entry */
2870 zend_module_entry oauth_module_entry = {
2871 STANDARD_MODULE_HEADER_EX, NULL,
2872 NULL,
2873 "OAuth",
2874 oauth_functions,
2875 PHP_MINIT(oauth),
2876 PHP_MSHUTDOWN(oauth),
2877 NULL,
2878 NULL,
2879 PHP_MINFO(oauth),
2880 OAUTH_EXT_VER,
2881 STANDARD_MODULE_PROPERTIES
2882 };
2883 /* }}} */
2884
2885 #if COMPILE_DL_OAUTH
2886 ZEND_GET_MODULE(oauth)
2887 #endif
2888
2889 /**
2890 * Local Variables:
2891 * c-basic-offset: 4
2892 * tab-width: 4
2893 * indent-tabs-mode: t
2894 * End:
2895 * vim600: fdm=marker
2896 * vim: noet sw=4 ts=4 noexpandtab
2897 */
2898