cleanups & includes
[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-2010, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id: php_http_headers_api.h 300300 2010-06-09 07:29:35Z mike $ */
14
15 #include "php_http.h"
16
17 #include <ext/standard/php_string.h>
18
19 #ifndef PHP_HTTP_DBG_NEG
20 # define PHP_HTTP_DBG_NEG 0
21 #endif
22
23 char *php_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
24 {
25 zval **value;
26 HashPosition pos;
27 const char *dash_test;
28
29 FOREACH_HASH_VAL(pos, supported, value) {
30 #if PHP_HTTP_DBG_NEG
31 fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
32 #endif
33 if (!strcasecmp(Z_STRVAL_PP(value), test)) {
34 return Z_STRVAL_PP(value);
35 }
36 }
37
38 /* no distinct match found, so try primaries */
39 if ((dash_test = strchr(test, '-'))) {
40 FOREACH_HASH_VAL(pos, supported, value) {
41 int len = dash_test - test;
42 #if PHP_HTTP_DBG_NEG
43 fprintf(stderr, "strncasecmp('%s', '%s', %d)\n", Z_STRVAL_PP(value), test, len);
44 #endif
45 if ( (!strncasecmp(Z_STRVAL_PP(value), test, len)) &&
46 ( (Z_STRVAL_PP(value)[len] == '\0') ||
47 (Z_STRVAL_PP(value)[len] == '-'))) {
48 *quality *= .9;
49 return Z_STRVAL_PP(value);
50 }
51 }
52 }
53
54 return NULL;
55 }
56
57
58 char *php_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
59 {
60 zval **value;
61 HashPosition pos;
62 (void) quality;
63
64 FOREACH_HASH_VAL(pos, supported, value) {
65 #if PHP_HTTP_DBG_NEG
66 fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
67 #endif
68 if (!strcasecmp(Z_STRVAL_PP(value), test)) {
69 return Z_STRVAL_PP(value);
70 }
71 }
72
73 return NULL;
74 }
75
76
77 static int php_http_negotiate_sort(const void *a, const void *b TSRMLS_DC)
78 {
79 zval result, *first, *second;
80
81 first = *((zval **) (*((Bucket **) a))->pData);
82 second= *((zval **) (*((Bucket **) b))->pData);
83
84 if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) {
85 return 0;
86 }
87 return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0));
88 }
89
90
91 PHP_HTTP_API HashTable *php_http_negotiate(const char *value, HashTable *supported, php_http_negotiate_func_t neg TSRMLS_DC)
92 {
93 HashTable *result = NULL;
94
95 if (*value) {
96 zval ex_arr, ex_del, ex_val;
97
98 INIT_PZVAL(&ex_del);
99 INIT_PZVAL(&ex_arr);
100 INIT_PZVAL(&ex_val);
101 ZVAL_STRINGL(&ex_del, ",", 1, 0);
102 ZVAL_STRING(&ex_val, value, 1);
103 array_init(&ex_arr);
104
105 php_explode(&ex_del, &ex_val, &ex_arr, INT_MAX);
106
107 if (zend_hash_num_elements(Z_ARRVAL(ex_arr)) > 0) {
108 int i = 0;
109 HashPosition pos;
110 zval **entry, array;
111
112 INIT_PZVAL(&array);
113 array_init(&array);
114
115 if (!neg) {
116 neg = php_http_negotiate_default_func;
117 }
118
119 FOREACH_HASH_VAL(pos, Z_ARRVAL(ex_arr), entry) {
120 int ident_len;
121 double quality;
122 char *selected, *identifier, *freeme;
123 const char *separator;
124
125 #if PHP_HTTP_DBG_NEG
126 fprintf(stderr, "Checking %s\n", Z_STRVAL_PP(entry));
127 #endif
128
129 if ((separator = strchr(Z_STRVAL_PP(entry), ';'))) {
130 const char *ptr = separator;
131
132 while (*++ptr && !PHP_HTTP_IS_CTYPE(digit, *ptr) && '.' != *ptr);
133
134 quality = zend_strtod(ptr, NULL);
135 identifier = estrndup(Z_STRVAL_PP(entry), ident_len = separator - Z_STRVAL_PP(entry));
136 } else {
137 quality = 1000.0 - i++;
138 identifier = estrndup(Z_STRVAL_PP(entry), ident_len = Z_STRLEN_PP(entry));
139 }
140 freeme = identifier;
141
142 while (PHP_HTTP_IS_CTYPE(space, *identifier)) {
143 ++identifier;
144 --ident_len;
145 }
146 while (ident_len && PHP_HTTP_IS_CTYPE(space, identifier[ident_len - 1])) {
147 identifier[--ident_len] = '\0';
148 }
149
150 if ((selected = neg(identifier, &quality, supported TSRMLS_CC))) {
151 /* don't overwrite previously set with higher quality */
152 if (!zend_hash_exists(Z_ARRVAL(array), selected, strlen(selected) + 1)) {
153 add_assoc_double(&array, selected, quality);
154 }
155 }
156
157 efree(freeme);
158 }
159
160 result = Z_ARRVAL(array);
161 zend_hash_sort(result, zend_qsort, php_http_negotiate_sort, 0 TSRMLS_CC);
162 }
163
164 zval_dtor(&ex_arr);
165 zval_dtor(&ex_val);
166 }
167
168 return result;
169 }
170
171
172
173 /*
174 * Local variables:
175 * tab-width: 4
176 * c-basic-offset: 4
177 * End:
178 * vim600: noet sw=4 ts=4 fdm=marker
179 * vim<600: noet sw=4 ts=4
180 */
181
182