2 +--------------------------------------------------------------------+
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 +--------------------------------------------------------------------+
15 #include <ext/standard/php_string.h>
17 #ifndef PHP_HTTP_DBG_NEG
18 # define PHP_HTTP_DBG_NEG 0
21 char *php_http_negotiate_language_func(const char *test
, double *quality
, HashTable
*supported TSRMLS_DC
)
25 const char *dash_test
;
27 FOREACH_HASH_VAL(pos
, supported
, value
) {
29 fprintf(stderr
, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value
), test
);
31 if (!strcasecmp(Z_STRVAL_PP(value
), test
)) {
32 return Z_STRVAL_PP(value
);
36 /* no distinct match found, so try primaries */
37 if ((dash_test
= strchr(test
, '-'))) {
38 FOREACH_HASH_VAL(pos
, supported
, value
) {
39 int len
= dash_test
- test
;
41 fprintf(stderr
, "strncasecmp('%s', '%s', %d)\n", Z_STRVAL_PP(value
), test
, len
);
43 if ( (!strncasecmp(Z_STRVAL_PP(value
), test
, len
)) &&
44 ( (Z_STRVAL_PP(value
)[len
] == '\0') ||
45 (Z_STRVAL_PP(value
)[len
] == '-'))) {
47 return Z_STRVAL_PP(value
);
56 char *php_http_negotiate_default_func(const char *test
, double *quality
, HashTable
*supported TSRMLS_DC
)
62 FOREACH_HASH_VAL(pos
, supported
, value
) {
64 fprintf(stderr
, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value
), test
);
66 if (!strcasecmp(Z_STRVAL_PP(value
), test
)) {
67 return Z_STRVAL_PP(value
);
75 static int php_http_negotiate_sort(const void *a
, const void *b TSRMLS_DC
)
77 zval result
, *first
, *second
;
79 first
= *((zval
**) (*((Bucket
**) a
))->pData
);
80 second
= *((zval
**) (*((Bucket
**) b
))->pData
);
82 if (numeric_compare_function(&result
, first
, second TSRMLS_CC
) != SUCCESS
) {
85 return (Z_LVAL(result
) > 0 ? -1 : (Z_LVAL(result
) < 0 ? 1 : 0));
89 PHP_HTTP_API HashTable
*php_http_negotiate(const char *value
, HashTable
*supported
, php_http_negotiate_func_t neg TSRMLS_DC
)
91 HashTable
*result
= NULL
;
94 zval ex_arr
, ex_del
, ex_val
;
99 ZVAL_STRINGL(&ex_del
, ",", 1, 0);
100 ZVAL_STRING(&ex_val
, value
, 1);
103 php_explode(&ex_del
, &ex_val
, &ex_arr
, INT_MAX
);
105 if (zend_hash_num_elements(Z_ARRVAL(ex_arr
)) > 0) {
114 neg
= php_http_negotiate_default_func
;
117 FOREACH_HASH_VAL(pos
, Z_ARRVAL(ex_arr
), entry
) {
120 char *selected
, *identifier
, *freeme
;
121 const char *separator
;
124 fprintf(stderr
, "Checking %s\n", Z_STRVAL_PP(entry
));
127 if ((separator
= strchr(Z_STRVAL_PP(entry
), ';'))) {
128 const char *ptr
= separator
;
130 while (*++ptr
&& !PHP_HTTP_IS_CTYPE(digit
, *ptr
) && '.' != *ptr
);
132 quality
= zend_strtod(ptr
, NULL
);
133 identifier
= estrndup(Z_STRVAL_PP(entry
), ident_len
= separator
- Z_STRVAL_PP(entry
));
135 quality
= 1000.0 - i
++;
136 identifier
= estrndup(Z_STRVAL_PP(entry
), ident_len
= Z_STRLEN_PP(entry
));
140 while (PHP_HTTP_IS_CTYPE(space
, *identifier
)) {
144 while (ident_len
&& PHP_HTTP_IS_CTYPE(space
, identifier
[ident_len
- 1])) {
145 identifier
[--ident_len
] = '\0';
148 if ((selected
= neg(identifier
, &quality
, supported TSRMLS_CC
))) {
149 /* don't overwrite previously set with higher quality */
150 if (!zend_symtable_exists(Z_ARRVAL(array
), selected
, strlen(selected
) + 1)) {
151 add_assoc_double(&array
, selected
, quality
);
158 result
= Z_ARRVAL(array
);
159 zend_hash_sort(result
, zend_qsort
, php_http_negotiate_sort
, 0 TSRMLS_CC
);
176 * vim600: noet sw=4 ts=4 fdm=marker
177 * vim<600: noet sw=4 ts=4