mirror of
https://github.com/lajg-dev/Obsidian-Plugin-GPG-Inline-Encrypt.git
synced 2026-07-22 09:20:31 +00:00
Merge fed8875957 into 81ff801005
This commit is contained in:
commit
f86f00a4d1
6 changed files with 228 additions and 92 deletions
|
|
@ -102,7 +102,7 @@ export class DecryptPreviewModal extends Modal {
|
|||
}
|
||||
}
|
||||
// Send Decrypt command
|
||||
let decryptedTextResult: GpgResult = await gpgDecrypt(this.plugin.settings, this.encryptedMessage, passphrase);
|
||||
let decryptedTextResult: GpgResult = await gpgDecrypt(this.plugin, this.plugin.settings, this.encryptedMessage, passphrase);
|
||||
// Check if result contains data
|
||||
if (decryptedTextResult.result) {
|
||||
// Cache the passphrase after a successful decrypt (openpgpjs only)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export class EncryptModal extends Modal {
|
|||
return;
|
||||
}
|
||||
// Show which key will be used
|
||||
let openpgpKeys = await getListPublicKey(this.plugin.settings);
|
||||
let openpgpKeys = await getListPublicKey(this.plugin, this.plugin.settings);
|
||||
if (openpgpKeys.length > 0) {
|
||||
contentEl.createEl("p", { text: "Encrypting with key: " + openpgpKeys[0].userID + " (" + openpgpKeys[0].keyID + ")" });
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ export class EncryptModal extends Modal {
|
|||
// Help text is created to select GPG keys
|
||||
contentEl.createEl("p", { text: "Select which Public GPG key(s) you want to be able to decrypt the text:" });
|
||||
// Get list of GPG public Keys
|
||||
let gpgPublicKeys: { keyID: string; userID: string }[] = await getListPublicKey(this.plugin.settings);
|
||||
let gpgPublicKeys: { keyID: string; userID: string }[] = await getListPublicKey(this.plugin, this.plugin.settings);
|
||||
// Sign key name by ID
|
||||
let gpgSignName: string = "";
|
||||
// Iterate over each public key
|
||||
|
|
@ -166,7 +166,7 @@ export class EncryptModal extends Modal {
|
|||
// Check if EncryptMode is Inline
|
||||
if (this.encryptMode == EncryptModalMode.INLINE) {
|
||||
// Send Encrypt command with list of GPG public keys IDs
|
||||
let encryptedTextResult: GpgResult = await gpgEncrypt(this.plugin.settings, this.editor.getSelection(), this.listPublicKeyToEncrypt, this.plugin.settings.pgpSignPublicKeyId, passphrase);
|
||||
let encryptedTextResult: GpgResult = await gpgEncrypt(this.plugin, this.plugin.settings, this.editor.getSelection(), this.listPublicKeyToEncrypt, this.plugin.settings.pgpSignPublicKeyId, passphrase);
|
||||
// Check if any error exists
|
||||
if (encryptedTextResult.error) {
|
||||
// Show the error message
|
||||
|
|
@ -187,7 +187,7 @@ export class EncryptModal extends Modal {
|
|||
// Check if EncryptMode is Document
|
||||
else if (this.encryptMode == EncryptModalMode.DOCUMENT) {
|
||||
// Send Encrypt command with list of GPG public keys IDs
|
||||
let encryptedTextResult: GpgResult = await gpgEncrypt(this.plugin.settings, this.editor.getValue(), this.listPublicKeyToEncrypt, this.plugin.settings.pgpSignPublicKeyId, passphrase);
|
||||
let encryptedTextResult: GpgResult = await gpgEncrypt(this.plugin, this.plugin.settings, this.editor.getValue(), this.listPublicKeyToEncrypt, this.plugin.settings.pgpSignPublicKeyId, passphrase);
|
||||
// Check if result contains data
|
||||
if (encryptedTextResult.result) {
|
||||
// Cache the passphrase after a successful sign+encrypt
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import GpgEncryptPlugin from "main";
|
|||
|
||||
// Settings object
|
||||
export interface GpgEncryptSettings {
|
||||
pgpExecPath: string;
|
||||
pgpExecPaths: string[];
|
||||
pgpSignPublicKeyId: string
|
||||
pgpAlwaysTrust: boolean,
|
||||
pgpDefaultEncryptKeys: Array<string>,
|
||||
|
|
@ -20,7 +20,7 @@ export interface GpgEncryptSettings {
|
|||
|
||||
// Default settings values
|
||||
const DEFAULT_SETTINGS: GpgEncryptSettings = {
|
||||
pgpExecPath: getDefaultExecPath(),
|
||||
pgpExecPaths: getDefaultExecPaths(),
|
||||
pgpSignPublicKeyId: "0",
|
||||
pgpAlwaysTrust: false,
|
||||
pgpDefaultEncryptKeys: [],
|
||||
|
|
@ -49,34 +49,78 @@ export class Settings {
|
|||
|
||||
// Load Settings from Plugin Data
|
||||
async loadSettings() {
|
||||
this.plugin.settings = Object.assign({}, DEFAULT_SETTINGS, await this.plugin.loadData());
|
||||
const loadedData = await this.plugin.loadData();
|
||||
this.plugin.settings = Object.assign({}, DEFAULT_SETTINGS, loadedData);
|
||||
|
||||
// Migration: convert old single pgpExecPath to pgpExecPaths array
|
||||
if (loadedData && 'pgpExecPath' in loadedData && typeof loadedData.pgpExecPath === 'string') {
|
||||
if (loadedData.pgpExecPath) {
|
||||
// If old path exists, put it first in array, then add defaults
|
||||
this.plugin.settings.pgpExecPaths = [loadedData.pgpExecPath, ...getDefaultExecPaths().filter(p => p !== loadedData.pgpExecPath)];
|
||||
} else {
|
||||
// If old path was empty, just use defaults
|
||||
this.plugin.settings.pgpExecPaths = getDefaultExecPaths();
|
||||
}
|
||||
// Save migrated settings
|
||||
await this.saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
// Save Settings to Plugin Data
|
||||
async saveSettings() {
|
||||
await this.plugin.saveData(this.plugin.settings);
|
||||
}
|
||||
|
||||
// Get the first working GPG executable path from the list
|
||||
async getWorkingGpgPath(): Promise<string | null> {
|
||||
// Lazy require so it works on mobile
|
||||
if (typeof process === "undefined" || !process.platform) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
// Try each path in order
|
||||
for (const path of this.plugin.settings.pgpExecPaths) {
|
||||
if (!path) continue;
|
||||
|
||||
try {
|
||||
// Check if file exists and is a gpg executable
|
||||
if (fs.existsSync(path) &&
|
||||
(path.endsWith("gpg") || path.endsWith("gpg.exe") ||
|
||||
path.endsWith("gpg2") || path.endsWith("gpg2.exe"))) {
|
||||
return path;
|
||||
}
|
||||
} catch (ex) {
|
||||
// Continue to next path
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Get Default Exec Path in base on platform name
|
||||
function getDefaultExecPath(): string {
|
||||
// Get Default Exec Paths for all platforms
|
||||
function getDefaultExecPaths(): string[] {
|
||||
// On mobile there is no Node process; return empty (native GPG is unavailable there)
|
||||
if (typeof process === "undefined" || !process.platform) {
|
||||
return "";
|
||||
}
|
||||
// Check platform name
|
||||
switch (process.platform) {
|
||||
// In case of Windows OS
|
||||
case "win32":
|
||||
return "C:\\Program Files (x86)\\GnuPG\\bin\\gpg.exe";
|
||||
// In case of MacOS
|
||||
case "darwin":
|
||||
return "/usr/local/bin/gpg";
|
||||
// In case of Linux
|
||||
case "linux":
|
||||
return "/usr/bin/gpg";
|
||||
// In default value return empty
|
||||
default:
|
||||
return "";
|
||||
return [];
|
||||
}
|
||||
// Return common paths for all platforms so config works cross-platform
|
||||
return [
|
||||
// Windows paths
|
||||
"C:\\Program Files (x86)\\GnuPG\\bin\\gpg.exe",
|
||||
"C:\\Program Files\\GnuPG\\bin\\gpg.exe",
|
||||
// macOS paths
|
||||
"/usr/local/bin/gpg",
|
||||
"/opt/homebrew/bin/gpg",
|
||||
"/usr/local/MacGPG2/bin/gpg",
|
||||
"/usr/local/MacGPG2/bin/gpg2",
|
||||
// Linux paths
|
||||
"/usr/bin/gpg",
|
||||
"/usr/bin/gpg2",
|
||||
"/bin/gpg",
|
||||
"/bin/gpg2"
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import spawnGPG, { GpgResult, getListPublicKey } from 'src/gpg';
|
||||
import spawnGPG, { GpgResult, getListPublicKey, clearWorkingPathCache } from 'src/gpg';
|
||||
import { App, DropdownComponent, PluginSettingTab, Setting } from 'obsidian';
|
||||
import GpgEncryptPlugin from 'main';
|
||||
import { Settings } from './Settings';
|
||||
|
|
@ -24,7 +24,8 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
this.plugin = plugin;
|
||||
}
|
||||
// List of settings objetcts
|
||||
private gpgExecPath: Setting;
|
||||
private gpgExecPaths: Setting;
|
||||
private gpgExecPathsList: HTMLDivElement;
|
||||
private gpgAditionalCommands: Setting;
|
||||
private gpgAditionalCommandsBefore: Setting;
|
||||
private gpgAditionalCommandsAfter: Setting;
|
||||
|
|
@ -74,24 +75,25 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
// ---------- OpenPGP.js settings ----------
|
||||
|
||||
// ---------- GPG executable setting ----------
|
||||
this.gpgExecPath = new Setting(containerEl)
|
||||
.setName('GPG executable')
|
||||
.setDesc('Path to GPG executable')
|
||||
.addText(text => text
|
||||
.setPlaceholder('gpg')
|
||||
.setValue(this.plugin.settings.pgpExecPath)
|
||||
.onChange(async (value: string) => {
|
||||
await this.checkGpgPath(value);
|
||||
}));
|
||||
this.gpgExecPaths = new Setting(containerEl)
|
||||
.setName('GPG executable paths')
|
||||
.setDesc('List of GPG executable paths to try (first working path will be used)');
|
||||
// Div to show list of paths
|
||||
this.gpgExecPathsList = this.gpgExecPaths.descEl.createDiv();
|
||||
this.gpgExecPathsList.className = "gpg-paths-list";
|
||||
// Render the paths list
|
||||
this.renderGpgPathsList();
|
||||
// Div to show GPG Path status
|
||||
this.gpgExecPathStatus = this.gpgExecPath.descEl.createDiv();
|
||||
this.gpgExecPathStatus = containerEl.createDiv();
|
||||
this.gpgExecPathStatus.style.marginTop = "10px";
|
||||
this.gpgExecPathStatus.style.marginBottom = "10px";
|
||||
// ---------- GPG executable setting ----------
|
||||
|
||||
// ---------- List of GPG Public Keys ----------
|
||||
this.gpgPublicKeysList = new Setting(containerEl)
|
||||
.setName("Public keys")
|
||||
// Run by first time checkGpgPath function
|
||||
this.checkGpgPath(this.plugin.settings.pgpExecPath);
|
||||
// Run by first time checkGpgPaths function
|
||||
this.checkGpgPaths();
|
||||
// ---------- List of GPG Public Keys ----------
|
||||
|
||||
// ---------- Always Trust ----------
|
||||
|
|
@ -161,41 +163,80 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
// ---------- Aditional Commands ----------
|
||||
}
|
||||
|
||||
// Function to check if GPG Path exits
|
||||
private async checkGpgPath(value: string) {
|
||||
// Function to render GPG paths list with add/remove functionality
|
||||
private renderGpgPathsList() {
|
||||
// Clear the list
|
||||
this.gpgExecPathsList.empty();
|
||||
|
||||
// Iterate over each path
|
||||
this.plugin.settings.pgpExecPaths.forEach((path, index) => {
|
||||
const pathDiv = this.gpgExecPathsList.createDiv();
|
||||
pathDiv.className = "gpg-path-item";
|
||||
|
||||
const pathSetting = new Setting(pathDiv)
|
||||
.addText(text => text
|
||||
.setPlaceholder('/usr/bin/gpg or C:\\Program Files\\GnuPG\\bin\\gpg.exe')
|
||||
.setValue(path)
|
||||
.onChange(async (value: string) => {
|
||||
this.plugin.settings.pgpExecPaths[index] = value;
|
||||
await new Settings(this.plugin).saveSettings();
|
||||
clearWorkingPathCache();
|
||||
this.checkGpgPaths();
|
||||
}))
|
||||
.addButton(button => button
|
||||
.setButtonText("Remove")
|
||||
.setWarning()
|
||||
.onClick(async () => {
|
||||
this.plugin.settings.pgpExecPaths.splice(index, 1);
|
||||
await new Settings(this.plugin).saveSettings();
|
||||
clearWorkingPathCache();
|
||||
this.renderGpgPathsList();
|
||||
this.checkGpgPaths();
|
||||
}));
|
||||
});
|
||||
|
||||
// Add button to add new path
|
||||
new Setting(this.gpgExecPathsList)
|
||||
.addButton(button => button
|
||||
.setButtonText("Add path")
|
||||
.setCta()
|
||||
.onClick(async () => {
|
||||
this.plugin.settings.pgpExecPaths.push("");
|
||||
await new Settings(this.plugin).saveSettings();
|
||||
this.renderGpgPathsList();
|
||||
}));
|
||||
}
|
||||
|
||||
// Function to check all GPG paths and find working one
|
||||
private async checkGpgPaths() {
|
||||
// Check if pgp Library is openpgpjs
|
||||
if (this.plugin.settings.pgpLibrary == "openpgpjs")
|
||||
// Abort the process
|
||||
return;
|
||||
// Lazy require so the settings tab still loads on mobile, where fs is absent
|
||||
const fs = require('fs');
|
||||
// Set settig variable pgpExecPath with new value
|
||||
this.plugin.settings.pgpExecPath = value;
|
||||
// Save settings with change
|
||||
await new Settings(this.plugin).saveSettings();
|
||||
|
||||
// Hide list of public GPG Keys
|
||||
this.gpgPublicKeysList.settingEl.hide();
|
||||
// Start with Loading status while real one is calculated
|
||||
this.changeGpgPathStatus(GpgExecPathStatus.LOADING);
|
||||
|
||||
// Get working path
|
||||
const workingPath = await new Settings(this.plugin).getWorkingGpgPath();
|
||||
|
||||
if (!workingPath) {
|
||||
this.changeGpgPathStatus(GpgExecPathStatus.FILE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if path ends with any gpg executable
|
||||
if (!workingPath.endsWith("gpg") && !workingPath.endsWith("gpg.exe") && !workingPath.endsWith("gpg2") && !workingPath.endsWith("gpg2.exe")){
|
||||
this.changeGpgPathStatus(GpgExecPathStatus.NO_GPG_IN_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
// Start a try in case of exception
|
||||
try
|
||||
{
|
||||
// Check if file doesn not exist
|
||||
if (!fs.existsSync(value)) {
|
||||
// Change the status to File Not Found
|
||||
this.changeGpgPathStatus(GpgExecPathStatus.FILE_NOT_FOUND);
|
||||
// End this check process
|
||||
return;
|
||||
}
|
||||
// Check if path ends with any gpg executable
|
||||
if (!value.endsWith("gpg") && !value.endsWith("gpg.exe") && !value.endsWith("gpg2") && !value.endsWith("gpg2.exe")){
|
||||
// Change the status to No GPG In Path
|
||||
this.changeGpgPathStatus(GpgExecPathStatus.NO_GPG_IN_PATH);
|
||||
// End this check process
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Check GPG version in console
|
||||
let gpgResult: GpgResult = await spawnGPG(this.plugin.settings, null, ["--logger-fd", "1", "--version"]);
|
||||
let gpgResult: GpgResult = await spawnGPG(this.plugin, this.plugin.settings, null, ["--logger-fd", "1", "--version"]);
|
||||
// Check if result is not null and is not an error
|
||||
if(gpgResult.result && !gpgResult.error) {
|
||||
// Get version string from result
|
||||
|
|
@ -203,7 +244,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
// In case of words gpg or GnuPG are include in output
|
||||
if(version.includes("gpg") && version.includes("GnuPG")) {
|
||||
// Change the status to OK
|
||||
this.changeGpgPathStatus(GpgExecPathStatus.OK);
|
||||
this.changeGpgPathStatus(GpgExecPathStatus.OK, workingPath);
|
||||
// Refresh GPG public key list
|
||||
await this.RefreshGpgPublicKeyList();
|
||||
// End this check process
|
||||
|
|
@ -251,10 +292,20 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
}
|
||||
}
|
||||
|
||||
// Function to check if GPG Path exits (legacy - kept for compatibility)
|
||||
private async checkGpgPath(value: string) {
|
||||
// Just call the new checkGpgPaths function
|
||||
await this.checkGpgPaths();
|
||||
}
|
||||
|
||||
// Function to change GPG executable path status
|
||||
private changeGpgPathStatus(status: GpgExecPathStatus) {
|
||||
private changeGpgPathStatus(status: GpgExecPathStatus, workingPath?: string) {
|
||||
// Change text status with new one
|
||||
this.gpgExecPathStatus.setText(`Status: ${status}`);
|
||||
let statusText = `Status: ${status}`;
|
||||
if (status === GpgExecPathStatus.OK && workingPath) {
|
||||
statusText += ` (using: ${workingPath})`;
|
||||
}
|
||||
this.gpgExecPathStatus.setText(statusText);
|
||||
// Swich to identify status style
|
||||
switch (status) {
|
||||
// In case of Loading status
|
||||
|
|
@ -278,7 +329,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
// Function to refresh list of GPG Public Keys
|
||||
private async RefreshGpgPublicKeyList() {
|
||||
// Get list of GPG public Keys
|
||||
let gpgPublicKeys: { keyID: string; userID: string }[] = await getListPublicKey(this.plugin.settings);
|
||||
let gpgPublicKeys: { keyID: string; userID: string }[] = await getListPublicKey(this.plugin, this.plugin.settings);
|
||||
// Iterate over each sub-element in list
|
||||
while (this.gpgPublicKeysList.descEl.firstChild) {
|
||||
// Remove each sub-element in list to clear list
|
||||
|
|
@ -337,7 +388,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
// Check ir requireSign to populate DropDown
|
||||
if (requireSign) {
|
||||
// Get list of GPG public Keys
|
||||
let gpgPublicKeys: { keyID: string; userID: string }[] = await getListPublicKey(this.plugin.settings);
|
||||
let gpgPublicKeys: { keyID: string; userID: string }[] = await getListPublicKey(this.plugin, this.plugin.settings);
|
||||
// Discard result if a newer call has already started
|
||||
if (generation !== this.signListGeneration) return;
|
||||
// Clear all DropDown items
|
||||
|
|
@ -396,7 +447,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
// Save settings with change
|
||||
await new Settings(this.plugin).saveSettings();
|
||||
// Run a script to check gpg path with pgpAditionalCommandsBefore
|
||||
await this.checkGpgPath(this.plugin.settings.pgpExecPath);
|
||||
await this.checkGpgPaths();
|
||||
}));
|
||||
this.gpgAditionalCommandsAfter.addText(text => text
|
||||
.setPlaceholder('command')
|
||||
|
|
@ -407,7 +458,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
// Save settings with change
|
||||
await new Settings(this.plugin).saveSettings();
|
||||
// Run a script to check gpg path with pgpAditionalCommandsAfter
|
||||
await this.checkGpgPath(this.plugin.settings.pgpExecPath);
|
||||
await this.checkGpgPaths();
|
||||
}));
|
||||
this.gpgAditionalCommandsConsole.addToggle((toggle) => {
|
||||
// Toggle component default value is false
|
||||
|
|
@ -435,7 +486,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
this.plugin.settings.pgpAditionalCommands = false;
|
||||
// And hide the aditional commands settings
|
||||
this.gpgAditionalCommands.settingEl.hide();
|
||||
this.gpgExecPath.settingEl.hide();
|
||||
this.gpgExecPaths.settingEl.hide();
|
||||
this.gpgPublicKeysList.settingEl.hide();
|
||||
this.gpgSignKeyId.settingEl.hide();
|
||||
this.gpgSignText.settingEl.hide();
|
||||
|
|
@ -450,7 +501,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
this.openpgpSettingsEl.empty();
|
||||
// And show the aditional commands settings
|
||||
this.gpgAditionalCommands.settingEl.show();
|
||||
this.gpgExecPath.settingEl.show();
|
||||
this.gpgExecPaths.settingEl.show();
|
||||
this.gpgPublicKeysList.settingEl.show();
|
||||
this.gpgSignText.settingEl.show();
|
||||
this.gpgAlwaysTrust.settingEl.show();
|
||||
|
|
@ -462,7 +513,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
// Repopulate sign key dropdown with native GPG keys
|
||||
this.RefreshListSign(this.plugin.settings.pgpSignPublicKeyId != "0");
|
||||
|
||||
this.checkGpgPath(this.plugin.settings.pgpExecPath);
|
||||
this.checkGpgPaths();
|
||||
}
|
||||
|
||||
// Call method to show/hide aditional commands
|
||||
|
|
@ -555,7 +606,7 @@ export class GpgSettingsTab extends PluginSettingTab {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
const keys = await getListPublicKey(this.plugin.settings);
|
||||
const keys = await getListPublicKey(this.plugin, this.plugin.settings);
|
||||
if (keys.length > 0) {
|
||||
const infoEl = this.openpgpKeyInfoEl.createDiv();
|
||||
infoEl.className = "text-color-green";
|
||||
|
|
|
|||
67
src/gpg.ts
67
src/gpg.ts
|
|
@ -1,9 +1,14 @@
|
|||
import { GpgEncryptSettings } from "./Settings";
|
||||
import { GpgEncryptSettings, Settings } from "./Settings";
|
||||
import * as openpgpBackend from "./openpgp";
|
||||
import GpgEncryptPlugin from "main";
|
||||
|
||||
// Default and Global Args
|
||||
const globalArgs: string[] = ["--batch"];
|
||||
|
||||
// Cache for working GPG path to avoid repeated lookups
|
||||
let cachedWorkingPath: string | null = null;
|
||||
let cachedPlugin: GpgEncryptPlugin | null = null;
|
||||
|
||||
// Object that is returned when spawnGPG method is called
|
||||
export interface GpgResult {
|
||||
result?: Buffer | string;
|
||||
|
|
@ -23,12 +28,42 @@ function AditionalArgs(settings: GpgEncryptSettings): string[] {
|
|||
return aditionalArgs;
|
||||
}
|
||||
|
||||
// Function to get working GPG path from settings (with caching)
|
||||
async function getWorkingGpgPath(plugin: GpgEncryptPlugin): Promise<string | null> {
|
||||
// Return cached path if available and plugin hasn't changed
|
||||
if (cachedWorkingPath && cachedPlugin === plugin) {
|
||||
return cachedWorkingPath;
|
||||
}
|
||||
|
||||
// Get working path from settings
|
||||
cachedWorkingPath = await new Settings(plugin).getWorkingGpgPath();
|
||||
cachedPlugin = plugin;
|
||||
|
||||
return cachedWorkingPath;
|
||||
}
|
||||
|
||||
// Function to clear cached working path (useful when settings change)
|
||||
export function clearWorkingPathCache() {
|
||||
cachedWorkingPath = null;
|
||||
cachedPlugin = null;
|
||||
}
|
||||
|
||||
// Function to execute GPG command with some arguments and input text
|
||||
export default function spawnGPG(settings: GpgEncryptSettings, input: string | Buffer | null, args?: string[]): Promise<GpgResult> {
|
||||
export default async function spawnGPG(plugin: GpgEncryptPlugin, settings: GpgEncryptSettings, input: string | Buffer | null, args?: string[]): Promise<GpgResult> {
|
||||
// New Promise to resolve when GPG command is executed
|
||||
return new Promise((resolve) => {
|
||||
return new Promise(async (resolve) => {
|
||||
// Try to catch all exceptions
|
||||
try {
|
||||
// Get working GPG path
|
||||
const workingPath = await getWorkingGpgPath(plugin);
|
||||
if (!workingPath) {
|
||||
resolve({
|
||||
result: undefined,
|
||||
error: new Error("❌ No working GPG executable found in configured paths")
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// In case of args are null
|
||||
if (!args) {
|
||||
// Create an empty args array
|
||||
|
|
@ -45,7 +80,7 @@ export default function spawnGPG(settings: GpgEncryptSettings, input: string |
|
|||
if (settings.pgpAditionalCommands && settings.pgpAditionalCommandsBefore !== '') {
|
||||
command = settings.pgpAditionalCommandsBefore + " && ";
|
||||
}
|
||||
command += "\"" + settings.pgpExecPath + "\"";
|
||||
command += "\"" + workingPath + "\"";
|
||||
fullArgs.forEach(arg => {
|
||||
command += " " + arg;
|
||||
});
|
||||
|
|
@ -108,19 +143,19 @@ export default function spawnGPG(settings: GpgEncryptSettings, input: string |
|
|||
}
|
||||
|
||||
// Get list of all Public Key availables (routes to the selected library)
|
||||
export async function getListPublicKey(settings: GpgEncryptSettings): Promise<{ keyID: string; userID: string }[]> {
|
||||
export async function getListPublicKey(plugin: GpgEncryptPlugin, settings: GpgEncryptSettings): Promise<{ keyID: string; userID: string }[]> {
|
||||
// When openpgpjs is selected, use the OpenPGP.js backend
|
||||
if (settings.pgpLibrary === "openpgpjs") {
|
||||
return openpgpBackend.getListPublicKey(settings);
|
||||
}
|
||||
// Otherwise use the native GPG executable
|
||||
return nativeGetListPublicKey(settings);
|
||||
return nativeGetListPublicKey(plugin, settings);
|
||||
}
|
||||
|
||||
// Get list of all Public Key availables using the native GPG executable
|
||||
async function nativeGetListPublicKey(settings: GpgEncryptSettings): Promise<{ keyID: string; userID: string }[]> {
|
||||
async function nativeGetListPublicKey(plugin: GpgEncryptPlugin, settings: GpgEncryptSettings): Promise<{ keyID: string; userID: string }[]> {
|
||||
// Build the executable and args
|
||||
const gpgResult: GpgResult = await spawnGPG(settings, null, ["--logger-fd", "1", "--list-public-keys", "--with-colons"]);
|
||||
const gpgResult: GpgResult = await spawnGPG(plugin, settings, null, ["--logger-fd", "1", "--list-public-keys", "--with-colons"]);
|
||||
// Check if result are null
|
||||
if(!gpgResult.result) {
|
||||
// And return a null array
|
||||
|
|
@ -154,17 +189,17 @@ async function nativeGetListPublicKey(settings: GpgEncryptSettings): Promise<{ k
|
|||
}
|
||||
|
||||
// Function to encrypt a plainText with a list of GPG public keys ID (routes to the selected library)
|
||||
export async function gpgEncrypt(settings: GpgEncryptSettings, plainText:string, publicKeyIds: string[], signPublicKeyId: string, passphrase?: string | null): Promise<GpgResult> {
|
||||
export async function gpgEncrypt(plugin: GpgEncryptPlugin, settings: GpgEncryptSettings, plainText:string, publicKeyIds: string[], signPublicKeyId: string, passphrase?: string | null): Promise<GpgResult> {
|
||||
// When openpgpjs is selected, use the OpenPGP.js backend
|
||||
if (settings.pgpLibrary === "openpgpjs") {
|
||||
return openpgpBackend.gpgEncrypt(settings, plainText, publicKeyIds, signPublicKeyId, passphrase);
|
||||
}
|
||||
// Otherwise use the native GPG executable
|
||||
return nativeGpgEncrypt(settings, plainText, publicKeyIds, signPublicKeyId);
|
||||
return nativeGpgEncrypt(plugin, settings, plainText, publicKeyIds, signPublicKeyId);
|
||||
}
|
||||
|
||||
// Function to encrypt a plainText using the native GPG executable
|
||||
async function nativeGpgEncrypt(settings: GpgEncryptSettings, plainText:string, publicKeyIds: string[], signPublicKeyId: string): Promise<GpgResult> {
|
||||
async function nativeGpgEncrypt(plugin: GpgEncryptPlugin, settings: GpgEncryptSettings, plainText:string, publicKeyIds: string[], signPublicKeyId: string): Promise<GpgResult> {
|
||||
// Check if at least one public key is selected
|
||||
if (publicKeyIds.length <= 0) {
|
||||
// And return with error message
|
||||
|
|
@ -186,7 +221,7 @@ async function nativeGpgEncrypt(settings: GpgEncryptSettings, plainText:string,
|
|||
args = args.concat(["--recipient", publicKey]);
|
||||
});
|
||||
// Build the executable and args
|
||||
const gpgResult: GpgResult = await spawnGPG(settings, plainText, args);
|
||||
const gpgResult: GpgResult = await spawnGPG(plugin, settings, plainText, args);
|
||||
// Check if error is null
|
||||
if(gpgResult.error) {
|
||||
// Return with error message
|
||||
|
|
@ -209,21 +244,21 @@ async function nativeGpgEncrypt(settings: GpgEncryptSettings, plainText:string,
|
|||
|
||||
|
||||
// Function to decrypt an encrypted text with a private key (routes to the selected library)
|
||||
export async function gpgDecrypt(settings: GpgEncryptSettings, encryptedText:string, passphrase?: string | null): Promise<GpgResult> {
|
||||
export async function gpgDecrypt(plugin: GpgEncryptPlugin, settings: GpgEncryptSettings, encryptedText:string, passphrase?: string | null): Promise<GpgResult> {
|
||||
// When openpgpjs is selected, use the OpenPGP.js backend
|
||||
if (settings.pgpLibrary === "openpgpjs") {
|
||||
return openpgpBackend.gpgDecrypt(settings, encryptedText, passphrase);
|
||||
}
|
||||
// Otherwise use the native GPG executable
|
||||
return nativeGpgDecrypt(settings, encryptedText);
|
||||
return nativeGpgDecrypt(plugin, settings, encryptedText);
|
||||
}
|
||||
|
||||
// Function to decrypt an encrypted text using the native GPG executable
|
||||
async function nativeGpgDecrypt(settings: GpgEncryptSettings, encryptedText:string): Promise<GpgResult> {
|
||||
async function nativeGpgDecrypt(plugin: GpgEncryptPlugin, settings: GpgEncryptSettings, encryptedText:string): Promise<GpgResult> {
|
||||
// List of Args before publicKeyIds
|
||||
let args: string[] = ["--decrypt"].concat(AditionalArgs(settings));
|
||||
// Build the executable and args
|
||||
const gpgResult: GpgResult = await spawnGPG(settings, encryptedText, args);
|
||||
const gpgResult: GpgResult = await spawnGPG(plugin, settings, encryptedText, args);
|
||||
// Check if error is null
|
||||
if(gpgResult.error) {
|
||||
// Return with error message
|
||||
|
|
|
|||
|
|
@ -49,4 +49,10 @@
|
|||
width: 100%;
|
||||
font-family: monospace;
|
||||
font-size: 11px;
|
||||
}
|
||||
.gpg-paths-list {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.gpg-path-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
Loading…
Reference in a new issue