+ php_http_buffer_appendl(&buf, url->path);
+ } else if (buf.used) {
+ php_http_buffer_appends(&buf, "/");
+ }
+
+ if (url->query && *url->query) {
+ php_http_buffer_appends(&buf, "?");
+ php_http_buffer_appendl(&buf, url->query);
+ }
+
+ if (url->fragment && *url->fragment) {
+ php_http_buffer_appends(&buf, "#");
+ php_http_buffer_appendl(&buf, url->fragment);
+ }
+
+ php_http_buffer_shrink(&buf);
+ php_http_buffer_fix(&buf);
+
+ if (url_len) {
+ *url_len = buf.used;
+ }
+
+ if (url_str) {
+ *url_str = buf.data;
+ }
+
+ return buf.data;
+}
+
+php_http_url_t *php_http_url_from_zval(zval *value, unsigned flags)
+{
+ zend_string *zs;
+ php_http_url_t *purl;
+
+ switch (Z_TYPE_P(value)) {
+ case IS_ARRAY:
+ case IS_OBJECT:
+ purl = php_http_url_from_struct(HASH_OF(value));
+ break;
+
+ default:
+ zs = zval_get_string(value);
+ purl = php_http_url_parse(zs->val, zs->len, flags);
+ zend_string_release(zs);
+ }
+
+ return purl;
+}
+
+php_http_url_t *php_http_url_from_struct(HashTable *ht)
+{
+ zval *e;
+ php_http_buffer_t buf;
+
+ php_http_buffer_init_ex(&buf, MAX(PHP_HTTP_BUFFER_DEFAULT_SIZE, sizeof(php_http_url_t)<<2), PHP_HTTP_BUFFER_INIT_PREALLOC);
+ php_http_buffer_account(&buf, sizeof(php_http_url_t));
+ memset(buf.data, 0, buf.used);
+
+ if ((e = zend_hash_str_find(ht, ZEND_STRL("scheme")))) {
+ zend_string *zs = zval_get_string(e);
+ url(buf)->scheme = &buf.data[buf.used];
+ php_http_buffer_append(&buf, zs->val, zs->len + 1);
+ zend_string_release(zs);
+ }
+ if ((e = zend_hash_str_find(ht, ZEND_STRL("user")))) {
+ zend_string *zs = zval_get_string(e);
+ url(buf)->user = &buf.data[buf.used];
+ php_http_buffer_append(&buf, zs->val, zs->len + 1);
+ zend_string_release(zs);
+ }
+ if ((e = zend_hash_str_find(ht, ZEND_STRL("pass")))) {
+ zend_string *zs = zval_get_string(e);
+ url(buf)->pass = &buf.data[buf.used];
+ php_http_buffer_append(&buf, zs->val, zs->len + 1);
+ zend_string_release(zs);
+ }
+ if ((e = zend_hash_str_find(ht, ZEND_STRL("host")))) {
+ zend_string *zs = zval_get_string(e);
+ url(buf)->host = &buf.data[buf.used];
+ php_http_buffer_append(&buf, zs->val, zs->len + 1);
+ zend_string_release(zs);
+ }
+ if ((e = zend_hash_str_find(ht, ZEND_STRL("port")))) {
+ url(buf)->port = (unsigned short) zval_get_long(e);
+ }
+ if ((e = zend_hash_str_find(ht, ZEND_STRL("path")))) {
+ zend_string *zs = zval_get_string(e);
+ url(buf)->path = &buf.data[buf.used];
+ php_http_buffer_append(&buf, zs->val, zs->len + 1);
+ zend_string_release(zs);
+ }
+ if ((e = zend_hash_str_find(ht, ZEND_STRL("query")))) {
+ zend_string *zs = zval_get_string(e);
+ url(buf)->query = &buf.data[buf.used];
+ php_http_buffer_append(&buf, zs->val, zs->len + 1);
+ zend_string_release(zs);
+ }
+ if ((e = zend_hash_str_find(ht, ZEND_STRL("fragment")))) {
+ zend_string *zs = zval_get_string(e);
+ url(buf)->fragment = &buf.data[buf.used];
+ php_http_buffer_append(&buf, zs->val, zs->len + 1);
+ zend_string_release(zs);
+ }
+
+ return url(buf);
+}
+
+HashTable *php_http_url_to_struct(const php_http_url_t *url, zval *strct)
+{
+ HashTable *ht;
+ zval tmp;
+
+ if (strct) {
+ switch (Z_TYPE_P(strct)) {
+ default:
+ zval_dtor(strct);
+ array_init(strct);
+ /* no break */
+ case IS_ARRAY:
+ case IS_OBJECT:
+ ht = HASH_OF(strct);
+ break;