Skip to content

Commit

Permalink
Merge pull request #888 from sjinks/hasfiles-nested
Browse files Browse the repository at this point in the history
[BUG] Phalcon\Http\Request::hasFiles() and getUploadedFiles() do not work with file arrays
  • Loading branch information
Phalcon committed Jul 22, 2013
2 parents 4d3e5db + a821e78 commit 3fba27a
Show file tree
Hide file tree
Showing 5 changed files with 492 additions and 94 deletions.
295 changes: 206 additions & 89 deletions ext/http/request.c
Original file line number Diff line number Diff line change
Expand Up @@ -1135,66 +1135,165 @@ PHP_METHOD(Phalcon_Http_Request, isOptions){
RETURN_MM();
}

static int phalcon_http_request_hasfiles_helper(zval *arr, int only_successful)
{
HashTable *ah0;
HashPosition hp0;
zval **hd;
int nfiles = 0;

assert(Z_TYPE_P(arr) == IS_ARRAY);

phalcon_is_iterable_ex(arr, &ah0, &hp0, 0, 0);
while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) {
if (Z_TYPE_PP(hd) < IS_ARRAY) {
if (!zend_is_true(*hd) || !only_successful) {
++nfiles;
}
}
else if (Z_TYPE_PP(hd) == IS_ARRAY) {
nfiles += phalcon_http_request_hasfiles_helper(*hd, only_successful);
}

zend_hash_move_forward_ex(ah0, &hp0);
}

return nfiles;
}

/**
* Checks whether request include attached files
* Checks whether request includes attached files
*
* @return boolean
*/
PHP_METHOD(Phalcon_Http_Request, hasFiles){

zval *not_errored = NULL, *files = NULL, *_FILES, *zero, *number_files = NULL;
zval *file = NULL, *error = NULL;
zval *not_errored = NULL, *_FILES, *error = NULL;
HashTable *ah0;
HashPosition hp0;
zval **hd;
int nfiles = 0;
int only_successful;

PHALCON_MM_GROW();

phalcon_fetch_params(1, 0, 1, &not_errored);
phalcon_fetch_params(0, 0, 1, &not_errored);

if (!not_errored) {
PHALCON_INIT_VAR(not_errored);
ZVAL_BOOL(not_errored, 0);
}
only_successful = not_errored ? phalcon_get_intval(not_errored) : 1;

phalcon_get_global(&_FILES, SS("_FILES") TSRMLS_CC);
PHALCON_CPY_WRT(files, _FILES);

PHALCON_INIT_VAR(zero);
ZVAL_LONG(zero, 0);
if (zend_is_true(not_errored)) {
PHALCON_INIT_VAR(number_files);
phalcon_fast_count(number_files, _FILES TSRMLS_CC);
} else {
PHALCON_INIT_NVAR(number_files);
ZVAL_LONG(number_files, 0);

phalcon_is_iterable(files, &ah0, &hp0, 0, 0);

while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) {

PHALCON_GET_HVALUE(file);

if (phalcon_array_isset_string(file, SS("error"))) {
PHALCON_OBS_NVAR(error);
phalcon_array_fetch_string(&error, file, SL("error"), PH_NOISY);
} else {
PHALCON_INIT_NVAR(error);
ZVAL_BOOL(error, 1);
if (unlikely(Z_TYPE_P(_FILES) != IS_ARRAY)) {
RETURN_LONG(0);
}

phalcon_is_iterable(_FILES, &ah0, &hp0, 0, 0);

while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) {

if (phalcon_array_isset_string(*hd, SS("error"))) {
phalcon_array_fetch_string(&error, *hd, SL("error"), PH_NOISY);
assert(Z_REFCOUNT_P(error) > 1);
Z_DELREF_P(error);

if (Z_TYPE_P(error) < IS_ARRAY) {
if (!zend_is_true(error) || !only_successful) {
++nfiles;
}
}
if (!zend_is_true(error)) {
PHALCON_SEPARATE(number_files);
phalcon_increment(number_files);
else if (Z_TYPE_P(error) == IS_ARRAY) {
nfiles += phalcon_http_request_hasfiles_helper(error, only_successful);
}

zend_hash_move_forward_ex(ah0, &hp0);
}


zend_hash_move_forward_ex(ah0, &hp0);
}

RETURN_LONG(nfiles);
}

static void phalcon_http_request_getuploadedfiles_helper(zval **return_value, zval *name, zval *type, zval *tmp_name, zval *error, zval *size, int only_successful, smart_str *prefix TSRMLS_DC)
{
if (
Z_TYPE_P(name) == IS_ARRAY && Z_TYPE_P(type) == IS_ARRAY
&& Z_TYPE_P(tmp_name) == IS_ARRAY && Z_TYPE_P(error) == IS_ARRAY
&& Z_TYPE_P(size) == IS_ARRAY
) {
HashPosition pos_name, pos_type, pos_tmp, pos_error, pos_size;
zval **dname, **dtype, **dtmp, **derror, **dsize;
zval *arr, *file, *key;
size_t prefix_len = prefix->len;

zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(name), &pos_name);
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(type), &pos_type);
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(tmp_name), &pos_tmp);
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(error), &pos_error);
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(size), &pos_size);

while (
zend_hash_get_current_data_ex(Z_ARRVAL_P(name), (void**)&dname, &pos_name) == SUCCESS
&& zend_hash_get_current_data_ex(Z_ARRVAL_P(type), (void**)&dtype, &pos_type) == SUCCESS
&& zend_hash_get_current_data_ex(Z_ARRVAL_P(tmp_name), (void**)&dtmp, &pos_tmp) == SUCCESS
&& zend_hash_get_current_data_ex(Z_ARRVAL_P(error), (void**)&derror, &pos_error) == SUCCESS
&& zend_hash_get_current_data_ex(Z_ARRVAL_P(size), (void**)&dsize, &pos_size) == SUCCESS
&& !EG(exception)
) {
zval index = phalcon_get_current_key_w(Z_ARRVAL_P(name), &pos_name);

if (Z_TYPE(index) == IS_STRING) {
smart_str_appendl(prefix, Z_STRVAL(index), Z_STRLEN(index));
}
else {
smart_str_append_long(prefix, Z_LVAL(index));
}

if (Z_TYPE_PP(derror) < IS_ARRAY) {
if (!zend_is_true(*derror) || !only_successful) {
Z_ADDREF_PP(dname);
Z_ADDREF_PP(dtype);
Z_ADDREF_PP(dtmp);
Z_ADDREF_PP(derror);
Z_ADDREF_PP(dsize);

ALLOC_INIT_ZVAL(arr);
array_init_size(arr, 5);
add_assoc_zval_ex(arr, SS("name"), *dname);
add_assoc_zval_ex(arr, SS("type"), *dtype);
add_assoc_zval_ex(arr, SS("tmp_name"), *dtmp);
add_assoc_zval_ex(arr, SS("error"), *derror);
add_assoc_zval_ex(arr, SS("size"), *dsize);

ALLOC_INIT_ZVAL(key);
ZVAL_STRINGL(key, prefix->c, prefix->len, 1);
prefix->len = prefix_len;

ALLOC_INIT_ZVAL(file);
object_init_ex(file, phalcon_http_request_file_ce);

zval* params[2] = { arr, key };
int res = phalcon_call_method_params_w(NULL, file, SL("__construct"), 2, params, 0, 0 TSRMLS_CC);

zval_ptr_dtor(&arr);
zval_ptr_dtor(&key);

if (res != FAILURE) {
add_next_index_zval(*return_value, file);
}
else {
break;
}
}
}
else if (Z_TYPE_PP(derror) == IS_ARRAY) {
smart_str_appendc(prefix, '.');
phalcon_http_request_getuploadedfiles_helper(return_value, *dname, *dtype, *dtmp, *derror, *dsize, only_successful, prefix TSRMLS_CC);
prefix->len = prefix_len;
}

zend_hash_move_forward_ex(Z_ARRVAL_P(name), &pos_name);
zend_hash_move_forward_ex(Z_ARRVAL_P(type), &pos_type);
zend_hash_move_forward_ex(Z_ARRVAL_P(tmp_name), &pos_tmp);
zend_hash_move_forward_ex(Z_ARRVAL_P(error), &pos_error);
zend_hash_move_forward_ex(Z_ARRVAL_P(size), &pos_size);
}
}

is_smaller_function(return_value, zero, number_files TSRMLS_CC);

RETURN_MM();
}

/**
Expand All @@ -1205,65 +1304,83 @@ PHP_METHOD(Phalcon_Http_Request, hasFiles){
*/
PHP_METHOD(Phalcon_Http_Request, getUploadedFiles){

zval *not_errored = NULL, *super_files = NULL, *_FILES, *files;
zval *file = NULL, *error = NULL, *request_file = NULL;
zval *name = NULL, *type = NULL, *tmp_name = NULL, *error = NULL, *size = NULL;
zval *not_errored = NULL, *_FILES, *request_file = NULL, *key = NULL;
HashTable *ah0;
HashPosition hp0;
zval **hd;
int only_successful;
smart_str prefix = { NULL, 0, 0 };

PHALCON_MM_GROW();

phalcon_fetch_params(1, 0, 1, &not_errored);

if (!not_errored) {
PHALCON_INIT_VAR(not_errored);
ZVAL_BOOL(not_errored, 0);
}
phalcon_fetch_params(0, 0, 1, &not_errored);

only_successful = not_errored ? phalcon_get_intval(not_errored) : 1;

array_init(return_value);

phalcon_get_global(&_FILES, SS("_FILES") TSRMLS_CC);
PHALCON_CPY_WRT(super_files, _FILES);

if (phalcon_fast_count_ev(super_files TSRMLS_CC)) {

PHALCON_INIT_VAR(files);
array_init(files);

phalcon_is_iterable(super_files, &ah0, &hp0, 0, 0);

while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) {

PHALCON_GET_HVALUE(file);

if (zend_is_true(not_errored)) {
if (phalcon_array_isset_string(file, SS("error"))) {
PHALCON_OBS_NVAR(error);
phalcon_array_fetch_string(&error, file, SL("error"), PH_NOISY);
} else {
PHALCON_INIT_NVAR(error);
ZVAL_BOOL(error, 1);
}
if (!zend_is_true(error)) {
if (Z_TYPE_P(_FILES) != IS_ARRAY || !zend_hash_num_elements(Z_ARRVAL_P(_FILES))) {
return;
}

PHALCON_MM_GROW();
phalcon_is_iterable(_FILES, &ah0, &hp0, 0, 0);

while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS && !EG(exception)) {

if (phalcon_array_isset_string(*hd, SS("error"))) {
PHALCON_OBS_NVAR(error);
phalcon_array_fetch_string(&error, *hd, SL("error"), PH_NOISY);
zval index = phalcon_get_current_key_w(ah0, &hp0);

if (Z_TYPE_P(error) < IS_ARRAY) {
if (!zend_is_true(error) || !only_successful) {
PHALCON_INIT_NVAR(request_file);
object_init_ex(request_file, phalcon_http_request_file_ce);
phalcon_call_method_p1_noret(request_file, "__construct", file);

phalcon_array_append(&files, request_file, PH_SEPARATE);

PHALCON_INIT_NVAR(key);
ZVAL_STRINGL(key, Z_STRVAL(index), Z_STRLEN(index), 1);

Z_ADDREF_PP(hd);
phalcon_call_method_p2_noret(request_file, "__construct", *hd, key);

phalcon_array_append(&return_value, request_file, 0);
}
} else {
PHALCON_INIT_NVAR(request_file);
object_init_ex(request_file, phalcon_http_request_file_ce);
phalcon_call_method_p1_noret(request_file, "__construct", file);

phalcon_array_append(&files, request_file, PH_SEPARATE);
}

zend_hash_move_forward_ex(ah0, &hp0);
else if (Z_TYPE_P(error) == IS_ARRAY) {
PHALCON_OBS_NVAR(name);
PHALCON_OBS_NVAR(type);
PHALCON_OBS_NVAR(tmp_name);
PHALCON_OBS_NVAR(size);
phalcon_array_fetch_string(&name, *hd, SL("name"), PH_NOISY);
phalcon_array_fetch_string(&type, *hd, SL("type"), PH_NOISY);
phalcon_array_fetch_string(&tmp_name, *hd, SL("tmp_name"), PH_NOISY);
phalcon_array_fetch_string(&size, *hd, SL("size"), PH_NOISY);

if (prefix.len) {
prefix.len = 0;
}

if (likely(Z_TYPE(index) == IS_STRING)) {
smart_str_appendl(&prefix, Z_STRVAL(index), Z_STRLEN(index));
}
else {
smart_str_append_long(&prefix, Z_LVAL(index));
}

smart_str_appendc(&prefix, '.');
phalcon_http_request_getuploadedfiles_helper(&return_value, name, type, tmp_name, error, size, only_successful, &prefix TSRMLS_CC);
}
}
RETURN_CTOR(files);

zend_hash_move_forward_ex(ah0, &hp0);
}

RETURN_MM_EMPTY_ARRAY();
if (prefix.c) {
smart_str_free(&prefix);
}

RETURN_MM();
}

/**
Expand Down
Loading

0 comments on commit 3fba27a

Please sign in to comment.