[PHP-DEV] Bug #841: basename() & dirname() do not parse path correctly From: inlan <email protected>
Date: 10/09/98

From: inlan <email protected>
Operating system: Win95
PHP version: 3.0.5
PHP Bug Type: Misbehaving function
Bug description: basename() & dirname() do not parse path correctly

I was trying to use basename() & dirname() to break up a parse_url()["path"] into the directory & filename. It seems these functions simply break at the last '/'.

Here's what they return:
PATH dirname() basename()
adir/afile adir afile <<this one is ok
adir/ adir adir/
/adir/ (nothing) adir
afile afile afile
/ (nothing) /

This would be nice (and seems correct to me):
PATH dirname() basename()
adir/afile adir afile
adir/ adir (nothing)
/adir/ /adir (nothing)
afile (nothing) afile
/afile / afile
/ / (nothing)

I'm using phpweb distribution...
PHP Version 3.0.5-dev
System: Windows 95/98 4.0
Build Date: Oct 3 1998

The ChangeLog says, "Added basename and dirname functions similar to sh counterparts." I don't know if these are the desired results.

If I'm going to gripe...
Below is patched source code for what I think is supposed to happen. If the results I'm getting are the desired results, I'd love to still have the functions below (with any suitable name). The existing ones don't seem too
useful--which could be a lack of understanding on my part.

I'm not set up to compile PHP3, but I believe the coding is correct.

Rich Clingman
inlan <email protected>

### patches to basename() & dirname() in functions/string.c
### Rich Clingman inlan <email protected> 06OCT98
### manual "patch" notation: < take out > put in

void php3_basename(INTERNAL_FUNCTION_PARAMETERS)
{
pval *str;
char *ret, *c;
TLS_VARS;

if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str)) {
  WRONG_PARAM_COUNT;
}
convert_to_string(str);

### As the function is rewritten below,
### we do not modify the string
### (only return a value).
### Can we use 'str' directly?
### If so, dump this line
### and change 'ret' to 'str' in added lines.

ret = estrdup(str->value.str.val);

< c = ret + str->value.str.len -1;
< while (*c == '/'
< #ifdef MSVC5
< || *c == '\\'
< #endif
< )
< c--;
< *(c + 1) = '\0';
< if ((c = strrchr(ret, '/'))
<#ifdef MSVC5
< || (c = strrchr(ret, '\\'))
<#endif
< ) {
< RETVAL_STRING(c + 1,1);
< } else {
< RETVAL_STRING(str->value.str.val,1);
< }

> // if no slash, then no dir, only filename
> if ( (c=strrchr(ret, '/'))
>#ifdef MSVC5
> || (c=strrchr(ret, '\\'))
>#endif
> )
> RETVAL_STRING(c+1,1); // backed to slash, move ahead 1 and return
> else
> RETVAL_STRING(ret,1); // no slash, only filename

efree(ret);
}

###### it appears the only call to the following
###### is from php3_dirname() so I put the patch
###### there & suggest removing this.

<PHPAPI void _php3_dirname(char *str, int len) {
< register char *c;
<
< c = str + len - 1;
< while (*c == '/'
<#ifdef MSVC5
< || *c == '\\'
<#endif
< )
< c--; /* strip trailing slashes */
< *(c + 1) = '\0';
< if ((c = strrchr(str, '/'))
<#ifdef MSVC5
< || (c = strrchr(str, '\\'))
<#endif
< )
< *c='\0';
<}

void php3_dirname(INTERNAL_FUNCTION_PARAMETERS)
{
pval *str;
char *ret;
TLS_VARS;
> register char *c;

if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str)) {
  WRONG_PARAM_COUNT;
}
convert_to_string(str);
ret = estrdup(str->value.str.val);

< _php3_dirname(ret,str->value.str.len);

> c=ret + len - 1;
> if ( *c=='/' // do we end with a slash?
>#ifdef MSVC5
> || *c == '\\'
>#endif
> || (c = strrchr(ret, '/')) // or found a slash?
>#ifdef MSVC5
> || (c = strrchr(ret, '\\'))
>#endif
> )
> {
> if ( c == str ) // if only a slash remains (root dir)
> c+1='\0'; // leave it
> else
> c='\0'; // else zap this slash
> } else {
> *ret = '\0'; // if no slash, no dir, only filename
> }

RETVAL_STRING(ret,1);
efree(ret);
}

--
PHP Development Mailing List   http://www.php.net/
To unsubscribe send an empty message to php-dev-unsubscribe <email protected>
For help: php-dev-help <email protected>