]> granicus.if.org Git - php/commitdiff
basename() now binary safe, testcases added
authorHartmut Holzgraefe <hholzgra@php.net>
Mon, 5 May 2003 13:46:14 +0000 (13:46 +0000)
committerHartmut Holzgraefe <hholzgra@php.net>
Mon, 5 May 2003 13:46:14 +0000 (13:46 +0000)
TODO
ext/exif/exif.c
ext/standard/ftp_fopen_wrapper.c
ext/standard/php_string.h
ext/standard/string.c
ext/standard/tests/strings/basename.phpt [new file with mode: 0644]

diff --git a/TODO b/TODO
index 09f1dfdea40fdf0a733707d415efd6a4ccc1d828..abbddda980b35267ad7acb67eb529340662eec66 100644 (file)
--- a/TODO
+++ b/TODO
@@ -136,8 +136,6 @@ ext/standard
       variable name is seen more than once.
     * Implement regex-cache for url-functions.
     * Move socket related functions to fsock.c.
-    * NOT binary safe:
-        basename()
 
 ext/wddx
 --------
index 8adc41100f6defff9542bea933dcc35fdd7ac035..13957bb3041681890fdd3ec8e8f29be2f2493223 100644 (file)
@@ -3687,7 +3687,7 @@ static int exif_read_file(image_info_type *ImageInfo, char *FileName, int read_t
                return FALSE;
        }
 
-       ImageInfo->FileName = php_basename(FileName, strlen(FileName), NULL, 0);
+       php_basename(FileName, strlen(FileName), NULL, 0, &(ImageInfo->FileName), NULL);
        ImageInfo->read_thumbnail = read_thumbnail;
        ImageInfo->read_all = read_all;
        ImageInfo->Thumbnail.filetype = IMAGE_FILETYPE_UNKNOWN;
index 59f01ef5859fa48373c21fb7c3932df40ba6eba5..216b52c1bba58b66783ee9e37ba0de4e5947e65d 100644 (file)
@@ -552,6 +552,7 @@ static size_t php_ftp_dirstream_read(php_stream *stream, char *buf, size_t count
        php_stream *innerstream = (php_stream *)stream->abstract;
        size_t tmp_len;
        char *basename;
+       int basename_len;
 
        if (count != sizeof(php_stream_dirent)) {
                return 0;
@@ -564,15 +565,19 @@ static size_t php_ftp_dirstream_read(php_stream *stream, char *buf, size_t count
        if (!php_stream_get_line(innerstream, ent->d_name, sizeof(ent->d_name), &tmp_len)) {
                return 0;
        }
-       if (!(basename = php_basename(ent->d_name, tmp_len, NULL, 0))) {
+
+       php_basename(ent->d_name, tmp_len, NULL, 0, &basename, &basename_len);
+       if (!basename) {
                return 0;
        }
 
-       if (strlen(basename) == 0) {
+       if (!basename_len) {
                efree(basename);
                return 0;
        }
-       strcpy(ent->d_name, basename);
+
+       memcpy(ent->d_name, basename, MIN(sizeof(ent->d_name), basename_len)-1);
+       ent->d_name[sizeof(ent->d_name)-1] = '\0';
        efree(basename);
 
        return sizeof(php_stream_dirent);
index 3e24b74070075b8b3119f7a13ca05082fc953ff2..fa682e7012890337acad98cd4c665215466847af 100644 (file)
@@ -121,7 +121,7 @@ PHPAPI char *php_addslashes(char *str, int length, int *new_length, int freeit T
 PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int freeit, char *what, int wlength TSRMLS_DC);
 PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC);
 PHPAPI void php_stripcslashes(char *str, int *len);
-PHPAPI char *php_basename(char *str, size_t  len , char *suffix, size_t sufflen);
+PHPAPI void php_basename(char *str, size_t  len , char *suffix, size_t sufflen, char **p_ret, int *p_len);
 PHPAPI size_t php_dirname(char *str, size_t len);
 PHPAPI char *php_stristr(unsigned char *s, unsigned char *t, size_t s_len, size_t t_len);
 PHPAPI char *php_str_to_str_ex(char *haystack, int length, char *needle,
index 5792fbf08b605cec8d982f62121993d82f1069b0..861c6bfffe25310beef8c5ec8335274dfa471bc4 100644 (file)
@@ -1074,21 +1074,11 @@ PHP_FUNCTION(strtolower)
 
 /* {{{ php_basename
  */
-PHPAPI char *php_basename(char *s, size_t len, char *suffix, size_t sufflen)
+PHPAPI void php_basename(char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, int *p_len)
 {
-       char *ret=NULL, *c, *p=NULL, buf='\0', *p2=NULL, buf2='\0';
+       char *ret=NULL, *c;
        c = s + len - 1;        
 
-       /* do suffix removal as the unix command does */
-       if (suffix && (len > sufflen)) {
-               if (!strncmp(suffix, c-sufflen+1, sufflen)) {
-                       c -= sufflen; 
-                       buf2 = *(c + 1); /* Save overwritten char */
-                       *(c + 1) = '\0'; /* overwrite char */
-                       p2 = c + 1;      /* Save pointer to overwritten char */
-               }
-       }
-
        /* strip trailing slashes */
        while (*c == '/'
 #ifdef PHP_WIN32
@@ -1096,30 +1086,44 @@ PHPAPI char *php_basename(char *s, size_t len, char *suffix, size_t sufflen)
 #endif
        ) {
                c--;
+               len--;
        }
 
-       if (c < s+len-1) {
-               buf = *(c + 1);  /* Save overwritten char */
-               *(c + 1) = '\0'; /* overwrite char */
-               p = c + 1;       /* Save pointer to overwritten char */
-       }
-
-       if ((c = strrchr(s, '/'))
+       /* do suffix removal as the unix command does */
+       if (suffix && (len > sufflen)) {
+               if (!memcmp(suffix, c-sufflen+1, sufflen)) {
+                       if( (*(c-sufflen) != '/')
 #ifdef PHP_WIN32
-               || ((c = strrchr(s, '\\')) && !IsDBCSLeadByte(*(c-1)))
-#endif
-       ) {
-               ret = estrdup(c + 1);
-       } else {
-               ret = estrdup(s);
-       }
-       if (buf) {
-               *p = buf;
+                  && ( *(c-sufflen) != '\\' || IsDBCSLeadByte(*(c-sufflen-1)))
+#endif                 
+                               ) {
+                               c -= sufflen;
+                               len -= sufflen;
+                       }
+               }
        }
-       if (buf2) {
-               *p2 = buf2;
+               
+       while(c>=s) {
+               if(*c == '/'
+#ifdef PHP_WIN32
+                  || ( *c == '\\' && !IsDBCSLeadByte(*c-1))
+#endif                 
+                  ) {
+                       c++;
+                       break;
+               }
+               c--;
        }
-       return (ret);
+
+       if (c<s) c=s;
+
+       len -= (c-s);
+       ret = emalloc(len+1);
+       memcpy(ret, c, len);
+       ret[len] = '\0';
+
+       if(p_ret) *p_ret = ret;
+       if(p_len) *p_len = len;
 }
 /* }}} */
 
@@ -1127,16 +1131,15 @@ PHPAPI char *php_basename(char *s, size_t len, char *suffix, size_t sufflen)
    Returns the filename component of the path */
 PHP_FUNCTION(basename)
 {
-       char *ret;
-       char *string, *suffix = NULL;
-       int   string_len, suffix_len = 0;
+       char *string, *suffix = NULL, *ret;
+       int   string_len, suffix_len = 0, ret_len;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &string, &string_len, &suffix, &suffix_len) == FAILURE) {
                return;
        }
 
-       ret = php_basename(string, string_len, suffix, suffix_len);     
-       RETURN_STRING(ret, 0);
+       php_basename(string, string_len, suffix, suffix_len, &ret, &ret_len);   
+       RETURN_STRINGL(ret, ret_len, 0);
 }
 /* }}} */
 
@@ -1233,7 +1236,7 @@ PHP_FUNCTION(pathinfo)
 {
        zval *tmp;
        char *path, *ret = NULL;
-       int path_len;
+       int path_len, ret_len;
        long opt = PHP_PATHINFO_ALL;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &path, &path_len, &opt) == FAILURE) {
@@ -1253,8 +1256,8 @@ PHP_FUNCTION(pathinfo)
        }
        
        if ((opt & PHP_PATHINFO_BASENAME) == PHP_PATHINFO_BASENAME) {
-               ret = php_basename(path, path_len, NULL, 0);
-               add_assoc_string(tmp, "basename", ret, 0);
+               php_basename(path, path_len, NULL, 0, &ret, &ret_len);
+               add_assoc_stringl(tmp, "basename", ret, ret_len, 0);
        }                       
        
        if ((opt & PHP_PATHINFO_EXTENSION) == PHP_PATHINFO_EXTENSION) {
@@ -1265,11 +1268,9 @@ PHP_FUNCTION(pathinfo)
 
                /* Have we alrady looked up the basename? */
                if (!have_basename) {
-                       ret = php_basename(path, path_len, NULL, 0);
+                       php_basename(path, path_len, NULL, 0, &ret, &ret_len);
                }
 
-               ret_len = strlen(ret);
-
                p = strrchr(ret, '.');
 
                if (p) {
diff --git a/ext/standard/tests/strings/basename.phpt b/ext/standard/tests/strings/basename.phpt
new file mode 100644 (file)
index 0000000..b1ccdfd
Binary files /dev/null and b/ext/standard/tests/strings/basename.phpt differ