Skip to content

Commit

Permalink
Merge pull request #420 from jamhall/win32-path-escape
Browse files Browse the repository at this point in the history
Escape invalid path characters in win32 envs
  • Loading branch information
kherock committed Mar 22, 2019
2 parents afdadae + a3ec092 commit b98e788
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
24 changes: 22 additions & 2 deletions lib/stores/filesystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ const { concatStreams, walk } = require("../utils");
const S3RVER_SUFFIX = "%s._S3rver_%s";

class FilesystemStore {
static decodeKeyPath(keyPath) {
return process.platform === "win32"
? keyPath.replace(/&../g, ent =>
Buffer.from(ent.slice(1), "hex").toString()
)
: keyPath;
}

static encodeKeyPath(key) {
return process.platform === "win32"
? key.replace(
/[<>:"\\|?*]/g,
ch => "&" + Buffer.from(ch, "utf8").toString("hex")
)
: key;
}

constructor(rootDirectory) {
this.rootDirectory = rootDirectory;
}
Expand All @@ -25,7 +42,7 @@ class FilesystemStore {
}

getResourcePath(bucket, key = "", resource) {
const parts = key.split("/");
const parts = FilesystemStore.encodeKeyPath(key).split("/");
const suffix = format(S3RVER_SUFFIX, parts.pop(), resource);
return path.join(this.rootDirectory, bucket, ...parts, suffix);
}
Expand Down Expand Up @@ -128,7 +145,10 @@ class FilesystemStore {
const objectSuffix = format(S3RVER_SUFFIX, "", "object");
let keys = [...walk(bucketPath)]
.filter(file => file.endsWith(objectSuffix))
.map(key => key.slice(bucketPath.length + 1, -objectSuffix.length));
.map(keyPath =>
keyPath.slice(bucketPath.length + 1, -objectSuffix.length)
)
.map(FilesystemStore.decodeKeyPath);

if (!keys.length) {
return {
Expand Down
17 changes: 17 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,23 @@ describe("S3rver Tests", function() {
expect(data.ETag).to.match(/"[a-fA-F0-9]{32}"/);
});

it("should store a text object with invalid win32 path characters and retrieve it", async function() {
const reservedChars = '\\/:*?"<>|';
await s3Client
.putObject({
Bucket: buckets[0].name,
Key: `mykey-&-${reservedChars}`,
Body: "Hello!"
})
.promise();

const object = await s3Client
.getObject({ Bucket: buckets[0].name, Key: `mykey-&-${reservedChars}` })
.promise();

expect(object.Body.toString()).to.equal("Hello!");
});

it("should store a text object with no content type and retrieve it", async function() {
const res = await request({
method: "PUT",
Expand Down

0 comments on commit b98e788

Please sign in to comment.