Bugzilla Bug 111428: more file pathname internationalization bug fixes.
authorwtchang%redhat.com
Fri, 17 Feb 2006 23:16:24 +0000
changeset 3589 859e54f66a6d991bdc376249481357afcc2aa14b
parent 3587 20a2565c3465f6bd6a7b3ada87524d6d23d13b43
child 3590 6feaad6ee12c060e4a42a183e600cc9cb168f5d8
push idunknown
push userunknown
push dateunknown
bugs111428
Bugzilla Bug 111428: more file pathname internationalization bug fixes. The patch is contributed by Masayuki Nakano <masayuki@d-toybox.com> and Jungshik Shin <jshin1987@gmail.com>. r=wtc,darin Tag: NSPRPUB_PRE_4_2_CLIENT_BRANCH
pr/src/md/windows/ntio.c
pr/src/md/windows/w95io.c
--- a/pr/src/md/windows/ntio.c
+++ b/pr/src/md/windows/ntio.c
@@ -15,16 +15,17 @@
  * The Original Code is the Netscape Portable Runtime (NSPR).
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998-2000
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Masayuki Nakano <masayuki@d-toybox.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -103,16 +104,18 @@ static DWORD dirAccessTable[] = {
  * This constant is used by _PR_FileTimeToPRTime().
  */
 #ifdef __GNUC__
 static const PRTime _pr_filetime_offset = 116444736000000000LL;
 #else
 static const PRTime _pr_filetime_offset = 116444736000000000i64;
 #endif
 
+static PRBool IsPrevCharSlash(const char *str, const char *current);
+
 #define _NEED_351_FILE_LOCKING_HACK
 #ifdef _NEED_351_FILE_LOCKING_HACK
 #define _PR_LOCAL_FILE 1
 #define _PR_REMOTE_FILE 2
 PRBool IsFileLocalInit();
 PRInt32 IsFileLocal(HANDLE hFile);
 #endif /* _NEED_351_FILE_LOCKING_HACK */
 
@@ -2764,17 +2767,17 @@ PRStatus
         return PR_FAILURE;
     }
     strcpy(filename, name);
 
     /*
      * If 'name' ends in a slash or backslash, do not append
      * another backslash.
      */
-    if (filename[len - 1] == '/' || filename[len - 1] == '\\') {
+    if (IsPrevCharSlash(filename, filename + len)) {
         len--;
     }
     strcpy(&filename[len], "\\*.*");
     FlipSlashes( filename, strlen(filename) );
 
     d->d_hdl = FindFirstFile( filename, &(d->d_entry) );
     if ( d->d_hdl == INVALID_HANDLE_VALUE ) {
 		_PR_MD_MAP_OPENDIR_ERROR(GetLastError());
@@ -2902,33 +2905,44 @@ PRInt32
          * can be handled by _stat() on NT but not on Win95.
          *
          * We remove the backslash or slash at the end and
          * try again.
          */
 
         int len = strlen(fn);
         if (len > 0 && len <= _MAX_PATH
-                && (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
+                && IsPrevCharSlash(fn, fn + len)) {
             char newfn[_MAX_PATH + 1];
 
             strcpy(newfn, fn);
             newfn[len - 1] = '\0';
             rv = _stat(newfn, (struct _stat *)info);
         }
     }
 
     if (-1 == rv) {
         _PR_MD_MAP_STAT_ERROR(errno);
     }
     return rv;
 }
 
 #define _PR_IS_SLASH(ch) ((ch) == '/' || (ch) == '\\')
 
+static PRBool
+IsPrevCharSlash(const char *str, const char *current)
+{
+    const char *prev;
+
+    if (str >= current)
+        return PR_FALSE;
+    prev = _mbsdec(str, current);
+    return (prev == current - 1) && _PR_IS_SLASH(*prev);
+}
+
 /*
  * IsRootDirectory --
  *
  * Return PR_TRUE if the pathname 'fn' is a valid root directory,
  * else return PR_FALSE.  The char buffer pointed to by 'fn' must
  * be writable.  During the execution of this function, the contents
  * of the buffer pointed to by 'fn' may be modified, but on return
  * the original contents will be restored.  'buflen' is the size of
@@ -2965,31 +2979,31 @@ IsRootDirectory(char *fn, size_t buflen)
         /* The 'server' part should have at least one character. */
         p = &fn[2];
         if (*p == '\0' || _PR_IS_SLASH(*p)) {
             return PR_FALSE;
         }
 
         /* look for the next slash */
         do {
-            p++;
+            p = _mbsinc(p);
         } while (*p != '\0' && !_PR_IS_SLASH(*p));
         if (*p == '\0') {
             return PR_FALSE;
         }
 
         /* The 'share' part should have at least one character. */
         p++;
         if (*p == '\0' || _PR_IS_SLASH(*p)) {
             return PR_FALSE;
         }
 
         /* look for the final slash */
         do {
-            p++;
+            p = _mbsinc(p);
         } while (*p != '\0' && !_PR_IS_SLASH(*p));
         if (_PR_IS_SLASH(*p) && p[1] != '\0') {
             return PR_FALSE;
         }
         if (*p == '\0') {
             /*
              * GetDriveType() doesn't work correctly if the
              * path is of the form \\server\share, so we add
@@ -3069,17 +3083,17 @@ PRInt32
             info->size = 0;
             /*
              * These timestamps don't make sense for root directories.
              */
             info->modifyTime = 0;
             info->creationTime = 0;
             return 0;
         }
-        if (!_PR_IS_SLASH(pathbuf[len - 1])) {
+        if (!IsPrevCharSlash(pathbuf, pathbuf + len)) {
             _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
             return -1;
         } else {
             pathbuf[len - 1] = '\0';
             hFindFile = FindFirstFile(pathbuf, &findFileData);
             if (INVALID_HANDLE_VALUE == hFindFile) {
                 _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
                 return -1;
--- a/pr/src/md/windows/w95io.c
+++ b/pr/src/md/windows/w95io.c
@@ -15,16 +15,17 @@
  * The Original Code is the Netscape Portable Runtime (NSPR).
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998-2000
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Masayuki Nakano <masayuki@d-toybox.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -75,16 +76,18 @@ static DWORD dirAccessTable[] = {
  * This constant is used by _PR_FileTimeToPRTime().
  */
 #if defined(__MINGW32__)
 static const PRTime _pr_filetime_offset = 116444736000000000LL;
 #else
 static const PRTime _pr_filetime_offset = 116444736000000000i64;
 #endif
 
+static PRBool IsPrevCharSlash(const char *str, const char *current);
+
 void
 _PR_MD_INIT_IO()
 {
     WORD WSAVersion = 0x0101;
     WSADATA WSAData;
     int err;
 
     err = WSAStartup( WSAVersion, &WSAData );
@@ -503,17 +506,17 @@ PRStatus
         return PR_FAILURE;
     }
     strcpy(filename, name);
 
     /*
      * If 'name' ends in a slash or backslash, do not append
      * another backslash.
      */
-    if (filename[len - 1] == '/' || filename[len - 1] == '\\') {
+    if (IsPrevCharSlash(filename, filename + len)) {
         len--;
     }
     strcpy(&filename[len], "\\*.*");
     FlipSlashes( filename, strlen(filename) );
 
     d->d_hdl = FindFirstFile( filename, &(d->d_entry) );
     if ( d->d_hdl == INVALID_HANDLE_VALUE ) {
 		_PR_MD_MAP_OPENDIR_ERROR(GetLastError());
@@ -641,33 +644,44 @@ PRInt32
          * can be handled by _stat() on NT but not on Win95.
          *
          * We remove the backslash or slash at the end and
          * try again.
          */
 
         size_t len = strlen(fn);
         if (len > 0 && len <= _MAX_PATH
-                && (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
+                && IsPrevCharSlash(fn, fn + len)) {
             char newfn[_MAX_PATH + 1];
 
             strcpy(newfn, fn);
             newfn[len - 1] = '\0';
             rv = _stat(newfn, (struct _stat *)info);
         }
     }
 
     if (-1 == rv) {
         _PR_MD_MAP_STAT_ERROR(errno);
     }
     return rv;
 }
 
 #define _PR_IS_SLASH(ch) ((ch) == '/' || (ch) == '\\')
 
+static PRBool
+IsPrevCharSlash(const char *str, const char *current)
+{
+    const char *prev;
+
+    if (str >= current)
+        return PR_FALSE;
+    prev = _mbsdec(str, current);
+    return (prev == current - 1) && _PR_IS_SLASH(*prev);
+}
+
 /*
  * IsRootDirectory --
  *
  * Return PR_TRUE if the pathname 'fn' is a valid root directory,
  * else return PR_FALSE.  The char buffer pointed to by 'fn' must
  * be writable.  During the execution of this function, the contents
  * of the buffer pointed to by 'fn' may be modified, but on return
  * the original contents will be restored.  'buflen' is the size of
@@ -704,31 +718,31 @@ IsRootDirectory(char *fn, size_t buflen)
         /* The 'server' part should have at least one character. */
         p = &fn[2];
         if (*p == '\0' || _PR_IS_SLASH(*p)) {
             return PR_FALSE;
         }
 
         /* look for the next slash */
         do {
-            p++;
+            p = _mbsinc(p);
         } while (*p != '\0' && !_PR_IS_SLASH(*p));
         if (*p == '\0') {
             return PR_FALSE;
         }
 
         /* The 'share' part should have at least one character. */
         p++;
         if (*p == '\0' || _PR_IS_SLASH(*p)) {
             return PR_FALSE;
         }
 
         /* look for the final slash */
         do {
-            p++;
+            p = _mbsinc(p);
         } while (*p != '\0' && !_PR_IS_SLASH(*p));
         if (_PR_IS_SLASH(*p) && p[1] != '\0') {
             return PR_FALSE;
         }
         if (*p == '\0') {
             /*
              * GetDriveType() doesn't work correctly if the
              * path is of the form \\server\share, so we add
@@ -808,17 +822,17 @@ PRInt32
             info->size = 0;
             /*
              * These timestamps don't make sense for root directories.
              */
             info->modifyTime = 0;
             info->creationTime = 0;
             return 0;
         }
-        if (!_PR_IS_SLASH(pathbuf[len - 1])) {
+        if (!IsPrevCharSlash(pathbuf, pathbuf + len)) {
             _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
             return -1;
         } else {
             pathbuf[len - 1] = '\0';
             hFindFile = FindFirstFile(pathbuf, &findFileData);
             if (INVALID_HANDLE_VALUE == hFindFile) {
                 _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
                 return -1;