928a31df18a81eaa4d4cbd26bd23dcacea6cca0a
[m6w6/ext-http] / php_http_negotiate.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2011, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14
15 #include <ext/standard/php_string.h>
16
17 static int php_http_negotiate_sort(const void *a, const void *b TSRMLS_DC)
18 {
19 zval result, *first, *second;
20
21 first = *((zval **) (*((Bucket **) a))->pData);
22 second= *((zval **) (*((Bucket **) b))->pData);
23
24 if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) {
25 return 0;
26 }
27 return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0));
28 }
29
30 static int php_http_negotiate_reduce(void *p TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
31 {
32 char *tmp;
33 zval **q, *supported = php_http_ztyp(IS_STRING, *(zval **)p);
34 HashTable *params = va_arg(args, HashTable *);
35 HashTable *result = va_arg(args, HashTable *);
36
37 tmp = php_strtolower(estrndup(Z_STRVAL_P(supported), Z_STRLEN_P(supported)), Z_STRLEN_P(supported));
38 if (SUCCESS == zend_symtable_find(params, tmp, Z_STRLEN_P(supported) + 1, (void *) &q)) {
39 Z_ADDREF_PP(q);
40 zend_symtable_update(result, Z_STRVAL_P(supported), Z_STRLEN_P(supported) + 1, (void *) q, sizeof(zval *), NULL);
41 }
42 efree(tmp);
43 zval_ptr_dtor(&supported);
44 return ZEND_HASH_APPLY_KEEP;
45 }
46
47 PHP_HTTP_API HashTable *php_http_negotiate(const char *value_str, size_t value_len, HashTable *supported, const char *primary_sep_str, size_t primary_sep_len TSRMLS_DC)
48 {
49 HashTable *result = NULL;
50
51 if (value_str && value_len) {
52 unsigned i = 0;
53 zval arr, **val, **arg, **zq;
54 HashPosition pos;
55 HashTable params;
56 php_http_array_hashkey_t key = php_http_array_hashkey_init(1);
57 php_http_params_opts_t opts;
58
59 zend_hash_init(&params, 10, NULL, ZVAL_PTR_DTOR, 0);
60 php_http_params_opts_default_get(&opts);
61 opts.input.str = estrndup(value_str, value_len);
62 opts.input.len = value_len;
63 php_http_params_parse(&params, &opts TSRMLS_CC);
64 efree(opts.input.str);
65
66 INIT_PZVAL(&arr);
67 array_init(&arr);
68
69 FOREACH_HASH_KEYVAL(pos, &params, key, val) {
70 double q;
71
72 if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("arguments"), (void *) &arg)
73 && IS_ARRAY == Z_TYPE_PP(arg)
74 && SUCCESS == zend_hash_find(Z_ARRVAL_PP(arg), ZEND_STRS("q"), (void *) &zq)) {
75 zval *tmp = php_http_ztyp(IS_DOUBLE, *zq);
76
77 q = Z_DVAL_P(tmp);
78 zval_ptr_dtor(&tmp);
79 } else {
80 q = 1.0 - ++i / 100.0;
81 }
82
83 if (key.type == HASH_KEY_IS_STRING) {
84 const char *ptr;
85
86 php_strtolower(key.str, key.len - 1);
87 add_assoc_double_ex(&arr, key.str, key.len, q);
88
89 if (primary_sep_str && primary_sep_len && (ptr = php_http_locate_str(key.str, key.len - 1, primary_sep_str, primary_sep_len))) {
90 key.str[ptr - key.str] = '\0';
91 add_assoc_double_ex(&arr, key.str, ptr - key.str + 1, q - i / 1000.0);
92 }
93 } else {
94 add_index_double(&arr, key.num, q);
95 }
96
97 STR_FREE(key.str);
98 }
99
100 ALLOC_HASHTABLE(result);
101 zend_hash_init(result, zend_hash_num_elements(supported), NULL, ZVAL_PTR_DTOR, 0);
102 zend_hash_apply_with_arguments(supported TSRMLS_CC, php_http_negotiate_reduce, 2, Z_ARRVAL(arr), result);
103 zend_hash_destroy(&params);
104 zval_dtor(&arr);
105 zend_hash_sort(result, zend_qsort, php_http_negotiate_sort, 0 TSRMLS_CC);
106 }
107
108 return result;
109 }
110
111
112
113 /*
114 * Local variables:
115 * tab-width: 4
116 * c-basic-offset: 4
117 * End:
118 * vim600: noet sw=4 ts=4 fdm=marker
119 * vim<600: noet sw=4 ts=4
120 */
121
122