Add sanitize

This commit is contained in:
istarkov authored and Ivan Starkov committed 2022-11-21 20:31:55 +04:00
1 parent d0dbf9938a
commit 279e2ec093
5 files changed
+62 -6

No files matched your search

@@ -0,0 +1,26 @@
/**
* TEMPORARY: This function is a temporary fix for https://github.com/remix-run/remix/issues/4443
*
* Based on this: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html
* Characters that might require special handling
* ASCII character ranges 00–1F hex (0–31 decimal) and 7F (127 decimal)
* "&","$", "@", "=", ";" "/", ":", "+", Significant sequences of spaces might be lost in some uses (especially multiple spaces)
* ",", "?"
* Characters to avoid
* Non-printable ASCII characters (128–255 decimal characters)
* "\", "{", "^", "}", "%", "`", "]", ', ", “, ”, ">", "[", "~", "<", "#", "|"
**/
// eslint-disable-next-line no-control-regex
const specialRegexps = [/[\x00-\x1F\x7F]+/g, /[&$@=;/:+\s,?]+/g];
// eslint-disable-next-line no-control-regex
const avoidRegexps = [/[\x80-\xFF]+/g, /[\\{^}%`\]'"“”>[~<#|]+/g];
const allRegexps = [...specialRegexps, ...avoidRegexps];
const REPLACE_CHAR = "_";
export const sanitizeS3Key = (str: string): string => {
return allRegexps.reduce((r, reg) => r.replace(reg, REPLACE_CHAR), str);
};
@@ -10,6 +10,7 @@ import ObjectID from "bson-objectid";
import { useMemo } from "react";
import { restAssetsPath } from "~/shared/router-utils";
import { useAssets as useAssetsState, useProject } from "../nano-states";
import { sanitizeS3Key } from "./sanitize-s3-key";
import { PreviewAsset } from "./types";
const toPreviewAssets = (formData: FormData): Promise<PreviewAsset[]> => {
@@ -54,7 +55,9 @@ const toFormData = (type: AssetType, input: HTMLInputElement) => {
);
continue;
}
formData.append(type, file, file.name);
// sanitizeS3Key here is just because of https://github.com/remix-run/remix/issues/4443
formData.append(type, file, sanitizeS3Key(file.name));
}
return formData;
};
@@ -14,6 +14,7 @@ import { createMany } from "../../db";
import type { Asset } from "../../types";
import { getUniqueFilename } from "../../utils/get-unique-filename";
import { getS3Client } from "./client";
import { sanitizeS3Key } from "../../utils/sanitize-s3-key";
const AssetsUploadedSuccess = z.object({
Location: z.string(),
@@ -72,7 +73,9 @@ const uploadHandler = async ({
throw new Error("Filename is required");
}
const uniqueFilename = getUniqueFilename(file.filename);
const fileName = sanitizeS3Key(file.filename);
const uniqueFilename = getUniqueFilename(fileName);
const s3Env = S3Env.parse(process.env);
@@ -82,12 +85,12 @@ const uploadHandler = async ({
const params: PutObjectCommandInput = {
...ACL,
Bucket: s3Env.S3_BUCKET,
Key: encodeURIComponent(uniqueFilename),
Key: uniqueFilename,
Body: data,
ContentType: file.contentType,
Metadata: {
// encodeURIComponent is needed to support special characters like Cyrillic
filename: "meta", // encodeURIComponent(file.filename) || "unnamed",
filename: encodeURIComponent(fileName) || "unnamed",
},
};
@@ -28,13 +28,13 @@ export const getAssetPath = (asset: DbAsset) => {
// see /packages/asset-uploader/src/targets/s3/upload.ts "Key: encodeURIComponent(uniqueFilename)"
// here we need to encode file name, i.e cndUrl.pathname = encodeURIComponent(fileName)
// but having that fileName = encodeURIComponent(asset.name) we are doing double encoding
cndUrl.pathname = encodeURIComponent(encodeURIComponent(asset.name));
cndUrl.pathname = asset.name;
return cndUrl.toString();
}
const s3Url = new URL(s3Envs.data.S3_ENDPOINT);
s3Url.hostname = `${s3Envs.data.S3_BUCKET}.${s3Url.hostname}`;
// See above comment about double encoding
s3Url.pathname = encodeURIComponent(encodeURIComponent(asset.name));
s3Url.pathname = asset.name;
return s3Url.toString();
}
@@ -0,0 +1,24 @@
/**
* Based on this: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html
* Characters that might require special handling
* ASCII character ranges 00–1F hex (0–31 decimal) and 7F (127 decimal)
* "&","$", "@", "=", ";" "/", ":", "+", Significant sequences of spaces might be lost in some uses (especially multiple spaces)
* ",", "?"
* Characters to avoid
* Non-printable ASCII characters (128–255 decimal characters)
* "\", "{", "^", "}", "%", "`", "]", ', ", “, ”, ">", "[", "~", "<", "#", "|"
**/
// eslint-disable-next-line no-control-regex
const specialRegexps = [/[\x00-\x1F\x7F]+/g, /[&$@=;/:+\s,?]+/g];
// eslint-disable-next-line no-control-regex
const avoidRegexps = [/[\x80-\xFF]+/g, /[\\{^}%`\]'"“”>[~<#|]+/g];
const allRegexps = [...specialRegexps, ...avoidRegexps];
const REPLACE_CHAR = "_";
export const sanitizeS3Key = (str: string): string => {
return allRegexps.reduce((r, reg) => r.replace(reg, REPLACE_CHAR), str);
};