From bc9388342f59ed5c69d69c7095e5a17fcbd80ba8 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Wed, 21 Nov 2012 01:00:45 +0100 Subject: windows: fix normalization of UNC paths --- lib/path.js | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'lib/path.js') diff --git a/lib/path.js b/lib/path.js index 7e521f20de..139d04aae8 100644 --- a/lib/path.js +++ b/lib/path.js @@ -59,7 +59,7 @@ if (isWindows) { // Regex to split a windows path into three parts: [*, device, slash, // tail] windows-only var splitDeviceRe = - /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?([\s\S]*?)$/; + /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; // Regex to split the tail part of the above into [*, dir, basename, ext] var splitTailRe = @@ -80,6 +80,10 @@ if (isWindows) { return [device, dir, basename, ext]; }; + var normalizeUNCRoot = function(device) { + return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\'); + } + // path.resolve([from ...], to) // windows version exports.resolve = function() { @@ -138,8 +142,11 @@ if (isWindows) { } } - // Replace slashes (in UNC share name) by backslashes - resolvedDevice = resolvedDevice.replace(/\//g, '\\'); + // Convert slashes to backslashes when `resolvedDevice` points to an UNC + // root. Also squash multiple slashes into a single one where appropriate. + if (isUnc) { + resolvedDevice = normalizeUNCRoot(resolvedDevice); + } // At this point the path should be resolved to a full absolute path, // but handle relative paths to be safe (might happen when process.cwd() @@ -180,7 +187,10 @@ if (isWindows) { } // Convert slashes to backslashes when `device` points to an UNC root. - device = device.replace(/\//g, '\\'); + // Also squash multiple slashes into a single one where appropriate. + if (isUnc) { + device = normalizeUNCRoot(device); + } return device + (isAbsolute ? '\\' : '') + tail; }; @@ -194,11 +204,21 @@ if (isWindows) { var paths = Array.prototype.filter.call(arguments, f); var joined = paths.join('\\'); - // Make sure that the joined path doesn't start with two slashes - // - it will be mistaken for an unc path by normalize() - - // unless the paths[0] also starts with two slashes - if (/^[\\\/]{2}/.test(joined) && !/^[\\\/]{2}/.test(paths[0])) { - joined = joined.substr(1); + // Make sure that the joined path doesn't start with two slashes, because + // normalize() will mistake it for an UNC path then. + // + // This step is skipped when it is very clear that the user actually + // intended to point at an UNC path. This is assumed when the first + // non-empty string arguments starts with exactly two slashes followed by + // at least one more non-slash character. + // + // Note that for normalize() to treat a path as an UNC path it needs to + // have at least 2 components, so we don't filter for that here. + // This means that the user can use join to construct UNC paths from + // a server name and a share name; for example: + // path.join('//server', 'share') -> '\\\\server\\share\') + if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) { + joined = joined.replace(/^[\\\/]{2,}/, '\\'); } return exports.normalize(joined); -- cgit v1.2.3