}
$this->saveFeed($this->url2name($r->getUrl()), $body);
}
+ echo $r->getHistory();
}
}
+$a = new FeedAggregator();
+$a->getFeed('http://www.planet-php.net/rss/');
?>
PHP_INI_END()
/* }}} */
-/* {{{ SSL */
-#ifdef HTTP_NEED_SSL
-
-#endif
-/* }}} */
-
/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(http)
{
int i, c = zend_hash_num_elements(&HTTP_G(request).methods.custom);
for (i = 0; i < c; ++i) {
- zend_printf("RSHUTDOWN: unregistering %d (%d)\n", i,
- http_request_method_unregister(HTTP_MAX_REQUEST_METHOD + i));
+ http_request_method_unregister(HTTP_MAX_REQUEST_METHOD + i);
}
#endif
http_globals_free(HTTP_GLOBALS);
}
/* }}} */
-/* {{{ proto string http_negotiate_language(array supported[, string default = 'en-US'])
+#define HTTP_DO_NEGOTIATE(type, supported, as_array) \
+{ \
+ HashTable *result; \
+ if (result = http_negotiate_ ##type(supported)) { \
+ if (as_array) { \
+ Z_TYPE_P(return_value) = IS_ARRAY; \
+ Z_ARRVAL_P(return_value) = result; \
+ } else { \
+ char *key; \
+ uint key_len; \
+ ulong idx; \
+ \
+ if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(result, &key, &key_len, &idx, 1, NULL)) { \
+ RETVAL_STRINGL(key, key_len-1, 0); \
+ } else { \
+ RETVAL_NULL(); \
+ } \
+ zend_hash_destroy(result); \
+ } \
+ } else { \
+ if (as_array) { \
+ zval **value; \
+ \
+ array_init(return_value); \
+ \
+ FOREACH_VAL(supported, value) { \
+ convert_to_string_ex(value); \
+ add_assoc_double(return_value, Z_STRVAL_PP(value), 1.0); \
+ } \
+ } else { \
+ zval **value; \
+ \
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(supported)); \
+ if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void **) &value)) { \
+ RETVAL_ZVAL(*value, 1, 0); \
+ } else { \
+ RETVAL_NULL(); \
+ } \
+ } \
+ } \
+}
+
+
+/* {{{ proto string http_negotiate_language(array supported[, bool return_quality_array = false])
*
* This function negotiates the clients preferred language based on its
* Accept-Language HTTP header. It returns the negotiated language or
- * the default language if none match.
+ * the default language (i.e. first array entry) if none match.
*
* The qualifier is recognized and languages without qualifier are rated highest.
*
PHP_FUNCTION(http_negotiate_language)
{
zval *supported;
- char *def = NULL;
- int def_len = 0;
+ zend_bool as_array = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|s", &supported, &def, &def_len) != SUCCESS) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &supported, &as_array) != SUCCESS) {
RETURN_FALSE;
}
-
- if (!def) {
- def = "en-US";
- }
-
- RETURN_STRING(http_negotiate_language(supported, def), 0);
+
+ HTTP_DO_NEGOTIATE(language, supported, as_array);
}
/* }}} */
-/* {{{ proto string http_negotiate_charset(array supported[, string default = 'iso-8859-1'])
+/* {{{ proto string http_negotiate_charset(array supported)
*
* This function negotiates the clients preferred charset based on its
* Accept-Charset HTTP header. It returns the negotiated charset or
- * the default charset if none match.
+ * the default charset (i.e. first array entry) if none match.
*
* The qualifier is recognized and charset without qualifier are rated highest.
*
PHP_FUNCTION(http_negotiate_charset)
{
zval *supported;
- char *def = NULL;
- int def_len = 0;
+ zend_bool as_array = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|s", &supported, &def, &def_len) != SUCCESS) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &supported, &as_array) != SUCCESS) {
RETURN_FALSE;
}
- if (!def) {
- def = "iso-8859-1";
- }
-
- RETURN_STRING(http_negotiate_charset(supported, def), 0);
+ HTTP_DO_NEGOTIATE(charset, supported, as_array);
}
/* }}} */
ZEND_EXTERN_MODULE_GLOBALS(http);
+#ifndef HTTP_DBG_NEG
+# define HTTP_DBG_NEG 0
+#endif
+
/* {{{ static int http_sort_q(const void *, const void *) */
static int http_sort_q(const void *a, const void *b TSRMLS_DC)
{
}
/* }}} */
-/* {{{ char *http_negotiate_q(char *, HashTable *, char *) */
-PHP_HTTP_API char *_http_negotiate_q(const char *entry, const HashTable *supported, const char *def TSRMLS_DC)
+/* {{{ char *http_negotiate_language_func */
+char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
{
- zval *zaccept, zdelim, zarray, zentries, **zentry, **zsupp;
- char *q_ptr = NULL, *key = NULL;
- int i = 0;
- ulong idx = 0;
- double qual;
-
- HTTP_GSC(zaccept, entry, estrdup(def));
-
- array_init(&zarray);
- array_init(&zentries);
-
- Z_STRVAL(zdelim) = ",";
- Z_STRLEN(zdelim) = 1;
-
- php_explode(&zdelim, zaccept, &zarray, -1);
-
- FOREACH_HASH_VAL(Z_ARRVAL(zarray), zentry) {
- if (q_ptr = strrchr(Z_STRVAL_PP(zentry), ';')) {
- qual = strtod(q_ptr + 3, NULL);
- *q_ptr = 0;
- q_ptr = NULL;
- } else {
- qual = 1000.0 - i++;
+ zval **value;
+ const char *dash_test;
+
+ FOREACH_HASH_VAL(supported, value) {
+#if HTTP_DBG_NEG
+ fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
+#endif
+ if (!strcasecmp(Z_STRVAL_PP(value), test)) {
+ return Z_STRVAL_PP(value);
}
- /* TODO: support primaries only, too */
- FOREACH_HASH_VAL((HashTable *)supported, zsupp) {
- if (!strcasecmp(Z_STRVAL_PP(zsupp), Z_STRVAL_PP(zentry))) {
- add_assoc_double(&zentries, Z_STRVAL_PP(zsupp), qual);
- break;
+ }
+
+ /* no distinct match found, so try primaries */
+ if (dash_test = strchr(test, '-')) {
+ FOREACH_HASH_VAL(supported, value) {
+ int len = dash_test - test;
+#if HTTP_DBG_NEG
+ fprintf(stderr, "strncascmp('%s', '%s', %d)\n", Z_STRVAL_PP(value), test, len);
+#endif
+ if ( (!strncasecmp(Z_STRVAL_PP(value), test, len)) &&
+ ( (Z_STRVAL_PP(value)[len] == '\0') ||
+ (Z_STRVAL_PP(value)[len] == '-'))) {
+ *quality /= 2;
+ return Z_STRVAL_PP(value);
}
}
}
- zval_dtor(&zarray);
-
- zend_hash_sort(Z_ARRVAL(zentries), zend_qsort, http_sort_q, 0 TSRMLS_CC);
+
+ return NULL;
+}
+/* }}} */
- FOREACH_HASH_KEY(Z_ARRVAL(zentries), key, idx) {
- if (key) {
- key = estrdup(key);
- zval_dtor(&zentries);
- return key;
+/* {{{ char *http_negotiate_charset_func */
+char *_http_negotiate_charset_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
+{
+ zval **value;
+
+ FOREACH_HASH_VAL(supported, value) {
+#if HTTP_DBG_NEG
+ fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
+#endif
+ if (!strcasecmp(Z_STRVAL_PP(value), test)) {
+ return Z_STRVAL_PP(value);
}
}
- zval_dtor(&zentries);
+
+ return NULL;
+}
+/* }}} */
- return estrdup(def);
+/* {{{ HashTable *http_negotiate_q(const char *, HashTable *, negotiate_func_t) */
+PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC)
+{
+ zval *accept;
+ HashTable *result = NULL;
+
+#if HTTP_DBG_NEG
+ fprintf(stderr, "Reading header %s: ", header);
+#endif
+ HTTP_GSC(accept, header, NULL);
+#if HTTP_DBG_NEG
+ fprintf(stderr, "%s\n", Z_STRVAL_P(accept));
+#endif
+
+ if (Z_STRLEN_P(accept)) {
+ zval ex_arr, ex_del;
+
+ INIT_PZVAL(&ex_del);
+ INIT_PZVAL(&ex_arr);
+ ZVAL_STRINGL(&ex_del, ",", 1, 0);
+ array_init(&ex_arr);
+
+ php_explode(&ex_del, accept, &ex_arr, -1);
+
+ if (zend_hash_num_elements(Z_ARRVAL(ex_arr)) > 0) {
+ int i = 0;
+ zval **entry, array;
+
+ INIT_PZVAL(&array);
+ array_init(&array);
+
+ FOREACH_HASH_VAL(Z_ARRVAL(ex_arr), entry) {
+ double quality;
+ char *selected, *identifier;
+ const char *separator;
+
+#if HTTP_DBG_NEG
+ fprintf(stderr, "Checking %s\n", Z_STRVAL_PP(entry));
+#endif
+
+ if (separator = strchr(Z_STRVAL_PP(entry), ';')) {
+ const char *ptr = separator;
+
+ do {
+ ++ptr;
+ } while ((*ptr == ' ') || (*ptr == 'q') || (*ptr == '='));
+
+ quality = strtod(ptr, NULL);
+ identifier = estrndup(Z_STRVAL_PP(entry), separator - Z_STRVAL_PP(entry));
+ } else {
+ quality = 1000.0 - i++;
+ identifier = estrndup(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry));
+ }
+
+ if (selected = neg(identifier, &quality, supported TSRMLS_CC)) {
+ /* don't overwrite previously set with higher quality */
+ if (!zend_hash_exists(Z_ARRVAL(array), selected, strlen(selected) + 1)) {
+ add_assoc_double(&array, selected, quality);
+ }
+ }
+
+ efree(identifier);
+ }
+
+ result = Z_ARRVAL(array);
+ zend_hash_sort(result, zend_qsort, http_sort_q, 0 TSRMLS_CC);
+ }
+
+ zval_dtor(&ex_arr);
+ }
+
+ return result;
}
/* }}} */
#define http_get_request_headers_ex(h, p) _http_get_request_headers_ex((h), (p) TSRMLS_CC)
PHP_HTTP_API void _http_get_request_headers_ex(HashTable *headers, zend_bool prettify TSRMLS_DC);
-#define http_negotiate_language(zsupported, def) http_negotiate_language_ex(Z_ARRVAL_P(zsupported), (def))
-#define http_negotiate_language_ex(supported, def) http_negotiate_q("HTTP_ACCEPT_LANGUAGE", (supported), (def))
-#define http_negotiate_charset(zsupported, def) http_negotiate_charset_ex(Z_ARRVAL_P(zsupported), (def))
-#define http_negotiate_charset_ex(supported, def) http_negotiate_q("HTTP_ACCEPT_CHARSET", (supported), (def))
-#define http_negotiate_q(e, s, d) _http_negotiate_q((e), (s), (d) TSRMLS_CC)
-PHP_HTTP_API char *_http_negotiate_q(const char *entry, const HashTable *supported, const char *def TSRMLS_DC);
+typedef char *(*negotiate_func_t)(const char *test, double *quality, HashTable *supported TSRMLS_DC);
+
+#define http_negotiate_language_func _http_negotiate_language_func
+extern char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC);
+#define http_negotiate_charset_func _http_negotiate_charset_func
+extern char *_http_negotiate_charset_func(const char *test, double *quality, HashTable *supported TSRMLS_DC);
+
+#define http_negotiate_language(zsupported) http_negotiate_language_ex(Z_ARRVAL_P(zsupported))
+#define http_negotiate_language_ex(supported) http_negotiate_q("HTTP_ACCEPT_LANGUAGE", (supported), http_negotiate_language_func)
+#define http_negotiate_charset(zsupported) http_negotiate_charset_ex(Z_ARRVAL_P(zsupported))
+#define http_negotiate_charset_ex(supported) http_negotiate_q("HTTP_ACCEPT_CHARSET", (supported), http_negotiate_charset_func)
+#define http_negotiate_q(e, s, n) _http_negotiate_q((e), (s), (n) TSRMLS_CC)
+PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC);
#define http_get_request_ranges(r, l) _http_get_request_ranges((r), (l) TSRMLS_CC)
PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC);
--- /dev/null
+--TEST--
+negotiation
+--SKIPIF--
+<?php
+include 'skip.inc';
+?>
+--ENV--
+HTTP_ACCEPT_LANGUAGE=de-AT,de-DE;q=0.8,en-GB;q=0.3,en-US;q=0.2
+HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7
+--FILE--
+<?php
+echo "-TEST\n";
+$langs = array(
+ array('de', 'en', 'es'),
+);
+$csets = array(
+ array('utf-8', 'iso-8859-1'),
+);
+var_dump(http_negotiate_language($langs[0]));
+print_r(http_negotiate_language($langs[0], true));
+var_dump(http_negotiate_charset($csets[0]));
+print_r(http_negotiate_charset($csets[0], true));
+echo "Done\n";
+--EXPECTF--
+%sTEST
+string(2) "de"
+Array
+(
+ [de] => 500
+ [en] => 0.15
+)
+string(10) "iso-8859-1"
+Array
+(
+ [iso-8859-1] => 1000
+ [utf-8] => 0.7
+)
+Done