diff --git a/README.md b/README.md index e4ac6ab0..c8f182da 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,11 @@ ## Get started -- Online version: [https://privacy.sexy](https://privacy.sexy) - - or download latest desktop version for [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-Setup-0.9.2.exe), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-0.9.2.AppImage), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-0.9.2.dmg) -- 💡 Come back regularly to apply latest version for stronger privacy and security. +- Online version at [https://privacy.sexy](https://privacy.sexy) + - 💡 No need to run any compiled software on your computer. +- Alternatively download offline version for [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-Setup-0.9.2.exe), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-0.9.2.dmg) or [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-0.9.2.AppImage). + - 💡 Single click to execute your script. +- ❗ Come back regularly to apply latest version for stronger privacy and security. [![privacy.sexy application](img/screenshot.png)](https://privacy.sexy) diff --git a/src/infrastructure/Clipboard.ts b/src/infrastructure/Clipboard.ts index a871d4a6..35519c5e 100644 --- a/src/infrastructure/Clipboard.ts +++ b/src/infrastructure/Clipboard.ts @@ -1,4 +1,3 @@ - export class Clipboard { public static copyText(text: string): void { const el = document.createElement('textarea'); diff --git a/src/infrastructure/CodeRunner.ts b/src/infrastructure/CodeRunner.ts new file mode 100644 index 00000000..15fb86ec --- /dev/null +++ b/src/infrastructure/CodeRunner.ts @@ -0,0 +1,69 @@ +import { Environment } from '@/application/Environment/Environment'; +import os from 'os'; +import path from 'path'; +import fs from 'fs'; +import child_process from 'child_process'; +import { OperatingSystem } from '@/domain/OperatingSystem'; + +export async function runCodeAsync( + code: string, folderName: string, fileExtension: string, + node = getNodeJs(), environment = Environment.CurrentEnvironment): Promise { + const dir = node.path.join(node.os.tmpdir(), folderName); + await node.fs.promises.mkdir(dir, {recursive: true}); + const filePath = node.path.join(dir, `run.${fileExtension}`); + await node.fs.promises.writeFile(filePath, code); + await node.fs.promises.chmod(filePath, '755'); + const command = getExecuteCommand(filePath, environment); + node.child_process.exec(command); +} + +function getExecuteCommand(scriptPath: string, environment: Environment): string { + switch (environment.os) { + case OperatingSystem.macOS: + return `open -a Terminal.app ${scriptPath}`; + // Another option with graphical sudo would be + // `osascript -e "do shell script \\"${scriptPath}\\" with administrator privileges"` + // However it runs in background + case OperatingSystem.Windows: + return scriptPath; + default: + throw Error('undefined os'); + } +} + +function getNodeJs(): INodeJs { + return { os, path, fs, child_process }; +} + +export interface INodeJs { + os: INodeOs; + path: INodePath; + fs: INodeFs; + child_process: INodeChildProcess; +} + +export interface INodeOs { + tmpdir(): string; +} + +export interface INodePath { + join(...paths: string[]): string; +} + +export interface INodeChildProcess { + exec(command: string): void; +} + +export interface INodeFs { + readonly promises: INodeFsPromises; +} + +interface INodeFsPromisesMakeDirectoryOptions { + recursive?: boolean; +} + +interface INodeFsPromises { // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node/v13/fs.d.ts + chmod(path: string, mode: string | number): Promise; + mkdir(path: string, options: INodeFsPromisesMakeDirectoryOptions): Promise; + writeFile(path: string, data: string): Promise; +} diff --git a/src/presentation/Bootstrapping/Modules/IconBootstrapper.ts b/src/presentation/Bootstrapping/Modules/IconBootstrapper.ts index 4762bd5a..94833f50 100644 --- a/src/presentation/Bootstrapping/Modules/IconBootstrapper.ts +++ b/src/presentation/Bootstrapping/Modules/IconBootstrapper.ts @@ -7,8 +7,7 @@ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; import { faFolderOpen, faFolder, faSmile } from '@fortawesome/free-regular-svg-icons'; /** SOLID ICONS (PREFIX: fas (default)) */ import { faTimes, faFileDownload, faCopy, faSearch, faInfoCircle, faUserSecret, faDesktop, - faTag, faGlobe, faSave, faBatteryFull, faBatteryHalf } from '@fortawesome/free-solid-svg-icons'; - + faTag, faGlobe, faSave, faBatteryFull, faBatteryHalf, faPlay } from '@fortawesome/free-solid-svg-icons'; export class IconBootstrapper implements IVueBootstrapper { public bootstrap(vue: VueConstructor): void { @@ -24,6 +23,7 @@ export class IconBootstrapper implements IVueBootstrapper { faTimes, faFileDownload, faSave, faCopy, + faPlay, faSearch, faBatteryFull, faBatteryHalf, faInfoCircle); diff --git a/src/presentation/CodeButtons/MacOsInstructions.vue b/src/presentation/CodeButtons/MacOsInstructions.vue index 17fd1360..19ddb638 100644 --- a/src/presentation/CodeButtons/MacOsInstructions.vue +++ b/src/presentation/CodeButtons/MacOsInstructions.vue @@ -1,8 +1,8 @@ diff --git a/src/presentation/CodeButtons/TheCodeButtons.vue b/src/presentation/CodeButtons/TheCodeButtons.vue index f358c114..99f50aac 100644 --- a/src/presentation/CodeButtons/TheCodeButtons.vue +++ b/src/presentation/CodeButtons/TheCodeButtons.vue @@ -1,5 +1,11 @@