- char *key = NULL;
- long idx = 0;
-
- FOREACH_HASH_KEY(HTTP_SERVER_VARS, key, idx) {
- if (key && !strncmp(key, "HTTP_", 5)) {
- zval **header;
- zend_hash_get_current_data(HTTP_SERVER_VARS, (void **) &header);
- add_assoc_stringl(array, pretty_key(key + 5, strlen(key) - 5, 1, 1), Z_STRVAL_PP(header), Z_STRLEN_PP(header), 1);
- }
- }
+ const char *key = cookie, *val = NULL;
+ int vallen = 0, keylen = 0, done = 0;
+ zval array;
+
+ Z_ARRVAL(array) = values;
+
+ if (!(val = strchr(cookie, '='))) {
+ return FAILURE;
+ }
+
+#define HTTP_COOKIE_VAL(array, k, str, len) \
+ { \
+ const char *encoded = str; \
+ char *decoded = NULL; \
+ int decoded_len = 0, encoded_len = len; \
+ decoded = estrndup(encoded, encoded_len); \
+ decoded_len = php_url_decode(decoded, encoded_len); \
+ add_assoc_stringl(array, k, decoded, decoded_len, 0); \
+ }
+#define HTTP_COOKIE_FIXKEY() \
+ { \
+ while (isspace(*key)) ++key; \
+ keylen = val - key; \
+ while (isspace(key[keylen - 1])) --keylen; \
+ }
+#define HTTP_COOKIE_FIXVAL() \
+ { \
+ ++val; \
+ while (isspace(*val)) ++val; \
+ vallen = key - val; \
+ while (isspace(val[vallen - 1])) --vallen; \
+ }
+
+ HTTP_COOKIE_FIXKEY();
+ HTTP_COOKIE_VAL(&array, "name", key, keylen);
+
+ /* just a name=value cookie */
+ if (!(key = strchr(val, ';'))) {
+ key = val + strlen(val);
+ HTTP_COOKIE_FIXVAL();
+ HTTP_COOKIE_VAL(&array, "value", val, vallen);
+ }
+ /* additional info appended */
+ else {
+ char *keydup = NULL;
+
+ HTTP_COOKIE_FIXVAL();
+ HTTP_COOKIE_VAL(&array, "value", val, vallen);
+
+ do {
+ if (!(val = strchr(key, '='))) {
+ break;
+ }
+ ++key;
+ HTTP_COOKIE_FIXKEY();
+ keydup = estrndup(key, keylen);
+ if (!(key = strchr(val, ';'))) {
+ done = 1;
+ key = val + strlen(val);
+ }
+ HTTP_COOKIE_FIXVAL();
+ HTTP_COOKIE_VAL(&array, keydup, val, vallen);
+ efree(keydup);
+ } while (!done);
+ }
+ return SUCCESS;