mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 07:04:52 +09:00
Ensure instance name is a valid Windows file name
Add check for instance name that ensures it being a valid Windows file. See the microsoft article about naming files for more details: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
This commit is contained in:
1 parent
1ba9e68603
commit
53a5ce062b
3 files changed
+98
No files matched your search
@@ -19,6 +19,7 @@ Version 2.0.0
|
||||
- The masterIP and masterPort config entries has been merged into masterURL.
|
||||
Breaks discordChat, playerManager, serverSelect, trainTeleports and
|
||||
clusterioModel.
|
||||
- Instance names can no longer be invalid Windows file names.
|
||||
|
||||
|
||||
Version 1.2.1
|
||||
|
||||
@@ -63,11 +63,55 @@ class Instance {
|
||||
}
|
||||
}
|
||||
|
||||
function checkFilename(name) {
|
||||
// All of these are bad in Windows only, except for /, . and ..
|
||||
// See: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
|
||||
const badChars = /[<>:"\/\\|?*\x00-\x1f]/g;
|
||||
const badEnd = /[. ]$/;
|
||||
|
||||
const oneToNine = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
const badNames = [
|
||||
// Relative path components
|
||||
'.', '..',
|
||||
|
||||
// Reserved filenames in Windows
|
||||
'CON', 'PRN', 'AUX', 'NUL',
|
||||
...oneToNine.map(n => `COM${n}`),
|
||||
...oneToNine.map(n => `LPT${n}`),
|
||||
];
|
||||
|
||||
if (typeof name !== "string") {
|
||||
throw new Error("must be a string");
|
||||
}
|
||||
|
||||
if (name === "") {
|
||||
throw new Error("cannot be empty");
|
||||
}
|
||||
|
||||
if (badChars.test(name)) {
|
||||
throw new Error('cannot contain <>:"\\/|=* or control characters');
|
||||
}
|
||||
|
||||
if (badNames.includes(name.toUpperCase())) {
|
||||
throw new Error(
|
||||
"cannot be named any of . .. CON PRN AUX NUL COM1-9 and LPT1-9"
|
||||
);
|
||||
}
|
||||
|
||||
if (badEnd.test(name)) {
|
||||
throw new Error("cannot end with . or space");
|
||||
}
|
||||
}
|
||||
|
||||
let instance;
|
||||
|
||||
if (process.argv[3] !== undefined) {
|
||||
let name = process.argv[3];
|
||||
try {
|
||||
checkFilename(name);
|
||||
} catch (err) {
|
||||
throw new Error(`Instance name ${err.message}`);
|
||||
}
|
||||
let dir = path.join(config.instanceDirectory, name);
|
||||
instance = new Instance(dir, name);
|
||||
}
|
||||
@@ -892,6 +936,7 @@ function hashMods(instance, callback) {
|
||||
module.exports = {
|
||||
// For testing only
|
||||
_Instance: Instance,
|
||||
_checkFilename: checkFilename,
|
||||
_randomDynamicPort: randomDynamicPort,
|
||||
_generatePassword: generatePassword,
|
||||
};
|
||||
|
||||
@@ -19,6 +19,58 @@ describe("Client testing", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe("checkFilename()", function() {
|
||||
it("should allow a basic name", function() {
|
||||
client._checkFilename("file");
|
||||
});
|
||||
|
||||
function check(item, msg) {
|
||||
assert.throws(() => client._checkFilename(item), new Error(msg));
|
||||
}
|
||||
|
||||
it("should throw on non-string", function() {
|
||||
check(undefined, "must be a string");
|
||||
check(null, "must be a string");
|
||||
check({}, "must be a string");
|
||||
check([], "must be a string");
|
||||
check(0, "must be a string");
|
||||
check(false, "must be a string");
|
||||
});
|
||||
|
||||
it("should throw on empty name", function() {
|
||||
check("", "cannot be empty");
|
||||
});
|
||||
|
||||
it("should throw on <>:\"\\/|?* \\x00\\r\\n\\t", function() {
|
||||
for (let char of '<>:"\\/|?*\x00\r\n\t') {
|
||||
check(char, 'cannot contain <>:"\\/|=* or control characters');
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw on CON, PRN, AUX, NUL, COM1, LPT1", function() {
|
||||
for (let bad of ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'LPT1']) {
|
||||
check(
|
||||
bad, 'cannot be named any of . ..'
|
||||
+' CON PRN AUX NUL COM1-9 and LPT1-9'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw on . and ..", function() {
|
||||
for (let bad of ['.', '..']) {
|
||||
check(
|
||||
bad, 'cannot be named any of . ..'
|
||||
+' CON PRN AUX NUL COM1-9 and LPT1-9'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw on names ending with . or space", function() {
|
||||
check("a ", "cannot end with . or space");
|
||||
check("a.", "cannot end with . or space");
|
||||
});
|
||||
});
|
||||
|
||||
describe("randomDynamicPort()", function() {
|
||||
it("should return a port number", function() {
|
||||
let port = client._randomDynamicPort()
|
||||
|
||||
Reference in new issue
Block a user