properly reject emoji file names for dropbox
This commit is contained in:
parent
9a4dd0186d
commit
cb7a372b69
@ -68,6 +68,7 @@
|
|||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"crypto-browserify": "^3.12.0",
|
"crypto-browserify": "^3.12.0",
|
||||||
"dropbox": "^10.22.0",
|
"dropbox": "^10.22.0",
|
||||||
|
"emoji-regex": "^10.1.0",
|
||||||
"http-status-codes": "^2.2.0",
|
"http-status-codes": "^2.2.0",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
|||||||
29
src/misc.ts
29
src/misc.ts
@ -3,6 +3,7 @@ import * as path from "path";
|
|||||||
|
|
||||||
import { base32, base64url } from "rfc4648";
|
import { base32, base64url } from "rfc4648";
|
||||||
import XRegExp from "xregexp";
|
import XRegExp from "xregexp";
|
||||||
|
import emojiRegex from "emoji-regex";
|
||||||
|
|
||||||
import { log } from "./moreOnLog";
|
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;
|
* If input is already a folder, returns it as is;
|
||||||
* And if input is a file, returns its direname.
|
* And if input is a file, returns its direname.
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Dropbox, DropboxAuth, files } from "dropbox";
|
import { Dropbox, DropboxAuth, files, DropboxResponseError } from "dropbox";
|
||||||
import { Vault } from "obsidian";
|
import { Vault } from "obsidian";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import {
|
import {
|
||||||
@ -8,7 +8,13 @@ import {
|
|||||||
OAUTH2_FORCE_EXPIRE_MILLISECONDS,
|
OAUTH2_FORCE_EXPIRE_MILLISECONDS,
|
||||||
} from "./baseTypes";
|
} from "./baseTypes";
|
||||||
import { decryptArrayBuffer, encryptArrayBuffer } from "./encrypt";
|
import { decryptArrayBuffer, encryptArrayBuffer } from "./encrypt";
|
||||||
import { bufferToArrayBuffer, getFolderLevels, mkdirpInVault } from "./misc";
|
import {
|
||||||
|
bufferToArrayBuffer,
|
||||||
|
getFolderLevels,
|
||||||
|
hasEmojiInText,
|
||||||
|
headersToRecord,
|
||||||
|
mkdirpInVault,
|
||||||
|
} from "./misc";
|
||||||
|
|
||||||
export { Dropbox } from "dropbox";
|
export { Dropbox } from "dropbox";
|
||||||
|
|
||||||
@ -338,6 +344,13 @@ export class WrappedDropboxClient {
|
|||||||
}
|
}
|
||||||
if (!this.vaultFolderExists) {
|
if (!this.vaultFolderExists) {
|
||||||
log.info(`remote does not have folder /${this.remoteBaseDir}`);
|
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({
|
await this.dropbox.filesCreateFolderV2({
|
||||||
path: `/${this.remoteBaseDir}`,
|
path: `/${this.remoteBaseDir}`,
|
||||||
});
|
});
|
||||||
@ -423,6 +436,12 @@ export const uploadToRemote = async (
|
|||||||
}
|
}
|
||||||
uploadFile = getDropboxPath(uploadFile, client.remoteBaseDir);
|
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("/");
|
const isFolder = fileOrFolderPath.endsWith("/");
|
||||||
|
|
||||||
if (isFolder && isRecursively) {
|
if (isFolder && isRecursively) {
|
||||||
@ -442,7 +461,8 @@ export const uploadToRemote = async (
|
|||||||
path: uploadFile,
|
path: uploadFile,
|
||||||
});
|
});
|
||||||
foldersCreatedBefore?.add(uploadFile);
|
foldersCreatedBefore?.add(uploadFile);
|
||||||
} catch (err) {
|
} catch (e: unknown) {
|
||||||
|
const err = e as DropboxResponseError<files.CreateFolderError>;
|
||||||
if (err.status === 409) {
|
if (err.status === 409) {
|
||||||
// pass
|
// pass
|
||||||
foldersCreatedBefore?.add(uploadFile);
|
foldersCreatedBefore?.add(uploadFile);
|
||||||
@ -455,10 +475,23 @@ export const uploadToRemote = async (
|
|||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
// if encrypted, upload a fake file with the encrypted file name
|
// if encrypted, upload a fake file with the encrypted file name
|
||||||
await client.dropbox.filesUpload({
|
try {
|
||||||
path: uploadFile,
|
await client.dropbox.filesUpload({
|
||||||
contents: "",
|
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);
|
return await getRemoteMeta(client, uploadFile);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -480,13 +513,33 @@ export const uploadToRemote = async (
|
|||||||
}
|
}
|
||||||
// in dropbox, we don't need to create folders before uploading! cool!
|
// in dropbox, we don't need to create folders before uploading! cool!
|
||||||
// TODO: filesUploadSession for larger files (>=150 MB)
|
// TODO: filesUploadSession for larger files (>=150 MB)
|
||||||
await client.dropbox.filesUpload({
|
try {
|
||||||
path: uploadFile,
|
await client.dropbox.filesUpload({
|
||||||
contents: remoteContent,
|
path: uploadFile,
|
||||||
mode: {
|
contents: remoteContent,
|
||||||
".tag": "overwrite",
|
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
|
// we want to mark that parent folders are created
|
||||||
if (foldersCreatedBefore !== undefined) {
|
if (foldersCreatedBefore !== undefined) {
|
||||||
const dirs = getFolderLevels(uploadFile).map((x) =>
|
const dirs = getFolderLevels(uploadFile).map((x) =>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user