Compare commits

..
7 Commits
10 changed files with 95 additions and 17 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"id": "remotely-save", "id": "remotely-save",
"name": "Remotely Save", "name": "Remotely Save",
"version": "0.3.8", "version": "0.3.9",
"minAppVersion": "0.13.21", "minAppVersion": "0.13.21",
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.", "description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
"author": "fyears", "author": "fyears",
+2 -3
View File
@@ -1,6 +1,6 @@
{ {
"name": "remotely-save", "name": "remotely-save",
"version": "0.3.8", "version": "0.3.9",
"description": "This is yet another sync plugin for Obsidian app.", "description": "This is yet another sync plugin for Obsidian app.",
"scripts": { "scripts": {
"dev2": "node esbuild.config.mjs", "dev2": "node esbuild.config.mjs",
@@ -26,7 +26,6 @@
"@microsoft/microsoft-graph-types": "^2.11.0", "@microsoft/microsoft-graph-types": "^2.11.0",
"@types/chai": "^4.2.22", "@types/chai": "^4.2.22",
"@types/chai-as-promised": "^7.1.4", "@types/chai-as-promised": "^7.1.4",
"@types/feather-icons": "^4.7.0",
"@types/jsdom": "^16.2.13", "@types/jsdom": "^16.2.13",
"@types/lodash": "^4.14.178", "@types/lodash": "^4.14.178",
"@types/mime-types": "^2.1.1", "@types/mime-types": "^2.1.1",
@@ -69,11 +68,11 @@
"codemirror": "^5.63.1", "codemirror": "^5.63.1",
"crypto-browserify": "^3.12.0", "crypto-browserify": "^3.12.0",
"dropbox": "^10.22.0", "dropbox": "^10.22.0",
"feather-icons": "^4.28.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",
"loglevel": "^1.8.0", "loglevel": "^1.8.0",
"lucide": "^0.17.12",
"mime-types": "^2.1.33", "mime-types": "^2.1.33",
"mustache": "^4.2.0", "mustache": "^4.2.0",
"nanoid": "^3.1.30", "nanoid": "^3.1.30",
+1
View File
@@ -15,6 +15,7 @@ export interface S3Config {
s3BucketName: string; s3BucketName: string;
bypassCorsLocally?: boolean; bypassCorsLocally?: boolean;
partsConcurrency?: number; partsConcurrency?: number;
forcePathStyle?: boolean;
} }
export interface DropboxConfig { export interface DropboxConfig {
+20
View File
@@ -165,3 +165,23 @@ export const decryptBase64urlToString = async (
) )
); );
}; };
export const getSizeFromOrigToEnc = (x: number) => {
if (x < 0 || !Number.isInteger(x)) {
throw Error(`x=${x} is not a valid size`);
}
return (Math.floor(x / 16) + 1) * 16 + 16;
};
export const getSizeFromEncToOrig = (x: number) => {
if (x < 32 || !Number.isInteger(x)) {
throw Error(`${x} is not a valid size`);
}
if (x % 16 !== 0) {
throw Error(`${x} is not a valid encrypted file size`);
}
return {
minSize: ((x - 16) / 16 - 1) * 16,
maxSize: ((x - 16) / 16 - 1) * 16 + 15,
};
};
+13 -11
View File
@@ -1,7 +1,7 @@
import { Modal, Notice, Plugin, Setting, addIcon, setIcon } from "obsidian"; import { Modal, Notice, Plugin, Setting, addIcon, setIcon } from "obsidian";
import cloneDeep from "lodash/cloneDeep"; import cloneDeep from "lodash/cloneDeep";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
import feather from "feather-icons"; import { createElement, RotateCcw, RefreshCcw } from "lucide";
import type { RemotelySavePluginSettings } from "./baseTypes"; import type { RemotelySavePluginSettings } from "./baseTypes";
import { import {
COMMAND_CALLBACK, COMMAND_CALLBACK,
@@ -76,14 +76,13 @@ type SyncTriggerSourceType = "manual" | "auto" | "dry" | "autoOnceInit";
const iconNameSyncWait = `remotely-save-sync-wait`; const iconNameSyncWait = `remotely-save-sync-wait`;
const iconNameSyncRunning = `remotely-save-sync-running`; const iconNameSyncRunning = `remotely-save-sync-running`;
const iconSvgSyncWait = feather.icons["rotate-ccw"].toSvg({
width: 100, const iconSvgSyncWait = createElement(RotateCcw);
height: 100, iconSvgSyncWait.setAttribute("width", "100");
}); iconSvgSyncWait.setAttribute("height", "100");
const iconSvgSyncRunning = feather.icons["refresh-ccw"].toSvg({ const iconSvgSyncRunning = createElement(RefreshCcw);
width: 100, iconSvgSyncRunning.setAttribute("width", "100");
height: 100, iconSvgSyncRunning.setAttribute("height", "100");
});
export default class RemotelySavePlugin extends Plugin { export default class RemotelySavePlugin extends Plugin {
settings: RemotelySavePluginSettings; settings: RemotelySavePluginSettings;
@@ -345,8 +344,8 @@ export default class RemotelySavePlugin extends Plugin {
async onload() { async onload() {
log.info(`loading plugin ${this.manifest.id}`); log.info(`loading plugin ${this.manifest.id}`);
addIcon(iconNameSyncWait, iconSvgSyncWait); addIcon(iconNameSyncWait, iconSvgSyncWait.outerHTML);
addIcon(iconNameSyncRunning, iconSvgSyncRunning); addIcon(iconNameSyncRunning, iconSvgSyncRunning.outerHTML);
this.oauth2Info = { this.oauth2Info = {
verifier: "", verifier: "",
@@ -659,6 +658,9 @@ export default class RemotelySavePlugin extends Plugin {
if (this.settings.s3.partsConcurrency === undefined) { if (this.settings.s3.partsConcurrency === undefined) {
this.settings.s3.partsConcurrency = 20; this.settings.s3.partsConcurrency = 20;
} }
if (this.settings.s3.forcePathStyle === undefined) {
this.settings.s3.forcePathStyle = false;
}
} }
async saveSettings() { async saveSettings() {
+3
View File
@@ -155,6 +155,7 @@ export const DEFAULT_S3_CONFIG = {
s3BucketName: "", s3BucketName: "",
bypassCorsLocally: true, bypassCorsLocally: true,
partsConcurrency: 20, partsConcurrency: 20,
forcePathStyle: false,
}; };
export type S3ObjectType = _Object; export type S3ObjectType = _Object;
@@ -192,6 +193,7 @@ export const getS3Client = (s3Config: S3Config) => {
const s3Client = new S3Client({ const s3Client = new S3Client({
region: s3Config.s3Region, region: s3Config.s3Region,
endpoint: endpoint, endpoint: endpoint,
forcePathStyle: s3Config.forcePathStyle,
credentials: { credentials: {
accessKeyId: s3Config.s3AccessKeyID, accessKeyId: s3Config.s3AccessKeyID,
secretAccessKey: s3Config.s3SecretAccessKey, secretAccessKey: s3Config.s3SecretAccessKey,
@@ -203,6 +205,7 @@ export const getS3Client = (s3Config: S3Config) => {
const s3Client = new S3Client({ const s3Client = new S3Client({
region: s3Config.s3Region, region: s3Config.s3Region,
endpoint: endpoint, endpoint: endpoint,
forcePathStyle: s3Config.forcePathStyle,
credentials: { credentials: {
accessKeyId: s3Config.s3AccessKeyID, accessKeyId: s3Config.s3AccessKeyID,
secretAccessKey: s3Config.s3SecretAccessKey, secretAccessKey: s3Config.s3SecretAccessKey,
+21
View File
@@ -745,6 +745,27 @@ export class RemotelySaveSettingTab extends PluginSettingTab {
}) })
); );
new Setting(s3Div)
.setName(t("settings_s3_urlstyle"))
.setDesc(t("settings_s3_urlstyle_desc"))
.addDropdown((dropdown) => {
dropdown.addOption(
"virtualHostedStyle",
"Virtual Hosted-Style (default)"
);
dropdown.addOption("pathStyle", "Path-Style");
dropdown
.setValue(
this.plugin.settings.s3.forcePathStyle
? "pathStyle"
: "virtualHostedStyle"
)
.onChange(async (val: string) => {
this.plugin.settings.s3.forcePathStyle = val === "pathStyle";
await this.plugin.saveSettings();
});
});
if (requireApiVersion(API_VER_REQURL)) { if (requireApiVersion(API_VER_REQURL)) {
new Setting(s3Div) new Setting(s3Div)
.setName(t("settings_s3_bypasscorslocally")) .setName(t("settings_s3_bypasscorslocally"))
+32
View File
@@ -8,6 +8,8 @@ import {
encryptArrayBuffer, encryptArrayBuffer,
encryptStringToBase32, encryptStringToBase32,
encryptStringToBase64url, encryptStringToBase64url,
getSizeFromEncToOrig,
getSizeFromOrigToEnc,
} from "../src/encrypt"; } from "../src/encrypt";
import { base64ToBase64url, bufferToArrayBuffer } from "../src/misc"; import { base64ToBase64url, bufferToArrayBuffer } from "../src/misc";
@@ -110,4 +112,34 @@ describe("Encryption tests", () => {
expect(Buffer.from(dec).equals(Buffer.from(opensslArrBuf))).to.be.true; expect(Buffer.from(dec).equals(Buffer.from(opensslArrBuf))).to.be.true;
}); });
it("should get size from origin to encrypted correctly", () => {
expect(() => getSizeFromOrigToEnc(-1)).to.throw();
expect(() => getSizeFromOrigToEnc(0.5)).to.throw();
expect(getSizeFromOrigToEnc(0)).equals(32);
expect(getSizeFromOrigToEnc(15)).equals(32);
expect(getSizeFromOrigToEnc(16)).equals(48);
expect(getSizeFromOrigToEnc(31)).equals(48);
expect(getSizeFromOrigToEnc(32)).equals(64);
expect(getSizeFromOrigToEnc(14787203)).equals(14787232);
});
it("should get size from encrypted to origin correctly", () => {
expect(() => getSizeFromEncToOrig(-1)).to.throw();
expect(() => getSizeFromEncToOrig(30)).to.throw();
expect(getSizeFromEncToOrig(32)).to.deep.equal({
minSize: 0,
maxSize: 15,
});
expect(getSizeFromEncToOrig(48)).to.deep.equal({
minSize: 16,
maxSize: 31,
});
expect(() => getSizeFromEncToOrig(14787231)).to.throw();
let { minSize, maxSize } = getSizeFromEncToOrig(14787232);
expect(minSize <= 14787203 && 14787203 <= maxSize).to.be.true;
});
}); });
+1 -1
View File
@@ -1,4 +1,4 @@
{ {
"0.3.2": "0.12.15", "0.3.2": "0.12.15",
"0.3.8": "0.13.21" "0.3.9": "0.13.21"
} }