+--------------------------------------------------------------------+
*/
-#include "php_http.h"
-
-#include <ext/standard/php_string.h>
-#include <Zend/zend_interfaces.h>
+#include "php_http_api.h"
static php_http_params_token_t def_param_sep = {",", 1}, *def_param_sep_ptr[] = {&def_param_sep, NULL};
static php_http_params_token_t def_arg_sep = {";", 1}, *def_arg_sep_ptr[] = {&def_arg_sep, NULL};
} current;
} php_http_params_state_t;
+static inline void sanitize_string(char *str, size_t len, zval *zv TSRMLS_DC)
+{
+ /* trim whitespace */
+ php_trim(str, len, NULL, 0, zv, 3 TSRMLS_CC);
+
+ /* dequote */
+ if (Z_STRVAL_P(zv)[0] == '"' && Z_STRVAL_P(zv)[Z_STRLEN_P(zv) - 1] == '"') {
+ size_t deq_len = Z_STRLEN_P(zv) - 2;
+ char *deq = estrndup(Z_STRVAL_P(zv) + 1, deq_len);
+
+ zval_dtor(zv);
+ ZVAL_STRINGL(zv, deq, deq_len, 0);
+ }
+
+ /* strip slashes */
+ php_stripslashes(Z_STRVAL_P(zv), &Z_STRLEN_P(zv) TSRMLS_CC);
+}
+
static void push_param(HashTable *params, php_http_params_state_t *state, const php_http_params_opts_t *opts TSRMLS_DC)
{
if (state->val.str) {
if (0 < (state->val.len = state->input.str - state->val.str)) {
- php_trim(state->val.str, state->val.len, NULL, 0, *(state->current.val), 3 TSRMLS_CC);
+ sanitize_string(state->val.str, state->val.len, *(state->current.val) TSRMLS_CC);
}
} else if (state->arg.str) {
if (0 < (state->arg.len = state->input.str - state->arg.str)) {
zval *val, key;
INIT_PZVAL(&key);
- php_trim(state->arg.str, state->arg.len, NULL, 0, &key, 3 TSRMLS_CC);
- MAKE_STD_ZVAL(val);
- ZVAL_TRUE(val);
- zend_symtable_update(Z_ARRVAL_PP(state->current.args), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val);
-
+ sanitize_string(state->arg.str, state->arg.len, &key TSRMLS_CC);
+ if (Z_STRLEN(key)) {
+ MAKE_STD_ZVAL(val);
+ ZVAL_TRUE(val);
+ zend_symtable_update(Z_ARRVAL_PP(state->current.args), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val);
+ }
zval_dtor(&key);
}
} else if (state->param.str) {
if (0 < (state->param.len = state->input.str - state->param.str)) {
zval *prm, *arg, *val, key;
- MAKE_STD_ZVAL(prm);
- array_init(prm);
- MAKE_STD_ZVAL(val);
- ZVAL_TRUE(val);
- zend_hash_update(Z_ARRVAL_P(prm), "value", sizeof("value"), (void *) &val, sizeof(zval *), (void *) &state->current.val);
-
- MAKE_STD_ZVAL(arg);
- array_init(arg);
- zend_hash_update(Z_ARRVAL_P(prm), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &state->current.args);
-
INIT_PZVAL(&key);
- php_trim(state->param.str, state->param.len, NULL, 0, &key, 3 TSRMLS_CC);
- zend_symtable_update(params, Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &prm, sizeof(zval *), (void *) &state->current.param);
-
+ sanitize_string(state->param.str, state->param.len, &key TSRMLS_CC);
+ if (Z_STRLEN(key)) {
+ MAKE_STD_ZVAL(prm);
+ array_init(prm);
+ MAKE_STD_ZVAL(val);
+ ZVAL_TRUE(val);
+ zend_hash_update(Z_ARRVAL_P(prm), "value", sizeof("value"), (void *) &val, sizeof(zval *), (void *) &state->current.val);
+
+ MAKE_STD_ZVAL(arg);
+ array_init(arg);
+ zend_hash_update(Z_ARRVAL_P(prm), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &state->current.args);
+
+ zend_symtable_update(params, Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &prm, sizeof(zval *), (void *) &state->current.param);
+ }
zval_dtor(&key);
}
}
PHP_HTTP_API HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t *opts TSRMLS_DC)
{
- php_http_params_state_t state = {
- .input.str = opts->input.str,
- .input.len = opts->input.len,
- .param.str = NULL,
- .param.len = 0,
- .arg.str = NULL,
- .arg.len = 0,
- .val.str = NULL,
- .val.len = 0
- };
+ php_http_params_state_t state = {{NULL,0}, {NULL,0}, {NULL,0}, {NULL,0}, {NULL,NULL,NULL}};
+
+ state.input.str = opts->input.str;
+ state.input.len = opts->input.len;
if (!params) {
ALLOC_HASHTABLE(params);
return params;
}
+PHP_HTTP_API php_http_buffer_t *php_http_params_to_string(php_http_buffer_t *buf, HashTable *params, const char *pss, size_t psl, const char *ass, size_t asl, const char *vss, size_t vsl TSRMLS_DC)
+{
+ zval **zparam;
+ HashPosition pos1, pos2;
+ php_http_array_hashkey_t key1 = php_http_array_hashkey_init(0), key2 = php_http_array_hashkey_init(0);
+
+ if (!buf) {
+ buf = php_http_buffer_init(NULL);
+ }
+
+ FOREACH_HASH_KEYVAL(pos1, params, key1, zparam) {
+ /* new param ? */
+ if (PHP_HTTP_BUFFER_LEN(buf)) {
+ php_http_buffer_append(buf, pss, psl);
+ }
+
+ /* add name */
+ if (key1.type == HASH_KEY_IS_STRING) {
+ php_http_buffer_append(buf, key1.str, key1.len - 1);
+ } else {
+ php_http_buffer_appendf(buf, "%lu", key1.num);
+ }
+
+ if (Z_TYPE_PP(zparam) != IS_ARRAY) {
+ zval *tmp = php_http_ztyp(IS_STRING, *zparam);
+
+ php_http_buffer_append(buf, vss, vsl);
+ php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
+ zval_ptr_dtor(&tmp);
+ } else {
+ zval **zvalue, **zargs, **zarg;
+
+ /* got a value? */
+ if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) {
+ if (Z_TYPE_PP(zvalue) != IS_BOOL) {
+ zval *tmp = php_http_ztyp(IS_STRING, *zvalue);
+
+ php_http_buffer_append(buf, vss, vsl);
+ php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
+ zval_ptr_dtor(&tmp);
+ } else if (!Z_BVAL_PP(zvalue)) {
+ php_http_buffer_append(buf, vss, vsl);
+ php_http_buffer_appends(buf, "0");
+ }
+ }
+ /* add arguments */
+ if (SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zargs)) {
+ zargs = zparam;
+ }
+
+ if (Z_TYPE_PP(zargs) == IS_ARRAY) {
+ FOREACH_KEYVAL(pos2, *zargs, key2, zarg) {
+ /* skip "value" if zargs == zparam */
+ if (zargs == zparam && key2.type == HASH_KEY_IS_STRING && !strcmp(key2.str, "value")) {
+ continue;
+ }
+
+ /* new arg? */
+ if (PHP_HTTP_BUFFER_LEN(buf)) {
+ php_http_buffer_append(buf, ass, asl);
+ }
+
+ /* add name */
+ if (key2.type == HASH_KEY_IS_STRING) {
+ php_http_buffer_append(buf, key2.str, key2.len - 1);
+ } else {
+ php_http_buffer_appendf(buf, "%lu", key2.num);
+ }
+ /* add value */
+ if (Z_TYPE_PP(zarg) != IS_BOOL) {
+ zval *tmp = php_http_ztyp(IS_STRING, *zarg);
+ int escaped_len;
+
+ Z_STRVAL_P(tmp) = php_addslashes(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), &escaped_len, 1 TSRMLS_CC);
+ php_http_buffer_append(buf, vss, vsl);
+ if (escaped_len != Z_STRLEN_P(tmp)) {
+ php_http_buffer_appends(buf, "\"");
+ php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) = escaped_len);
+ php_http_buffer_appends(buf, "\"");
+ } else {
+ php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
+ }
+ zval_ptr_dtor(&tmp);
+ } else if (!Z_BVAL_PP(zarg)) {
+ php_http_buffer_append(buf, vss, vsl);
+ php_http_buffer_appends(buf, "0");
+ }
+ }
+ }
+ }
+ }
+
+ php_http_buffer_shrink(buf);
+ php_http_buffer_fix(buf);
+
+ return buf;
+}
+
#define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpParams, method, 0, req_args)
#define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpParams, method, 0)
#define PHP_HTTP_PARAMS_ME(method, visibility) PHP_ME(HttpParams, method, PHP_HTTP_ARGS(HttpParams, method), visibility)
PHP_HTTP_BEGIN_ARGS(__construct, 0)
PHP_HTTP_ARG_VAL(params, 0)
- PHP_HTTP_ARG_VAL(flags, 0)
+ PHP_HTTP_ARG_VAL(param_sep, 0)
+ PHP_HTTP_ARG_VAL(arg_sep, 0)
+ PHP_HTTP_ARG_VAL(val_sep, 0)
PHP_HTTP_END_ARGS;
PHP_HTTP_EMPTY_ARGS(toArray);
if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z/z/z/", &zparams, ¶m_sep, &arg_sep, &val_sep)) {
switch (ZEND_NUM_ARGS()) {
case 4:
- zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), param_sep TSRMLS_CC);
+ zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), val_sep TSRMLS_CC);
+ /* no break */
case 3:
zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), arg_sep TSRMLS_CC);
+ /* no break */
case 2:
- zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), val_sep TSRMLS_CC);
+ zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), param_sep TSRMLS_CC);
+ /* no break */
}
if (zparams) {
zcopy = php_http_ztyp(IS_STRING, zparams);
if (Z_STRLEN_P(zcopy)) {
php_http_params_opts_t opts = {
- .input.str = Z_STRVAL_P(zcopy),
- .input.len = Z_STRLEN_P(zcopy),
+ .input = {
+ .str = Z_STRVAL_P(zcopy),
+ .len = Z_STRLEN_P(zcopy)
+ },
.param = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC) TSRMLS_CC),
.arg = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC) TSRMLS_CC),
.val = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC) TSRMLS_CC)
PHP_METHOD(HttpParams, toString)
{
zval *zparams, *zpsep, *zasep, *zvsep;
- zval **zparam, **zvalue, **zargs, **zarg;
- HashPosition pos1, pos2;
- php_http_array_hashkey_t key1 = php_http_array_hashkey_init(0), key2 = php_http_array_hashkey_init(0);
php_http_buffer_t buf;
zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
zpsep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC));
zasep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC));
zvsep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC));
- php_http_buffer_init(&buf);
-
- FOREACH_KEYVAL(pos1, zparams, key1, zparam) {
- /* new param ? */
- if (PHP_HTTP_BUFFER_LEN(&buf)) {
- php_http_buffer_append(&buf, Z_STRVAL_P(zpsep), Z_STRLEN_P(zpsep));
- }
-
- /* add name */
- if (key1.type == HASH_KEY_IS_STRING) {
- php_http_buffer_append(&buf, key1.str, key1.len - 1);
- } else {
- php_http_buffer_appendf(&buf, "%lu", key1.num);
- }
-
- if (Z_TYPE_PP(zparam) == IS_ARRAY) {
- /* got a value? */
- if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) {
- if (Z_TYPE_PP(zvalue) != IS_BOOL) {
- zval *tmp = php_http_ztyp(IS_STRING, *zvalue);
-
- php_http_buffer_append(&buf, Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep));
- php_http_buffer_append(&buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
- zval_ptr_dtor(&tmp);
- } else if (!Z_BVAL_PP(zvalue)) {
- php_http_buffer_append(&buf, Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep));
- php_http_buffer_appends(&buf, "0");
- }
- }
- /* add arguments */
- if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zargs)) {
- if (Z_TYPE_PP(zargs) == IS_ARRAY) {
- FOREACH_KEYVAL(pos2, *zargs, key2, zarg) {
- /* new arg? */
- if (PHP_HTTP_BUFFER_LEN(&buf)) {
- php_http_buffer_append(&buf, Z_STRVAL_P(zasep), Z_STRLEN_P(zasep));
- }
- /* add name */
- if (key2.type == HASH_KEY_IS_STRING) {
- php_http_buffer_append(&buf, key2.str, key2.len - 1);
- } else {
- php_http_buffer_appendf(&buf, "%lu", key2.num);
- }
- /* add value */
- if (Z_TYPE_PP(zarg) != IS_BOOL) {
- zval *tmp = php_http_ztyp(IS_STRING, *zarg);
-
- php_http_buffer_append(&buf, Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep));
- php_http_buffer_append(&buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
- zval_ptr_dtor(&tmp);
- } else if (!Z_BVAL_PP(zarg)) {
- php_http_buffer_append(&buf, Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep));
- php_http_buffer_appends(&buf, "0");
- }
- }
- }
- }
- }
- }
+ php_http_buffer_init(&buf);
+ php_http_params_to_string(&buf, Z_ARRVAL_P(zparams), Z_STRVAL_P(zpsep), Z_STRLEN_P(zpsep), Z_STRVAL_P(zasep), Z_STRLEN_P(zasep), Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep) TSRMLS_CC);
zval_ptr_dtor(&zparams);
zval_ptr_dtor(&zpsep);
zval_ptr_dtor(&zasep);
zval_ptr_dtor(&zvsep);
- php_http_buffer_shrink(&buf);
RETVAL_PHP_HTTP_BUFFER_VAL(&buf);
}