fix: more fixes related to object name encoding (#1128)

- removing limitation of characters for paths/folders
- fixed object names with international characters inside paths

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
This commit is contained in:
Lenin Alevski
2021-10-19 17:42:59 -07:00
committed by GitHub
parent 37d7f0025b
commit 95f622a597
6 changed files with 33 additions and 35 deletions

View File

@@ -584,9 +584,17 @@ export const representationNumber = (number: number | undefined) => {
};
export const encodeFileName = (name: string) => {
return btoa(unescape(encodeURIComponent(name)));
try {
return btoa(unescape(encodeURIComponent(name)));
} catch (err) {
return "";
}
};
export const decodeFileName = (text: string) => {
return decodeURIComponent(escape(window.atob(text)));
try {
return decodeURIComponent(escape(window.atob(text)));
} catch (err) {
return text;
}
};

View File

@@ -55,7 +55,6 @@ const CreateFolderModal = ({
classes,
}: ICreateFolder) => {
const [pathUrl, setPathUrl] = useState("");
const [nameInputError, setNameInputError] = useState<string>("");
const [isFormValid, setIsFormValid] = useState<boolean>(false);
const currentPath = `${bucketName}/${decodeFileName(folderName)}`;
@@ -80,21 +79,9 @@ const CreateFolderModal = ({
onClose();
};
const validPathURL = useCallback(() => {
const patternAgainst = /^[a-zA-Z0-9*'#-\[\]_/&.@\s()]+$/; // Only allow uppercase, numbers, dashes and underscores
if (patternAgainst.test(pathUrl)) {
setNameInputError("");
return true;
}
setNameInputError(
"Please verify the folder path contains valid characters only (letters, numbers and some special characters)."
);
return false;
}, [pathUrl]);
useEffect(() => {
let valid = true;
if (pathUrl.trim().length === 0 || !validPathURL()) {
if (pathUrl.trim().length === 0) {
valid = false;
}
setIsFormValid(valid);
@@ -120,7 +107,6 @@ const CreateFolderModal = ({
setPathUrl(e.target.value);
}}
required
error={nameInputError}
/>
</Grid>
<Grid item xs={12} className={classes.buttonContainer}>

View File

@@ -28,6 +28,7 @@ import {
import { setErrorSnackMessage } from "../../../../../../actions";
import { ErrorResponseHandler } from "../../../../../../common/types";
import api from "../../../../../../common/api";
import { decodeFileName } from "../../../../../../common/utils";
interface IDeleteObjectProps {
closeDeleteModalAndRefresh: (refresh: boolean) => void;
@@ -50,13 +51,8 @@ const DeleteObject = ({
if (deleteLoading) {
return;
}
let recursive = false;
if (selectedObject.endsWith("/")) {
recursive = true;
}
// Escape object name
selectedObject = encodeURIComponent(selectedObject);
const decodedSelectedObject = decodeFileName(selectedObject);
const recursive = decodedSelectedObject.endsWith("/");
api
.invoke(
"DELETE",
@@ -85,7 +81,8 @@ const DeleteObject = ({
<DialogContent>
{deleteLoading && <LinearProgress />}
<DialogContentText id="alert-dialog-description">
Are you sure you want to delete: <b>{selectedObject}</b>?{" "}
Are you sure you want to delete:{" "}
<b>{decodeFileName(selectedObject)}</b>?{" "}
</DialogContentText>
</DialogContent>
<DialogActions>

View File

@@ -897,12 +897,8 @@ const ListObjects = ({
},
];
const ccPath = internalPaths.split("/").pop();
const pageTitle = ccPath !== "" ? decodeFileName(ccPath) : "/";
// console.log("pageTitle", pageTitle);
const pageTitle = decodeFileName(internalPaths);
const currentPath = pageTitle.split("/").filter((i: string) => i !== "");
// console.log("currentPath", currentPath);
return (
<React.Fragment>
@@ -922,7 +918,7 @@ const ListObjects = ({
<DeleteObject
deleteOpen={deleteOpen}
selectedBucket={bucketName}
selectedObject={selectedObject}
selectedObject={encodeFileName(selectedObject)}
closeDeleteModalAndRefresh={closeDeleteModalAndRefresh}
/>
)}

View File

@@ -77,7 +77,7 @@ import EditIcon from "../../../../../../icons/EditIcon";
import SearchIcon from "../../../../../../icons/SearchIcon";
import ObjectBrowserIcon from "../../../../../../icons/ObjectBrowserIcon";
import PreviewFileContent from "../Preview/PreviewFileContent";
import { decodeFileName } from "../../../../../../common/utils";
import { decodeFileName, encodeFileName } from "../../../../../../common/utils";
const styles = (theme: Theme) =>
createStyles({
@@ -420,7 +420,9 @@ const ObjectDetails = ({
if (redirectBack) {
const newPath = allPathData.join("/");
history.push(
`/buckets/${bucketName}/browse${newPath === "" ? "" : `/${newPath}`}`
`/buckets/${bucketName}/browse${
newPath === "" ? "" : `/${encodeFileName(newPath)}`
}`
);
}
};

View File

@@ -328,7 +328,16 @@ func downloadObject(ctx context.Context, client MCClient, versionID *string) (io
// getDeleteObjectResponse returns whether there was an error on deletion of object
func getDeleteObjectResponse(session *models.Principal, params user_api.DeleteObjectParams) *models.Error {
ctx := context.Background()
s3Client, err := newS3BucketClient(session, params.BucketName, params.Path)
var prefix string
if params.Path != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Path)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return prepareError(err)
}
prefix = string(decodedPrefix)
}
s3Client, err := newS3BucketClient(session, params.BucketName, prefix)
if err != nil {
return prepareError(err)
}
@@ -343,7 +352,7 @@ func getDeleteObjectResponse(session *models.Principal, params user_api.DeleteOb
if params.VersionID != nil {
version = *params.VersionID
}
err = deleteObjects(ctx, mcClient, params.BucketName, params.Path, version, rec)
err = deleteObjects(ctx, mcClient, params.BucketName, prefix, version, rec)
if err != nil {
return prepareError(err)
}