From: Remi Collet Date: Sat, 25 Jul 2015 14:58:36 +0000 (+0200) Subject: Fix #70112 RFE Allow dirname to go up various times X-Git-Tag: php-7.0.0beta3~5^2~94 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e811770a68641c85d7e49f84f3230b4ed7a1e808;p=php Fix #70112 RFE Allow dirname to go up various times --- diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 488b71b900..3f03275aa5 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2213,8 +2213,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_basename, 0, 0, 1) ZEND_ARG_INFO(0, suffix) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_dirname, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_dirname, 0, 0, 1) ZEND_ARG_INFO(0, path) + ZEND_ARG_INFO(0, levels) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_pathinfo, 0, 0, 1) diff --git a/ext/standard/string.c b/ext/standard/string.c index 2a9ddb2a18..143c6f636c 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1648,21 +1648,36 @@ PHPAPI size_t php_dirname(char *path, size_t len) } /* }}} */ -/* {{{ proto string dirname(string path) +/* {{{ proto string dirname(string path[, int levels]) Returns the directory name component of the path */ PHP_FUNCTION(dirname) { char *str; zend_string *ret; size_t str_len; + zend_long levels = 1; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &levels) == FAILURE) { return; } ret = zend_string_init(str, str_len, 0); - ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len); + if (levels == 1) { + /* Defaut case */ + ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len); + + } else if (levels < 1) { + php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1"); + return; + + + } else { + /* Some levels up */ + do { + ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len=ZSTR_LEN(ret)); + } while (ZSTR_LEN(ret)0); + } RETURN_NEW_STR(ret); } /* }}} */ diff --git a/ext/standard/tests/strings/dirname_error.phpt b/ext/standard/tests/strings/dirname_error.phpt index bf6310283b..303a59b2d5 100644 --- a/ext/standard/tests/strings/dirname_error.phpt +++ b/ext/standard/tests/strings/dirname_error.phpt @@ -9,17 +9,23 @@ echo "*** Testing error conditions ***\n"; // zero arguments var_dump( dirname() ); +// Bad arg +var_dump( dirname("/var/tmp/bar.gz", 0) ); + // more than expected no. of arguments -var_dump( dirname("/var/tmp/bar.gz", ".gz") ); +var_dump( dirname("/var/tmp/bar.gz", 1, ".gz") ); echo "Done\n"; ?> --EXPECTF-- *** Testing error conditions *** -Warning: dirname() expects exactly 1 parameter, 0 given in %s on line %d +Warning: dirname() expects at least 1 parameter, 0 given in %s on line %d +NULL + +Warning: dirname(): Invalid argument, levels must be >= 1 in %s on line %d NULL -Warning: dirname() expects exactly 1 parameter, 2 given in %s on line %d +Warning: dirname() expects at most 2 parameters, 3 given in %s on line %d NULL Done diff --git a/ext/standard/tests/strings/dirname_multi.phpt b/ext/standard/tests/strings/dirname_multi.phpt new file mode 100644 index 0000000000..d0fdfac0a2 --- /dev/null +++ b/ext/standard/tests/strings/dirname_multi.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test dirname() function : usage variations +--FILE-- + +Done +--EXPECT-- +string(8) "/foo/bar" +string(4) "/foo" +string(1) "/" +string(1) "/" +string(1) "/" +Done