Compare commits

..
3 Commits
Author SHA1 Message Date
fyears 05313f9530 0.0.13 2021-11-09 10:01:18 +08:00
fyears ce4e55fcc7 more tests 2021-11-09 10:00:44 +08:00
fyears b26d6a7ffb more clear notice 2021-11-09 10:00:14 +08:00
7 changed files with 65 additions and 9 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"id": "obsdian-save-remote", "id": "obsdian-save-remote",
"name": "Save remote", "name": "Save remote",
"version": "0.0.12", "version": "0.0.13",
"minAppVersion": "0.12.15", "minAppVersion": "0.12.15",
"description": "This is yet another plugin allowing users to sync notes between local device and the cloud.", "description": "This is yet another plugin allowing users to sync notes between local device and the cloud.",
"author": "fyears", "author": "fyears",
+3 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "obsidian-save-remote", "name": "obsidian-save-remote",
"version": "0.0.12", "version": "0.0.13",
"description": "This is yet another sync plugin for Obsidian app.", "description": "This is yet another sync plugin for Obsidian app.",
"scripts": { "scripts": {
"dev": "webpack --mode development --watch", "dev": "webpack --mode development --watch",
@@ -31,7 +31,8 @@
"typescript": "^4.4.4", "typescript": "^4.4.4",
"webdav-server": "^2.6.2", "webdav-server": "^2.6.2",
"webpack": "^5.58.2", "webpack": "^5.58.2",
"webpack-cli": "^4.9.1" "webpack-cli": "^4.9.1",
"xregexp": "^5.1.0"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.37.0", "@aws-sdk/client-s3": "^3.37.0",
+1
View File
@@ -105,6 +105,7 @@ export default class SaveRemotePlugin extends Plugin {
this.settings.password this.settings.password
); );
if (!passwordCheckResult.ok) { if (!passwordCheckResult.ok) {
new Notice("something goes wrong while checking password");
throw Error(passwordCheckResult.reason); throw Error(passwordCheckResult.reason);
} }
+19
View File
@@ -2,6 +2,7 @@ import { Vault } from "obsidian";
import * as path from "path"; import * as path from "path";
import { base32 } from "rfc4648"; import { base32 } from "rfc4648";
import XRegExp from "XRegExp";
export type SUPPORTED_SERVICES_TYPE = "s3" | "webdav" | "ftp"; export type SUPPORTED_SERVICES_TYPE = "s3" | "webdav" | "ftp";
@@ -111,3 +112,21 @@ export const hexStringToTypedArray = (hex: string) => {
export const base64ToBase32 = (a: string) => { export const base64ToBase32 = (a: string) => {
return base32.stringify(Buffer.from(a, "base64")); return base32.stringify(Buffer.from(a, "base64"));
}; };
/**
* iOS Safari could decrypt string with invalid password!
* So we need an extra way to test the decrypted result.
* One simple way is testing the result are "valid", printable chars or not.
*
* https://stackoverflow.com/questions/6198986
* https://www.regular-expressions.info/unicode.html
* Manual test shows that emojis like '🍎' match '\\p{Cs}',
* so we need to write the regrex in a form that \p{C} minus \p{Cs}
* @param a
*/
export const isVaildText = (a: string) => {
// If the regex matches, the string is invalid.
return !XRegExp("\\p{Cc}|\\p{Cf}|\\p{Co}|\\p{Cn}|\\p{Zl}|\\p{Zp}", "A").test(
a
);
};
+21 -5
View File
@@ -16,7 +16,12 @@ import {
deleteFromRemote, deleteFromRemote,
downloadFromRemote, downloadFromRemote,
} from "./s3"; } from "./s3";
import { mkdirpInVault, SUPPORTED_SERVICES_TYPE, isHiddenPath } from "./misc"; import {
mkdirpInVault,
SUPPORTED_SERVICES_TYPE,
isHiddenPath,
isVaildText,
} from "./misc";
import { import {
decryptBase32ToString, decryptBase32ToString,
encryptStringToBase32, encryptStringToBase32,
@@ -74,6 +79,7 @@ export interface PasswordCheckType {
| "remote_encrypted_local_no_password" | "remote_encrypted_local_no_password"
| "password_matched" | "password_matched"
| "password_not_matched" | "password_not_matched"
| "invalid_text_after_decryption"
| "remote_not_encrypted_local_has_password" | "remote_not_encrypted_local_has_password"
| "no_password_both_sides"; | "no_password_both_sides";
} }
@@ -101,10 +107,20 @@ export const isPasswordOk = async (
} }
try { try {
const res = await decryptBase32ToString(santyCheckKey, password); const res = await decryptBase32ToString(santyCheckKey, password);
return {
ok: true, // additional test
reason: "password_matched", // because iOS Safari bypasses decryption with wrong password!
} as PasswordCheckType; if (isVaildText(res)) {
return {
ok: true,
reason: "password_matched",
} as PasswordCheckType;
} else {
return {
ok: false,
reason: "invalid_text_after_decryption",
} as PasswordCheckType;
}
} catch (error) { } catch (error) {
return { return {
ok: false, ok: false,
+19
View File
@@ -70,3 +70,22 @@ describe("Misc: get folder levels", () => {
expect(misc.getFolderLevels(item3)).to.deep.equal(res3); expect(misc.getFolderLevels(item3)).to.deep.equal(res3);
}); });
}); });
describe("Misc: vaild file name tests", () => {
it("should treat no ascii correctly", async () => {
const x = misc.isVaildText("😄🍎 apple 苹果");
// console.log(x)
expect(x).to.be.true;
});
it("should find not-printable chars correctly", async () => {
const x = misc.isVaildText("😄🍎 apple 苹果\u0000");
// console.log(x)
expect(x).to.be.false;
});
it("should allow spaces/slashes/...", async () => {
const x = misc.isVaildText("😄🍎 apple 苹果/-_=/\\*%^&@#$`");
expect(x).to.be.true;
});
});
+1 -1
View File
@@ -1,3 +1,3 @@
{ {
"0.0.12": "0.12.15" "0.0.13": "0.12.15"
} }