properly reject emoji file names for dropbox

This commit is contained in:
fyears 2022-04-16 11:36:04 +08:00
parent 9a4dd0186d
commit cb7a372b69
3 changed files with 97 additions and 14 deletions

View File

@ -68,6 +68,7 @@
"buffer": "^6.0.3",
"crypto-browserify": "^3.12.0",
"dropbox": "^10.22.0",
"emoji-regex": "^10.1.0",
"http-status-codes": "^2.2.0",
"localforage": "^1.10.0",
"lodash": "^4.17.21",

View File

@ -3,6 +3,7 @@ import * as path from "path";
import { base32, base64url } from "rfc4648";
import XRegExp from "xregexp";
import emojiRegex from "emoji-regex";
import { log } from "./moreOnLog";
@ -162,6 +163,34 @@ export const isVaildText = (a: string) => {
);
};
/**
* Use regex to detect a text contains emoji or not.
* @param a
* @returns
*/
export const hasEmojiInText = (a: string) => {
const regex = emojiRegex();
return regex.test(a);
};
/**
* Convert the headers to a normal object.
* @param h
* @param toLower
* @returns
*/
export const headersToRecord = (h: Headers, toLower: boolean = true) => {
const res: Record<string, string> = {};
h.forEach((v, k) => {
if (toLower) {
res[k.toLowerCase()] = v;
} else {
res[k] = v;
}
});
return res;
};
/**
* If input is already a folder, returns it as is;
* And if input is a file, returns its direname.

View File

@ -1,4 +1,4 @@
import { Dropbox, DropboxAuth, files } from "dropbox";
import { Dropbox, DropboxAuth, files, DropboxResponseError } from "dropbox";
import { Vault } from "obsidian";
import * as path from "path";
import {
@ -8,7 +8,13 @@ import {
OAUTH2_FORCE_EXPIRE_MILLISECONDS,
} from "./baseTypes";
import { decryptArrayBuffer, encryptArrayBuffer } from "./encrypt";
import { bufferToArrayBuffer, getFolderLevels, mkdirpInVault } from "./misc";
import {
bufferToArrayBuffer,
getFolderLevels,
hasEmojiInText,
headersToRecord,
mkdirpInVault,
} from "./misc";
export { Dropbox } from "dropbox";
@ -338,6 +344,13 @@ export class WrappedDropboxClient {
}
if (!this.vaultFolderExists) {
log.info(`remote does not have folder /${this.remoteBaseDir}`);
if (hasEmojiInText(`/${this.remoteBaseDir}`)) {
throw new Error(
`/${this.remoteBaseDir}: Error: Dropbox does not support emoji in folder names.`
);
}
await this.dropbox.filesCreateFolderV2({
path: `/${this.remoteBaseDir}`,
});
@ -423,6 +436,12 @@ export const uploadToRemote = async (
}
uploadFile = getDropboxPath(uploadFile, client.remoteBaseDir);
if (hasEmojiInText(uploadFile)) {
throw new Error(
`${uploadFile}: Error: Dropbox does not support emoji in file / folder names.`
);
}
const isFolder = fileOrFolderPath.endsWith("/");
if (isFolder && isRecursively) {
@ -442,7 +461,8 @@ export const uploadToRemote = async (
path: uploadFile,
});
foldersCreatedBefore?.add(uploadFile);
} catch (err) {
} catch (e: unknown) {
const err = e as DropboxResponseError<files.CreateFolderError>;
if (err.status === 409) {
// pass
foldersCreatedBefore?.add(uploadFile);
@ -455,10 +475,23 @@ export const uploadToRemote = async (
return res;
} else {
// if encrypted, upload a fake file with the encrypted file name
await client.dropbox.filesUpload({
path: uploadFile,
contents: "",
});
try {
await client.dropbox.filesUpload({
path: uploadFile,
contents: "",
});
} catch (e: unknown) {
const err = e as DropboxResponseError<files.UploadError>;
// log.debug(
// `we are of error: ${JSON.stringify(
// headersToRecord(err.headers),
// null,
// 2
// )}, ${err.status}, ${JSON.stringify(err.error, null, 2)}`
// );
throw err;
}
return await getRemoteMeta(client, uploadFile);
}
} else {
@ -480,13 +513,33 @@ export const uploadToRemote = async (
}
// in dropbox, we don't need to create folders before uploading! cool!
// TODO: filesUploadSession for larger files (>=150 MB)
await client.dropbox.filesUpload({
path: uploadFile,
contents: remoteContent,
mode: {
".tag": "overwrite",
},
});
try {
await client.dropbox.filesUpload({
path: uploadFile,
contents: remoteContent,
mode: {
".tag": "overwrite",
},
});
} catch (e: unknown) {
const err = e as DropboxResponseError<files.UploadError>;
// log.debug(
// `we are of error: ${JSON.stringify(
// headersToRecord(err.headers),
// null,
// 2
// )}, ${err.status}, ${JSON.stringify(err.error, null, 2)}`
// );
// if (err.status === 429) {
// // too many request
// } else if (err.status === 409) {
// // Endpoint Specific Error
// } else {
// throw err;
// }
throw err;
}
// we want to mark that parent folders are created
if (foldersCreatedBefore !== undefined) {
const dirs = getFolderLevels(uploadFile).map((x) =>