+/* }}} */
+
+/* {{{ http_cookie_list *http_cookie_list_fromstruct(http_cookie_list *, zval *strct) */
+PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC)
+{
+ zval **tmp, *cpy;
+ HashTable *ht = HASH_OF(strct);
+
+ list = http_cookie_list_init(list);
+
+ if (SUCCESS == zend_hash_find(ht, "cookies", sizeof("cookies"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
+ zend_hash_copy(&list->cookies, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
+ }
+ if (SUCCESS == zend_hash_find(ht, "extras", sizeof("extras"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
+ zend_hash_copy(&list->extras, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
+ }
+ if (SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &tmp)) {
+ switch (Z_TYPE_PP(tmp)) {
+ case IS_LONG:
+ list->flags = Z_LVAL_PP(tmp);
+ break;
+ case IS_DOUBLE:
+ list->flags = (long) Z_DVAL_PP(tmp);
+ break;
+ case IS_STRING:
+ cpy = *tmp;
+ convert_to_long_ex(&cpy);
+ list->flags = Z_LVAL_PP(tmp);
+ if (cpy != *tmp) {
+ zval_ptr_dtor(&cpy);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (SUCCESS == zend_hash_find(ht, "expires", sizeof("expires"), (void *) &tmp)) {
+ switch (Z_TYPE_PP(tmp)) {
+ case IS_LONG:
+ list->expires = Z_LVAL_PP(tmp);
+ break;
+ case IS_DOUBLE:
+ list->expires = (long) Z_DVAL_PP(tmp);
+ break;
+ case IS_STRING:
+ cpy = *tmp;
+ convert_to_long_ex(&cpy);
+ if (Z_LVAL_P(cpy)) {
+ list->expires = Z_LVAL_P(cpy);
+ } else {
+ time_t expires = http_parse_date(Z_STRVAL_PP(tmp));
+ if (expires > 0) {
+ list->expires = expires;
+ }
+ }
+ if (cpy != *tmp) {
+ zval_ptr_dtor(&cpy);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
+ list->path = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+ }
+ if (SUCCESS == zend_hash_find(ht, "domain", sizeof("domain"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
+ list->domain = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+ }
+
+ return list;
+}
+/* }}} */
+
+/* {{{ inline append_encoded */
+static inline void append_encoded(phpstr *buf, const char *key, size_t key_len, const char *val, size_t val_len)
+{
+ char *enc_str[2];
+ int enc_len[2];
+
+ enc_str[0] = php_url_encode(key, key_len, &enc_len[0]);
+ enc_str[1] = php_url_encode(val, val_len, &enc_len[1]);
+
+ phpstr_append(buf, enc_str[0], enc_len[0]);
+ phpstr_appends(buf, "=");
+ phpstr_append(buf, enc_str[1], enc_len[1]);
+ phpstr_appends(buf, "; ");
+
+ efree(enc_str[0]);
+ efree(enc_str[1]);
+}
+/* }}} */
+
+/* {{{ void http_cookie_list_tostring(http_cookie_list *, char **, size_t *) */
+PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC)
+{
+ phpstr buf;
+ zval **val;
+ HashKey key = initHashKey(0);
+ HashPosition pos;
+
+ phpstr_init(&buf);
+
+ FOREACH_HASH_KEYVAL(pos, &list->cookies, key, val) {
+ if (key.type == HASH_KEY_IS_STRING && key.len) {
+ append_encoded(&buf, key.str, key.len-1, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
+ }
+ }
+
+ if (list->domain && *list->domain) {
+ phpstr_appendf(&buf, "domain=%s; ", list->domain);
+ }
+ if (list->path && *list->path) {
+ phpstr_appendf(&buf, "path=%s; ", list->path);
+ }
+ if (list->expires) {
+ char *date = http_date(list->expires);
+ phpstr_appendf(&buf, "expires=%s; ", date);
+ efree(date);
+ }
+
+ FOREACH_HASH_KEYVAL(pos, &list->extras, key, val) {
+ if (key.type == HASH_KEY_IS_STRING && key.len) {
+ append_encoded(&buf, key.str, key.len-1, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
+ }
+ }
+
+ if (list->flags & HTTP_COOKIE_SECURE) {
+ phpstr_appends(&buf, "secure; ");
+ }
+ if (list->flags & HTTP_COOKIE_HTTPONLY) {
+ phpstr_appends(&buf, "httpOnly; ");
+ }
+
+ phpstr_fix(&buf);
+ *str = PHPSTR_VAL(&buf);
+ *len = PHPSTR_LEN(&buf);
+}
+/* }}} */