From 645e9e4a1416f1a6b12ae99b20e36819e779b2fa Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Wed, 28 Jun 2023 18:41:52 -0400 Subject: [PATCH 01/63] Empty ProjectManager with button to enter it --- frontend/src/App.svelte | 5 +++++ frontend/src/ProjectManagerView.svelte | 0 frontend/src/StartView.svelte | 7 +++++++ 3 files changed, 12 insertions(+) create mode 100644 frontend/src/ProjectManagerView.svelte diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 8183ceb9c..2a0997b97 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -52,10 +52,12 @@ import { keyEventToString, shortcuts } from "./keyboard.js"; import { writable } from "svelte/store"; + import ProjectManagerView from "./ProjectManagerView.svelte"; printConsoleArt(); let showRootResource = false, + showProjectManager = false, dataLenPromise = Promise.resolve([]), hexScrollY = writable({}), useAssemblyView = false, @@ -252,10 +254,13 @@ Answer by running riddle.answer('your answer here') from the console.`); {/if} +{:else if showProjectManager} + {:else} 0) { @@ -337,6 +342,7 @@ type="submit">Go! + {:else} No resources loaded yet. {/if} @@ -344,6 +350,7 @@

Failed to get any pre-existing root resources!

The back end server may be down.

{/await} + Date: Thu, 29 Jun 2023 15:58:15 -0400 Subject: [PATCH 02/63] Some arrangement --- frontend/src/App.svelte | 5 +- .../ProjectManagerBinariesView.svelte | 10 +++ .../ProjectManagerComponentsView.svelte} | 0 .../ProjectManagerReadmeView.svelte | 0 .../ProjectManagerScriptsView.svelte | 7 ++ .../ProjectManager/ProjectManagerView.svelte | 83 +++++++++++++++++++ 6 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 frontend/src/ProjectManager/ProjectManagerBinariesView.svelte rename frontend/src/{ProjectManagerView.svelte => ProjectManager/ProjectManagerComponentsView.svelte} (100%) create mode 100644 frontend/src/ProjectManager/ProjectManagerReadmeView.svelte create mode 100644 frontend/src/ProjectManager/ProjectManagerScriptsView.svelte create mode 100644 frontend/src/ProjectManager/ProjectManagerView.svelte diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 2a0997b97..cfc8c6c72 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -4,7 +4,7 @@ } .carousel { - margin-top: 1em; + margin-top: 0.1em; } .bottomleft { @@ -42,7 +42,6 @@ import MagnitudeView from "./MagnitudeView.svelte"; import Pane from "./Pane.svelte"; import ResourceTreeView from "./ResourceTreeView.svelte"; - import ScriptView from "./ScriptView.svelte"; import Split from "./Split.svelte"; import StartView from "./StartView.svelte"; import TextView from "./TextView.svelte"; @@ -52,7 +51,7 @@ import { keyEventToString, shortcuts } from "./keyboard.js"; import { writable } from "svelte/store"; - import ProjectManagerView from "./ProjectManagerView.svelte"; + import ProjectManagerView from "./ProjectManager/ProjectManagerView.svelte"; printConsoleArt(); diff --git a/frontend/src/ProjectManager/ProjectManagerBinariesView.svelte b/frontend/src/ProjectManager/ProjectManagerBinariesView.svelte new file mode 100644 index 000000000..df2d22fec --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerBinariesView.svelte @@ -0,0 +1,10 @@ + + + + + + + +
diff --git a/frontend/src/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerComponentsView.svelte similarity index 100% rename from frontend/src/ProjectManagerView.svelte rename to frontend/src/ProjectManager/ProjectManagerComponentsView.svelte diff --git a/frontend/src/ProjectManager/ProjectManagerReadmeView.svelte b/frontend/src/ProjectManager/ProjectManagerReadmeView.svelte new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/src/ProjectManager/ProjectManagerScriptsView.svelte b/frontend/src/ProjectManager/ProjectManagerScriptsView.svelte new file mode 100644 index 000000000..7e7b2a986 --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerScriptsView.svelte @@ -0,0 +1,7 @@ + + + + +
diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte new file mode 100644 index 000000000..d664c7590 --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -0,0 +1,83 @@ + + + + +
+
OFRAK Project Manager
+
+
+ Binaries +
+ +
+
+
+ Scripts +
+ +
+
+
+ Components +
+ +
+
+
+ Documentation +
+ +
+
+
+
From 8226e377dc0aa60cb9514ea4783a25ef4a1dcfdc Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 30 Jun 2023 11:20:31 -0400 Subject: [PATCH 03/63] Scrolling, unified project view --- frontend/src/App.svelte | 10 ++- .../ProjectManagerBinariesView.svelte | 10 --- .../ProjectManagerComponentsView.svelte | 0 .../ProjectManagerReadmeView.svelte | 0 .../ProjectManagerScriptsView.svelte | 7 -- .../ProjectManagerSelector.svelte | 57 ++++++++++++++ .../ProjectManager/ProjectManagerView.svelte | 74 ++++++++----------- frontend/src/StartView.svelte | 2 +- 8 files changed, 97 insertions(+), 63 deletions(-) delete mode 100644 frontend/src/ProjectManager/ProjectManagerBinariesView.svelte delete mode 100644 frontend/src/ProjectManager/ProjectManagerComponentsView.svelte delete mode 100644 frontend/src/ProjectManager/ProjectManagerReadmeView.svelte delete mode 100644 frontend/src/ProjectManager/ProjectManagerScriptsView.svelte create mode 100644 frontend/src/ProjectManager/ProjectManagerSelector.svelte diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index cfc8c6c72..e3b25ff09 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -70,6 +70,14 @@ modifierView, bottomLeftPane; + let testProject = { + name: "Test Project", + binaries: ["example_1", "example_2"], + scripts: ["example_1.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_3.py"], + components: [], + readme: "This is the Readme\nIt looks like this" + } + // TODO: Move to settings let riddleAnswered = JSON.parse(window.localStorage.getItem("riddleSolved")); if (riddleAnswered === null || riddleAnswered === undefined) { @@ -254,7 +262,7 @@ Answer by running riddle.answer('your answer here') from the console.`); {/if} {:else if showProjectManager} - + {:else} - - - - - - - -
diff --git a/frontend/src/ProjectManager/ProjectManagerComponentsView.svelte b/frontend/src/ProjectManager/ProjectManagerComponentsView.svelte deleted file mode 100644 index e69de29bb..000000000 diff --git a/frontend/src/ProjectManager/ProjectManagerReadmeView.svelte b/frontend/src/ProjectManager/ProjectManagerReadmeView.svelte deleted file mode 100644 index e69de29bb..000000000 diff --git a/frontend/src/ProjectManager/ProjectManagerScriptsView.svelte b/frontend/src/ProjectManager/ProjectManagerScriptsView.svelte deleted file mode 100644 index 7e7b2a986..000000000 --- a/frontend/src/ProjectManager/ProjectManagerScriptsView.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - - -
diff --git a/frontend/src/ProjectManager/ProjectManagerSelector.svelte b/frontend/src/ProjectManager/ProjectManagerSelector.svelte new file mode 100644 index 000000000..36859ab6b --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerSelector.svelte @@ -0,0 +1,57 @@ + + + + +
+
"{title}"
+
+
+ {#each projectElementOptions as projectOption} +
+ {projectOption} +
+ {/each} +
+
+
diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index d664c7590..fd3f1fc19 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -23,61 +23,47 @@ justify-content: space-around; flex-direction: row; width: 100%; - height: 100%; - } - - .view { - padding-left: 1em; - text-align: center; - font-size: x-large; - font-weight: bold; - text-transform: uppercase; - width: 100%; - height: 100%; + height: 70%; } - .box { - outline: solid 1px var(--main-fg-color); + .options-box{ + display: flex; + outline: solid 2px var(--main-fg-color); border-radius: 5%; - padding-top: 1em; width: 100%; - height: 100%; - } + height: 30%; + font-size: x-large; + overflow: auto; + overflow-y: hidden; + margin-top: 1em; +} +.options{ + display: flex; + flex-direction: column; + width: 100%; + height: 30100%; + overflow:auto; + overflow-y: scroll; +}
OFRAK Project Manager
-
- Binaries -
- -
-
-
- Scripts -
- -
-
-
- Components -
- -
-
-
- Documentation -
- -
-
+ + + +
+
+
+
+
diff --git a/frontend/src/StartView.svelte b/frontend/src/StartView.svelte index 96421d108..ece125bfa 100644 --- a/frontend/src/StartView.svelte +++ b/frontend/src/StartView.svelte @@ -342,7 +342,6 @@ type="submit">Go! - {:else} No resources loaded yet. {/if} @@ -350,6 +349,7 @@

Failed to get any pre-existing root resources!

The back end server may be down.

{/await} + Date: Fri, 30 Jun 2023 13:05:41 -0400 Subject: [PATCH 04/63] initial adventure/project implementation --- ofrak_core/ofrak/adventure/__init__.py | 0 ofrak_core/ofrak/adventure/adventure.py | 110 ++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 ofrak_core/ofrak/adventure/__init__.py create mode 100644 ofrak_core/ofrak/adventure/adventure.py diff --git a/ofrak_core/ofrak/adventure/__init__.py b/ofrak_core/ofrak/adventure/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ofrak_core/ofrak/adventure/adventure.py b/ofrak_core/ofrak/adventure/adventure.py new file mode 100644 index 000000000..50b6f5d29 --- /dev/null +++ b/ofrak_core/ofrak/adventure/adventure.py @@ -0,0 +1,110 @@ +import json +import os.path +from dataclasses import dataclass +from typing import Dict, Optional, Set + +from ofrak.core.run_script_modifier import RunScriptModifier, RunScriptModifierConfig + +from ofrak.resource import Resource + +from ofrak.ofrak_context import OFRAKContext + + +class OfrakAdventure: + """ + An OFRAK 'project' + + """ + + def __init__(self): + self.path: str = "" + self.name: str = "" + self.adventure_id: bytes = b"" + self.binaries: Dict[str, _OfrakAdventureBinary] = dict() + self.scripts: Set[str] = set() + + @staticmethod + def init_from_path(path: str) -> "OfrakAdventure": + """ + + Assume path points to a directory with the following structure: + (top-level directory) + |-metadata.json + |-README.md + |--binaries + | |-binary1.bin + | | ... + |--scripts + |-script1.py + | ... + + :param path: + :return: + """ + if not os.path.exists(path): + raise ValueError(f"{path} does not exist") + if not os.path.isdir(path): + raise ValueError(f"{path} is not a directory") + + metadata_path = os.path.join(path, "metadata.json") + readme_path = os.path.join(path, "README.md") + binaries_path = os.path.join(path, "binaries") + scripts_path = os.path.join(path, "scripts") + + if not all( + [ + os.path.exists(metadata_path), + os.path.exists(readme_path), + os.path.exists(binaries_path), + os.path.isdir(binaries_path), + os.path.exists(scripts_path), + os.path.isdir(scripts_path), + ] + ): + raise ValueError(f"{path} has invalid structure to be an Adventure") + + with open(metadata_path) as f: + raw_metadata = json.load(f) + + scripts = raw_metadata["scripts"] + binaries = { + info["name"]: _OfrakAdventureBinary( + set(info["associated_scripts"]), info.get("init_script") + ) + for info in raw_metadata["binaries"] + } + name = raw_metadata["name"] + adventure_id = raw_metadata["id"] + + adventure = OfrakAdventure() + adventure.scripts = scripts + adventure.binaries = binaries + adventure.name = name + adventure.adventure_id = adventure_id + + return adventure + + async def init_adventure_binary( + self, binary_name: str, ofrak_context: OFRAKContext + ) -> Resource: + if binary_name not in self.binaries: + raise ValueError(f"{binary_name} is not a binary in Adventure {self.name}") + + binary_metadata = self.binaries[binary_name] + + resource = await ofrak_context.create_root_resource_from_file( + os.path.join(self.path, "binaries", binary_name) + ) + + if binary_metadata.init_script: + with open(os.path.join(self.path, "scripts", binary_metadata.init_script)) as f: + code = f.read() + await resource.run(RunScriptModifier, RunScriptModifierConfig(code)) + + return resource + + +@dataclass +class _OfrakAdventureBinary: + associated_scripts: Set[str] + init_script: Optional[str] From e5f516d3a96343f997d749e915c0aecc084dfea3 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 30 Jun 2023 17:12:42 -0400 Subject: [PATCH 05/63] Exclusive checkboxes with focus --- frontend/src/App.svelte | 61 +++++++++++++++-- frontend/src/Checkbox.svelte | 12 +++- .../ProjectManagerCheckbox.svelte | 15 +++++ .../ProjectManagerOptions.svelte | 30 +++++++++ .../ProjectManagerSelector.svelte | 52 +++++++------- .../ProjectManager/ProjectManagerView.svelte | 67 +++++++++---------- 6 files changed, 171 insertions(+), 66 deletions(-) create mode 100644 frontend/src/ProjectManager/ProjectManagerCheckbox.svelte create mode 100644 frontend/src/ProjectManager/ProjectManagerOptions.svelte diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index e3b25ff09..3e561798b 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -73,10 +73,63 @@ let testProject = { name: "Test Project", binaries: ["example_1", "example_2"], - scripts: ["example_1.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_2.py", "example_3.py"], + scripts: [ + "example_1.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_2.py", + "example_3.py", + ], components: [], - readme: "This is the Readme\nIt looks like this" - } + readme: "This is the Readme\nIt looks like this", + }; // TODO: Move to settings let riddleAnswered = JSON.parse(window.localStorage.getItem("riddleSolved")); @@ -262,7 +315,7 @@ Answer by running riddle.answer('your answer here') from the console.`); {/if} {:else if showProjectManager} - + {:else} diff --git a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte new file mode 100644 index 000000000..7ac04db5a --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte @@ -0,0 +1,15 @@ + + +
+ {option} +
diff --git a/frontend/src/ProjectManager/ProjectManagerOptions.svelte b/frontend/src/ProjectManager/ProjectManagerOptions.svelte new file mode 100644 index 000000000..ba24cc129 --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerOptions.svelte @@ -0,0 +1,30 @@ + + + + +
+
+
+ "{focus}" +
+
+
diff --git a/frontend/src/ProjectManager/ProjectManagerSelector.svelte b/frontend/src/ProjectManager/ProjectManagerSelector.svelte index 36859ab6b..28d8a701e 100644 --- a/frontend/src/ProjectManager/ProjectManagerSelector.svelte +++ b/frontend/src/ProjectManager/ProjectManagerSelector.svelte @@ -1,57 +1,59 @@
-
"{title}"
-
-
- {#each projectElementOptions as projectOption} -
- {projectOption} -
- {/each} +
"{title}"
+
+
+ {#each projectElementOptions as projectOption} +
+
+ {/each}
+
diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index fd3f1fc19..4aeb80831 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -1,7 +1,7 @@
OFRAK Project Manager
-
- - - +
+ + +
-
-
- +
From 8cefac5dd798cb5f664cf1bd7dfe24db97213b0b Mon Sep 17 00:00:00 2001 From: edward Date: Fri, 30 Jun 2023 17:54:07 -0400 Subject: [PATCH 06/63] iterate a bit on adventure data structure --- ofrak_core/ofrak/adventure/adventure.py | 86 +++++++++++++++++-------- 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/ofrak_core/ofrak/adventure/adventure.py b/ofrak_core/ofrak/adventure/adventure.py index 50b6f5d29..9f3599624 100644 --- a/ofrak_core/ofrak/adventure/adventure.py +++ b/ofrak_core/ofrak/adventure/adventure.py @@ -1,5 +1,7 @@ +import binascii import json import os.path +import uuid from dataclasses import dataclass from typing import Dict, Optional, Set @@ -10,18 +12,42 @@ from ofrak.ofrak_context import OFRAKContext +@dataclass +class _OfrakAdventureBinary: + associated_scripts: Set[str] + init_script: Optional[str] + contents: bytes + + class OfrakAdventure: """ An OFRAK 'project' """ - def __init__(self): - self.path: str = "" - self.name: str = "" - self.adventure_id: bytes = b"" - self.binaries: Dict[str, _OfrakAdventureBinary] = dict() - self.scripts: Set[str] = set() + def __init__( + self, + path: str, + name: str, + adventure_id: bytes, + binaries: Dict[str, _OfrakAdventureBinary], + scripts: Dict[str, str], + ): + self.path: str = path + self.name: str = name + self.adventure_id: bytes = adventure_id + self.binaries: Dict[str, _OfrakAdventureBinary] = binaries + self.scripts: Dict[str, str] = scripts + + @staticmethod + def create(name: str, path: str) -> "OfrakAdventure": + return OfrakAdventure( + path, + name, + uuid.uuid4().bytes, + {}, + {}, + ) @staticmethod def init_from_path(path: str) -> "OfrakAdventure": @@ -66,21 +92,30 @@ def init_from_path(path: str) -> "OfrakAdventure": with open(metadata_path) as f: raw_metadata = json.load(f) - scripts = raw_metadata["scripts"] - binaries = { - info["name"]: _OfrakAdventureBinary( - set(info["associated_scripts"]), info.get("init_script") + scripts = {} + for script_name in raw_metadata["scripts"]: + with open(os.path.join(path, "scripts", script_name)) as f: + contents = f.read() + scripts[script_name] = contents + + binaries = {} + + for info in raw_metadata["binaries"]: + with open(os.path.join(path, "binaries", info["name"]), "rb") as f: + contents = f.read() + binaries[info["name"]] = _OfrakAdventureBinary( + set(info["associated_scripts"]), info.get("init_script"), contents ) - for info in raw_metadata["binaries"] - } name = raw_metadata["name"] - adventure_id = raw_metadata["id"] - - adventure = OfrakAdventure() - adventure.scripts = scripts - adventure.binaries = binaries - adventure.name = name - adventure.adventure_id = adventure_id + adventure_id = binascii.unhexlify(raw_metadata["id"]) + + adventure = OfrakAdventure( + path, + name, + adventure_id, + binaries, + scripts, + ) return adventure @@ -97,14 +132,11 @@ async def init_adventure_binary( ) if binary_metadata.init_script: - with open(os.path.join(self.path, "scripts", binary_metadata.init_script)) as f: - code = f.read() + if binary_metadata.init_script not in self.scripts: + raise ValueError( + f"Init script {binary_metadata.init_script} (for binary {binary_name}) not found in project!" + ) + code = self.scripts[binary_metadata.init_script] await resource.run(RunScriptModifier, RunScriptModifierConfig(code)) return resource - - -@dataclass -class _OfrakAdventureBinary: - associated_scripts: Set[str] - init_script: Optional[str] From bded40e8f619cbd5121da775df2bc6a5773212c6 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 30 Jun 2023 18:05:45 -0400 Subject: [PATCH 07/63] Do checkbox better --- frontend/src/Checkbox.svelte | 12 +++--------- .../src/ProjectManager/ProjectManagerCheckbox.svelte | 11 ++++++----- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/frontend/src/Checkbox.svelte b/frontend/src/Checkbox.svelte index 330b2a840..8d6eb1e9e 100644 --- a/frontend/src/Checkbox.svelte +++ b/frontend/src/Checkbox.svelte @@ -57,25 +57,19 @@ export let checked, value, leftbox = false, - nomargin = false, - onselect = null; + nomargin = false; $: value = checked; diff --git a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte index 7ac04db5a..e45bb6153 100644 --- a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte +++ b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte @@ -1,15 +1,16 @@
- {option}
From 4c6357a7b36060f0d81a070204db4ba2c0f002fc Mon Sep 17 00:00:00 2001 From: edward Date: Wed, 5 Jul 2023 18:31:48 -0400 Subject: [PATCH 08/63] tests, rename to projects, more implementation --- ofrak_core/ofrak/adventure/adventure.py | 142 ------------- .../ofrak/{adventure => project}/__init__.py | 0 ofrak_core/ofrak/project/project.py | 195 ++++++++++++++++++ .../ofrak_project/test_ofrak_adventure.py | 27 +++ .../test_projects/project1/README.md | 0 .../project1/binaries/hello_world.bin | Bin 0 -> 16616 bytes .../test_projects/project1/metadata.json | 14 ++ .../project1/scripts/script_a.py | 9 + 8 files changed, 245 insertions(+), 142 deletions(-) delete mode 100644 ofrak_core/ofrak/adventure/adventure.py rename ofrak_core/ofrak/{adventure => project}/__init__.py (100%) create mode 100644 ofrak_core/ofrak/project/project.py create mode 100644 ofrak_core/test_ofrak/unit/ofrak_project/test_ofrak_adventure.py create mode 100644 ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/README.md create mode 100755 ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/binaries/hello_world.bin create mode 100644 ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/metadata.json create mode 100644 ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/scripts/script_a.py diff --git a/ofrak_core/ofrak/adventure/adventure.py b/ofrak_core/ofrak/adventure/adventure.py deleted file mode 100644 index 9f3599624..000000000 --- a/ofrak_core/ofrak/adventure/adventure.py +++ /dev/null @@ -1,142 +0,0 @@ -import binascii -import json -import os.path -import uuid -from dataclasses import dataclass -from typing import Dict, Optional, Set - -from ofrak.core.run_script_modifier import RunScriptModifier, RunScriptModifierConfig - -from ofrak.resource import Resource - -from ofrak.ofrak_context import OFRAKContext - - -@dataclass -class _OfrakAdventureBinary: - associated_scripts: Set[str] - init_script: Optional[str] - contents: bytes - - -class OfrakAdventure: - """ - An OFRAK 'project' - - """ - - def __init__( - self, - path: str, - name: str, - adventure_id: bytes, - binaries: Dict[str, _OfrakAdventureBinary], - scripts: Dict[str, str], - ): - self.path: str = path - self.name: str = name - self.adventure_id: bytes = adventure_id - self.binaries: Dict[str, _OfrakAdventureBinary] = binaries - self.scripts: Dict[str, str] = scripts - - @staticmethod - def create(name: str, path: str) -> "OfrakAdventure": - return OfrakAdventure( - path, - name, - uuid.uuid4().bytes, - {}, - {}, - ) - - @staticmethod - def init_from_path(path: str) -> "OfrakAdventure": - """ - - Assume path points to a directory with the following structure: - (top-level directory) - |-metadata.json - |-README.md - |--binaries - | |-binary1.bin - | | ... - |--scripts - |-script1.py - | ... - - :param path: - :return: - """ - if not os.path.exists(path): - raise ValueError(f"{path} does not exist") - if not os.path.isdir(path): - raise ValueError(f"{path} is not a directory") - - metadata_path = os.path.join(path, "metadata.json") - readme_path = os.path.join(path, "README.md") - binaries_path = os.path.join(path, "binaries") - scripts_path = os.path.join(path, "scripts") - - if not all( - [ - os.path.exists(metadata_path), - os.path.exists(readme_path), - os.path.exists(binaries_path), - os.path.isdir(binaries_path), - os.path.exists(scripts_path), - os.path.isdir(scripts_path), - ] - ): - raise ValueError(f"{path} has invalid structure to be an Adventure") - - with open(metadata_path) as f: - raw_metadata = json.load(f) - - scripts = {} - for script_name in raw_metadata["scripts"]: - with open(os.path.join(path, "scripts", script_name)) as f: - contents = f.read() - scripts[script_name] = contents - - binaries = {} - - for info in raw_metadata["binaries"]: - with open(os.path.join(path, "binaries", info["name"]), "rb") as f: - contents = f.read() - binaries[info["name"]] = _OfrakAdventureBinary( - set(info["associated_scripts"]), info.get("init_script"), contents - ) - name = raw_metadata["name"] - adventure_id = binascii.unhexlify(raw_metadata["id"]) - - adventure = OfrakAdventure( - path, - name, - adventure_id, - binaries, - scripts, - ) - - return adventure - - async def init_adventure_binary( - self, binary_name: str, ofrak_context: OFRAKContext - ) -> Resource: - if binary_name not in self.binaries: - raise ValueError(f"{binary_name} is not a binary in Adventure {self.name}") - - binary_metadata = self.binaries[binary_name] - - resource = await ofrak_context.create_root_resource_from_file( - os.path.join(self.path, "binaries", binary_name) - ) - - if binary_metadata.init_script: - if binary_metadata.init_script not in self.scripts: - raise ValueError( - f"Init script {binary_metadata.init_script} (for binary {binary_name}) not found in project!" - ) - code = self.scripts[binary_metadata.init_script] - await resource.run(RunScriptModifier, RunScriptModifierConfig(code)) - - return resource diff --git a/ofrak_core/ofrak/adventure/__init__.py b/ofrak_core/ofrak/project/__init__.py similarity index 100% rename from ofrak_core/ofrak/adventure/__init__.py rename to ofrak_core/ofrak/project/__init__.py diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py new file mode 100644 index 000000000..013a17ff0 --- /dev/null +++ b/ofrak_core/ofrak/project/project.py @@ -0,0 +1,195 @@ +import binascii +import json +import os.path +import uuid +from dataclasses import dataclass +from typing import Dict, List, Optional + +from ofrak.core.run_script_modifier import RunScriptModifier, RunScriptModifierConfig + +from ofrak.resource import Resource + +from ofrak.ofrak_context import OFRAKContext + + +@dataclass +class _OfrakProjectBinary: + associated_scripts: List[str] + init_script: Optional[str] + + +class OfrakProject: + """ + An OFRAK 'project' + + """ + + def __init__( + self, + path: str, + name: str, + project_id: bytes, + binaries: Dict[str, _OfrakProjectBinary], + scripts: List[str], + ): + self.path: str = path + self.name: str = name + self.project_id: bytes = project_id + self.binaries: Dict[str, _OfrakProjectBinary] = binaries + self.scripts: List[str] = scripts + + @property + def metadata_path(self): + return os.path.join(self.path, "metadata.json") + + @property + def readme_path(self): + return os.path.join(self.path, "README.md") + + @staticmethod + def create(name: str, path: str) -> "OfrakProject": + + new_project = OfrakProject( + path, + name, + uuid.uuid4().bytes, + {}, + [], + ) + + os.makedirs(os.path.join(path, "scripts"), exist_ok=True) + os.makedirs(os.path.join(path, "binaries"), exist_ok=True) + + with open(new_project.metadata_path, "w+") as f: + pass + with open(new_project.readme_path, "w+") as f: + pass + + return new_project + + @staticmethod + def init_from_path(path: str) -> "OfrakProject": + """ + + Assume path points to a directory with the following structure: + (top-level directory) + |-metadata.json + |-README.md + |--binaries + | |-binary1.bin + | | ... + |--scripts + |-script1.py + | ... + + :param path: + :return: + """ + if not os.path.exists(path): + raise ValueError(f"{path} does not exist") + if not os.path.isdir(path): + raise ValueError(f"{path} is not a directory") + + metadata_path = os.path.join(path, "metadata.json") + readme_path = os.path.join(path, "README.md") + binaries_path = os.path.join(path, "binaries") + scripts_path = os.path.join(path, "scripts") + + if not all( + [ + os.path.exists(metadata_path), + os.path.exists(readme_path), + os.path.exists(binaries_path), + os.path.isdir(binaries_path), + os.path.exists(scripts_path), + os.path.isdir(scripts_path), + ] + ): + raise ValueError(f"{path} has invalid structure to be an Project") + + with open(metadata_path) as f: + raw_metadata = json.load(f) + + scripts = [script_name for script_name in raw_metadata["scripts"]] + + binaries = {} + + for info in raw_metadata["binaries"]: + binaries[info["name"]] = _OfrakProjectBinary( + info["associated_scripts"], info.get("init_script") + ) + name = raw_metadata["name"] + project_id = binascii.unhexlify(raw_metadata["id"]) + + project = OfrakProject( + path, + name, + project_id, + binaries, + scripts, + ) + + return project + + def script_path(self, script_name, check: bool = True) -> str: + if check and script_name not in self.scripts: + raise ValueError(f"Script {script_name} is not a script in this Project") + p = os.path.join(self.path, "scripts", script_name) + if check and not os.path.exists(p): + raise ValueError( + f"Script {script_name} is known to this Project but is not on disk " + f"(looked at {p})" + ) + return p + + def binary_path(self, binary_name, check: bool = True) -> str: + if check and binary_name not in self.binaries: + raise ValueError(f"Binary {binary_name} is not a binary in this Project") + p = os.path.join(self.path, "binaries", binary_name) + if check and not os.path.exists(p): + raise ValueError( + f"Binary {binary_name} is known to this Project but is not on disk " + f"(looked at {p})" + ) + return p + + async def init_adventure_binary( + self, binary_name: str, ofrak_context: OFRAKContext + ) -> Resource: + binary_metadata = self.binaries[binary_name] + resource = await ofrak_context.create_root_resource_from_file(self.binary_path(binary_name)) + + if binary_metadata.init_script: + with open(self.script_path(binary_metadata.init_script)) as f: + code = f.read() + await resource.run(RunScriptModifier, RunScriptModifierConfig(code)) + + return resource + + def write_metadata_to_disk(self): + metadata = { + "name": self.name, + "id": self.project_id.hex(), + "scripts": [script for script in self.scripts], + "binaries": [ + { + "name": binary_name, + "init_script": binary_info.init_script, + "associated_scripts": binary_info.associated_scripts, + } + for binary_name, binary_info in self.binaries.items() + ], + } + with open(os.path.join(self.path, "metadata.json"), "w") as f: + json.dump(metadata, f) + + def add_binary(self, name: str, contents: bytes): + self.binaries[name] = _OfrakProjectBinary([], None) + os.makedirs(os.path.join(self.path, "binaries"), exist_ok=True) + with open(self.binary_path(name, check=False), "wb+") as f: + f.write(contents) + + def add_script(self, name: str, script_contents: str): + self.scripts.append(name) + with open(self.script_path(name, check=False), "w+") as f: + f.write(script_contents) diff --git a/ofrak_core/test_ofrak/unit/ofrak_project/test_ofrak_adventure.py b/ofrak_core/test_ofrak/unit/ofrak_project/test_ofrak_adventure.py new file mode 100644 index 000000000..73f60e07f --- /dev/null +++ b/ofrak_core/test_ofrak/unit/ofrak_project/test_ofrak_adventure.py @@ -0,0 +1,27 @@ +import os.path + +from ofrak import OFRAKContext +from ofrak.project.project import OfrakProject + +TEST_PROJECT_PATH = os.path.join(os.path.dirname(__file__), "test_projects", "project1") + + +async def test_load_project(ofrak_context: OFRAKContext): + adventure = OfrakProject.init_from_path(TEST_PROJECT_PATH) + initialized_resource = await adventure.init_adventure_binary("hello_world.bin", ofrak_context) + assert len(list(await initialized_resource.get_children())) > 0 + + +async def test_create_new_project(ofrak_context, tmpdir): + new_project = OfrakProject.create( + "New Test Project", + tmpdir, + ) + + new_project.add_binary("tiny_binary", b"just a basic binary, nothing special") + + new_project.write_metadata_to_disk() + + new_project2 = OfrakProject.init_from_path(tmpdir) + assert new_project.project_id == new_project2.project_id + assert new_project.binaries == new_project2.binaries diff --git a/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/README.md b/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/binaries/hello_world.bin b/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/binaries/hello_world.bin new file mode 100755 index 0000000000000000000000000000000000000000..d0340b0a22968810d3a1a0fd4ac9a8083d66e965 GIT binary patch literal 16616 zcmeHOU2Ggz6~60@W2Z^hPMT0R0WvA6NNBuS=f^m0-0b=%86zh#sojP)$#m^qdpF%5 zvpd_`0n{L;MXTbHha&L+FH}gaR3r*7fIv-%RjEQn$pa8k6-<>1CxYSttx{;SoHKL2 z^~`vU5D)ZajG1mVXl``r}3o8kwYmHL3lC+CDeGZN2> zJ)~m-vMtlV+h&5x>on#T<33xgfbjb~`Efh{TSD58N_|V^rA68glne=e`?j4y# zYbKp5O|(vQw70hJ4j1#`omRisQA2o69Xvdwe)_Y_*z3Rj-9NKab>F^J8h-fN?xWx1 zc5@pz9@{XnJ<^Z7v)=C4SJ_0$N?lI=Dr*Ur_}Wi$t%i={t*s%yV+r{qB-d)#pISoB z<9}BTdo^B2=gd)M7$XyLV>F$MXVRyW#8MtdjG`GYm_|09&MD?OjqU1Se_vO(u`|3g zyhj;*gNKYnvXC507tLg0@KARqpGywLhcg^wESt|s48u09X~@m0lMExz0UCjAB*%Ox zZAhGqUI#5vORX9R&}UoXfBPBmGvH^y&w!r+KLdUS{0#UR_~oj2<$m-MNb#*5X4Rrb6^s>APuDluFE}SbuG{LUi{Ji61=&hqk};l`o&v z%WvsZSLX)?`={$4rscOjz54HDp-*>SAgHV#C7*vZZR)W^FA}3q*MFB`?@e<(HRpaV zQ*%~SW}7yh;n)`iDa52@zo)>k?Ur7i*Dt)YU%zlOs0UuvFW)lPQGoRlps_MLYSjb( zGo5=$rAj-7^r_DG!c^4DZ=0+1XF4~Ke6E#xG?${USL@dhA2mcO!TC3(Om9vD~311@IM>t5h`9`HOL)cGvmGC9P?ewJ2 z?_rq&r;n<@L~~%{s)ojMfre(5^Sk`nzg8;uuz^r*d!@FJp6$<&y~eho<^!RY&o!-l zqVbH{zu~^m?Al_z_GJGa`b>}=-T|^X`yQvy5ViNyEQp1gpRVg(y?mG&L@fJ!nLdw_ z{sf`w3N?SDt}oQ`Y_K<^O)u*WZT)(EPbl*Aay`^B)o?HrJr(MRg(9)g)~=A&6>1^- zu27@(9&?7=Cnyee-zPr$}jO@R>Q+Vvp+$cPrxi$!oeVY9I#RUDkw<>vymra-0OL;|j?4gVZf1Bm4 z)LFrmf-QpU1p(rwRMeJW?}-p)wMD$q+E(cYM(rU`@RFRr;{0c3^;_Gjjx=~q>*d_kGt5YF$#*=5-$6?8T z;E`_@Irg2~QIz^D6#{CZJ-FVxE&1a7oRT>BJw}|zE&IiJ{wB$5wSTF8J#WQXs|LBj z9;y}RWy|LFMdSDjk_Xh{ar~v&d*{RNE&1Ykb;F9YcznN49jK#IMBeM7f#hpxT+YjV zhx^HN2Ng7{C;T}ts_bW2YpfO2V~yfBf1}v zobA1Nctz~@NPO!*Qu3K0Ik(eme~ILpqdpX`ll(3)P8=ziMYA+I8Xi##=SU1QYmD$o zk|LcVN#u>OOnx|?F%o9JP&DGD2{n?>j%Si)G7*l{w&0^IX(L`J#3zkp&MZu-(Ly|% zG!mt3c9L8ioI#eR%QVG*bQ@3bAKla}!#Hp>cBt3rJ=|l^F&4LZLK!_@I2=3F*X`C= zCuc}RXNZhmT_Wf`N0o7~|43J?-#BvMzyrO5#$c?gzn7z0=WRxcC9C28`CLsh5jW#< za3|_IjpIGF>%Ex`e$kj3xE>336_%NYaurY-aolZ&?##K0%HPDqc*faAGn?@oY2;w&w9Ph^z0avx5nWCo=Y6a<{@YELEG17)fqo=uNX^?8#cQ{#9H!<0!CrpcV8 zIqJMB{^v5Ux9L)&-%OjZega~>Eo#daWyVj@hu669$2tqRg^e79-yw+Fso?a-dJL$+ zP|)k&L-O}%&5Qc6ZUdrzJQra7jj)HQKzEC3`?0N3FBMTg)`7sY z;t$|lJLx1byrzdg){8)1H!z|7ume6uI(|j~k98$bV`n07`)#RGr>Vd>g+JDx!1H2= z`n~<<{;_|T*x|Vch&-`BKO1@dpCuXR1kY)F%d$w2eVoK~IjKyH(_a(6Dmsm+>g>F+(SyU%G%WpDkjc>D)6+X2|<=|A#jTPgJ#6?l&GHN=GVAI|Z5?ZE?o zO+HQZfj^!b=H;9->^L?Pc;FvN#&Zw;c)q|n=~-z%<|q6xj^83*Hi18$L$2%~A<1N;8@~ literal 0 HcmV?d00001 diff --git a/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/metadata.json b/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/metadata.json new file mode 100644 index 000000000..13f8cbdaa --- /dev/null +++ b/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/metadata.json @@ -0,0 +1,14 @@ +{ + "name": "Test project A", + "id": "38f71e0209a6cc", + "scripts": [ + "script_a.py" + ], + "binaries": [ + { + "name": "hello_world.bin", + "associated_scripts": ["script_a.py"], + "init_script": "script_a.py" + } + ] +} diff --git a/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/scripts/script_a.py b/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/scripts/script_a.py new file mode 100644 index 000000000..91a546b8e --- /dev/null +++ b/ofrak_core/test_ofrak/unit/ofrak_project/test_projects/project1/scripts/script_a.py @@ -0,0 +1,9 @@ +from ofrak import * +from ofrak.core import * + + +async def main(ofrak_context: OFRAKContext, root_resource: Optional[Resource]): + if root_resource is None: + raise ValueError() + + await root_resource.unpack() From 9b2318fe6bbf2d37d36336804276e5986157cec8 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 7 Jul 2023 16:34:30 -0400 Subject: [PATCH 09/63] Mostly focusing elemetns and css --- frontend/src/App.svelte | 5 ++-- .../ProjectManagerCheckbox.svelte | 20 +++++++++---- .../ProjectManagerFocusableLabel.svelte | 17 +++++++++++ .../ProjectManagerOptions.svelte | 8 ++++-- .../ProjectManagerSelector.svelte | 18 ++++++------ .../ProjectManager/ProjectManagerView.svelte | 28 +++++++++++++++++-- 6 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 3e561798b..41865e333 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -70,7 +70,7 @@ modifierView, bottomLeftPane; - let testProject = { + let project = { name: "Test Project", binaries: ["example_1", "example_2"], scripts: [ @@ -315,7 +315,7 @@ Answer by running riddle.answer('your answer here') from the console.`);
{/if} {:else if showProjectManager} - + {:else} {/if} diff --git a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte index e45bb6153..e7bfde9c9 100644 --- a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte +++ b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte @@ -1,16 +1,26 @@ + + -
- {option} + {option}
diff --git a/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte b/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte new file mode 100644 index 000000000..601f7b1b7 --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte @@ -0,0 +1,17 @@ + + + + + diff --git a/frontend/src/ProjectManager/ProjectManagerOptions.svelte b/frontend/src/ProjectManager/ProjectManagerOptions.svelte index ba24cc129..8e19bfea7 100644 --- a/frontend/src/ProjectManager/ProjectManagerOptions.svelte +++ b/frontend/src/ProjectManager/ProjectManagerOptions.svelte @@ -2,18 +2,18 @@ .hbox { width: 100%; height: 100%; - padding: 2em; } .options-box { display: flex; outline: solid 2px var(--main-fg-color); - border-radius: 5%; + border-radius: 1em; height: 95%; font-size: x-large; } .options { display: flex; flex-direction: column; + margin: 1em; } @@ -24,7 +24,9 @@
- "{focus}" + {#if focus} + {focus} + {/if}
diff --git a/frontend/src/ProjectManager/ProjectManagerSelector.svelte b/frontend/src/ProjectManager/ProjectManagerSelector.svelte index 28d8a701e..487436de8 100644 --- a/frontend/src/ProjectManager/ProjectManagerSelector.svelte +++ b/frontend/src/ProjectManager/ProjectManagerSelector.svelte @@ -14,7 +14,7 @@ .content-box { display: flex; outline: solid 2px var(--main-fg-color); - border-radius: 5%; + border-radius: 1em; width: 100%; height: 95%; font-size: x-large; @@ -28,21 +28,23 @@ overflow: auto; overflow-y: scroll; } - .element { - margin-block: 1em; - margin-left: 1em; - margin-top: 1em; - }
-
"{title}"
+
+ +
{#each projectElementOptions as projectOption} diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 4aeb80831..bc2514607 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -1,4 +1,11 @@ @@ -39,6 +53,8 @@ export let project; let focus, selectedBinary, selectedScript; + + function openProject() {}
@@ -46,18 +62,21 @@
@@ -65,4 +84,7 @@
+
+ +
From 836d432bab4b4fc7f0d7ac0e96e1fbc179cbdc2e Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 11 Jul 2023 12:45:32 -0400 Subject: [PATCH 10/63] Use panes and some other small changes --- frontend/src/App.svelte | 2 +- .../ProjectManagerFocusableLabel.svelte | 2 +- .../ProjectManagerOptions.svelte | 20 ++--- .../ProjectManagerSelector.svelte | 34 +++----- .../ProjectManager/ProjectManagerView.svelte | 84 +++++++------------ 5 files changed, 50 insertions(+), 92 deletions(-) diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 41865e333..90b3069c7 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -4,7 +4,7 @@ } .carousel { - margin-top: 0.1em; + margin-top: 1em; } .bottomleft { diff --git a/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte b/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte index 601f7b1b7..7c808f717 100644 --- a/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte +++ b/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte @@ -1,6 +1,6 @@ @@ -22,11 +16,11 @@
-
-
- {#if focus} - {focus} - {/if} -
+
+ {#if focus} + {focus} + {:else} + Click anywhere to see its options. + {/if}
diff --git a/frontend/src/ProjectManager/ProjectManagerSelector.svelte b/frontend/src/ProjectManager/ProjectManagerSelector.svelte index 487436de8..23bcf3e21 100644 --- a/frontend/src/ProjectManager/ProjectManagerSelector.svelte +++ b/frontend/src/ProjectManager/ProjectManagerSelector.svelte @@ -11,22 +11,12 @@ font-weight: bold; text-transform: uppercase; } - .content-box { - display: flex; - outline: solid 2px var(--main-fg-color); - border-radius: 1em; - width: 100%; - height: 95%; - font-size: x-large; - overflow: auto; - overflow-y: hidden; - } .content { + font-size: x-large; display: flex; flex-direction: column; width: 100%; overflow: auto; - overflow-y: scroll; } @@ -45,17 +35,15 @@ focusText="{description}" />
-
-
- {#each projectElementOptions as projectOption} -
- -
- {/each} -
+
+ {#each projectElementOptions as projectOption} +
+ +
+ {/each}
diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index bc2514607..4cf1945b2 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -1,16 +1,8 @@ -
-
OFRAK Project Manager
-
- - - -
-
+
OFRAK Project Manager
+ + + + + + + + + + -
-
- -
+ + +
+
From f11c6e1dfdb0fccfb71662349c797af8be594c29 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 11 Jul 2023 12:51:54 -0400 Subject: [PATCH 11/63] Move titles outside of content boxes --- .../ProjectManagerFocusableLabel.svelte | 4 +-- .../ProjectManagerSelector.svelte | 10 +------ .../ProjectManager/ProjectManagerView.svelte | 26 ++++++++++++++++--- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte b/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte index 7c808f717..8db244120 100644 --- a/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte +++ b/frontend/src/ProjectManager/ProjectManagerFocusableLabel.svelte @@ -8,9 +8,9 @@ diff --git a/frontend/src/ProjectManager/ProjectManagerSelector.svelte b/frontend/src/ProjectManager/ProjectManagerSelector.svelte index 23bcf3e21..a25a5f3bb 100644 --- a/frontend/src/ProjectManager/ProjectManagerSelector.svelte +++ b/frontend/src/ProjectManager/ProjectManagerSelector.svelte @@ -22,19 +22,11 @@
-
- -
{#each projectElementOptions as projectOption}
diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 4cf1945b2..a81ed8fbf 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -21,11 +21,19 @@ height: 5vh; margin-top: 1em; } + .title { + padding-bottom: 0.5em; + text-align: center; + font-size: xx-large; + font-weight: bold; + text-transform: uppercase; + } + +"{description}" + diff --git a/frontend/src/ProjectManager/ProjectManagerOptions.svelte b/frontend/src/ProjectManager/ProjectManagerOptions.svelte index 391002ea0..4cfe0af8a 100644 --- a/frontend/src/ProjectManager/ProjectManagerOptions.svelte +++ b/frontend/src/ProjectManager/ProjectManagerOptions.svelte @@ -17,8 +17,10 @@
- {#if focus} - {focus} + {#if focus && typeof focus == "string"} + "{focus}" + {:else if focus} + {:else} Click anywhere to see its options. {/if} diff --git a/frontend/src/ProjectManager/ProjectManagerSelector.svelte b/frontend/src/ProjectManager/ProjectManagerSelector.svelte index a25a5f3bb..05830f51b 100644 --- a/frontend/src/ProjectManager/ProjectManagerSelector.svelte +++ b/frontend/src/ProjectManager/ProjectManagerSelector.svelte @@ -4,13 +4,6 @@ padding: 2em; overflow-y: hidden; } - .title { - padding-bottom: 0.5em; - text-align: center; - font-size: xx-large; - font-weight: bold; - text-transform: uppercase; - } .content { font-size: x-large; display: flex; diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index a81ed8fbf..58aa51633 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -33,6 +33,7 @@ -"{description}" - + +{#if f} + + +{/if} diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 58aa51633..270f23794 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -66,7 +66,7 @@
{ + if (!r.ok) { + throw Error(r.statusText); + } + return r.json(); + }); + $selectedProject = result.id; + console.log($selectedProject); showProjectManager = true; } + async function getProjects() { + return await this.fetch(`/get_projects`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }).then(async (r) => { + if (!r.ok) { + throw Error(JSON.stringify(await r.json(), undefined, 2)); + } + return await r.json(); + }); + } + async function handleDrop(e) { dragging = false; if (e.dataTransfer.files.length > 0) { @@ -349,7 +382,9 @@

Failed to get any pre-existing root resources!

The back end server may be down.

{/await} - + { + if (!r.ok) { + throw Error(JSON.stringify(await r.json(), undefined, 2)); + } + return await r.json(); + }); + } + + async get_projects() { + return await this.fetch("/get_projects", { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }).then(async (r) => { + if (!r.ok) { + throw Error(JSON.stringify(await r.json(), undefined, 2)); + } + return await r.json(); + }); + } + + async add_binary_to_project(id, name, data) { + return await this.fetch("/add_binary_to_project", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: id, + name: name, + data: data, + }), + }).then(async (r) => { + if (!r.ok) { + throw Error(JSON.stringify(await r.json(), undefined, 2)); + } + return await r.json(); + }); + } + + async add_binary_to_project(id, name, data) { + return await this.fetch("/add_script_to_project", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: id, + name: name, + data: data, + }), + }).then(async (r) => { + if (!r.ok) { + throw Error(JSON.stringify(await r.json(), undefined, 2)); + } + return await r.json(); + }); + } } export function remote_models_to_resources(remote_models, resources) { diff --git a/frontend/src/stores.js b/frontend/src/stores.js index 81f0d88b0..a3c4a596b 100644 --- a/frontend/src/stores.js +++ b/frontend/src/stores.js @@ -8,6 +8,9 @@ export const selected = writable(undefined); // Currently selected resource object export const selectedResource = writable(undefined); +// Currently selected project ID +export const selectedProject = writable(undefined); + // User-generated OFRAK script (array of lines) export const script = writable([]); diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index 1ee561783..e94ba43ee 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -6,6 +6,7 @@ import functools import itertools import logging +from ofrak.project.project import OfrakProject import typing_inspect from typing_inspect import get_args @@ -147,6 +148,7 @@ def __init__( self.component_context: ComponentContext = ClientComponentContext() self.script_builder: ScriptBuilder = ScriptBuilder() self.resource_builder: Dict[str, Tuple[Resource, memoryview]] = {} + self.projects: List[OfrakProject] = [] self._app.add_routes( [ web.post("/create_root_resource", self.create_root_resource), @@ -201,6 +203,10 @@ def __init__( "/{resource_id}/get_tags_and_num_components", self.get_tags_and_num_components ), web.post("/{resource_id}/search_data", self.search_data), + web.post("/create_new_project", self.create_new_project), + web.get("/get_projects", self.get_projects), + web.post("/add_binary_to_project", self.add_binary_to_project), + web.post("/add_script_to_project", self.add_script_to_project), web.get("/", self.get_static_files), web.static( "/", @@ -1016,6 +1022,47 @@ async def search_data(self, request: Request) -> Response: return json_response(results) + async def create_new_project(self, request: Request) -> Response: + body = await request.json() + name = body.get("name") + id = len(self.projects) + self.projects.append(OfrakProject(os.path.join("/tmp/", name), name, id, {}, [])) + return json_response({"id": id}) + + async def get_projects(self, requests: Request) -> Response: + return json_response([project.id for project in self.projects]) + + async def add_binary_to_project(self, request: Request) -> Response: + id = int(request.query.get("id")) + name = request.query.get("name") + data = await request.read() + project = self._get_project_by_id(id) + project.add_binary(name, data) + + async def add_script_to_project(self, request: Request) -> Response: + body = await request.json() + id = body["id"] + name = body["name"] + data = body["data"] + project = self._get_project_by_id(id) + project.add_script(name, data) + + def _get_project_by_name(self, name) -> OfrakProject: + result = [project for project in self.projects if project.name == name] + if len(result) > 1: + raise AttributeError("Project Name Collision") + if len(result) == 0: + return None + return result[0] + + def _get_project_by_id(self, id) -> OfrakProject: + result = [project for project in self.projects if project.project_id == id] + if len(result) > 1: + raise AttributeError("Project ID Collision") + if len(result) == 0: + raise ValueError(f"Project with ID {id} not found") + return result[0] + def _construct_field_response(self, obj): if dataclasses.is_dataclass(obj): res = [] diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index 013a17ff0..508e4e74a 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -48,7 +48,6 @@ def readme_path(self): @staticmethod def create(name: str, path: str) -> "OfrakProject": - new_project = OfrakProject( path, name, From c410752c950d3f6782f7029f004deed12c070204 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 18 Jul 2023 12:35:22 -0400 Subject: [PATCH 14/63] Missed something --- frontend/src/StartView.svelte | 2 +- frontend/src/ofrak/remote_resource.js | 66 --------------------------- 2 files changed, 1 insertion(+), 67 deletions(-) diff --git a/frontend/src/StartView.svelte b/frontend/src/StartView.svelte index db3d116de..761d2d16a 100644 --- a/frontend/src/StartView.svelte +++ b/frontend/src/StartView.svelte @@ -197,7 +197,7 @@ async function createNewProject() { let result = await fetch( - `${$settings.backendUrl}/create_new_project?id=${id}name=${f.name}`, + `${$settings.backendUrl}/create_new_project`, { method: "POST", headers: { diff --git a/frontend/src/ofrak/remote_resource.js b/frontend/src/ofrak/remote_resource.js index 097d58b47..548c7b736 100644 --- a/frontend/src/ofrak/remote_resource.js +++ b/frontend/src/ofrak/remote_resource.js @@ -704,72 +704,6 @@ export class RemoteResource extends Resource { return await r.json(); }); } - - async create_new_project() { - return await this.fetch("/create_new_project", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - }).then(async (r) => { - if (!r.ok) { - throw Error(JSON.stringify(await r.json(), undefined, 2)); - } - return await r.json(); - }); - } - - async get_projects() { - return await this.fetch("/get_projects", { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }).then(async (r) => { - if (!r.ok) { - throw Error(JSON.stringify(await r.json(), undefined, 2)); - } - return await r.json(); - }); - } - - async add_binary_to_project(id, name, data) { - return await this.fetch("/add_binary_to_project", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - id: id, - name: name, - data: data, - }), - }).then(async (r) => { - if (!r.ok) { - throw Error(JSON.stringify(await r.json(), undefined, 2)); - } - return await r.json(); - }); - } - - async add_binary_to_project(id, name, data) { - return await this.fetch("/add_script_to_project", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - id: id, - name: name, - data: data, - }), - }).then(async (r) => { - if (!r.ok) { - throw Error(JSON.stringify(await r.json(), undefined, 2)); - } - return await r.json(); - }); - } } export function remote_models_to_resources(remote_models, resources) { From 4e1ec0ad68f24b07163547e7a3ab94b172f3835f Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 18 Jul 2023 12:43:09 -0400 Subject: [PATCH 15/63] Add proper response to server routes --- ofrak_core/ofrak/gui/server.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index e94ba43ee..073578edb 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -1038,6 +1038,7 @@ async def add_binary_to_project(self, request: Request) -> Response: data = await request.read() project = self._get_project_by_id(id) project.add_binary(name, data) + return json_response([]) async def add_script_to_project(self, request: Request) -> Response: body = await request.json() @@ -1046,6 +1047,7 @@ async def add_script_to_project(self, request: Request) -> Response: data = body["data"] project = self._get_project_by_id(id) project.add_script(name, data) + return json_response([]) def _get_project_by_name(self, name) -> OfrakProject: result = [project for project in self.projects if project.name == name] From e150a1702017a84772919220a31ac986b04fa8b6 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 18 Jul 2023 13:08:57 -0400 Subject: [PATCH 16/63] Use project given from server --- frontend/src/App.svelte | 64 +------------------ .../ProjectManagerAddFileToProject.svelte | 21 +++++- .../ProjectManager/ProjectManagerView.svelte | 6 +- frontend/src/StartView.svelte | 29 +++++---- ofrak_core/ofrak/gui/server.py | 8 ++- ofrak_core/ofrak/project/project.py | 8 +++ 6 files changed, 56 insertions(+), 80 deletions(-) diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 90b3069c7..c88be30b3 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -70,66 +70,7 @@ modifierView, bottomLeftPane; - let project = { - name: "Test Project", - binaries: ["example_1", "example_2"], - scripts: [ - "example_1.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_2.py", - "example_3.py", - ], - components: [], - readme: "This is the Readme\nIt looks like this", - }; + let project; // TODO: Move to settings let riddleAnswered = JSON.parse(window.localStorage.getItem("riddleSolved")); @@ -315,7 +256,7 @@ Answer by running riddle.answer('your answer here') from the console.`);
{/if} {:else if showProjectManager} - + {:else} {/if} diff --git a/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte b/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte index 26555e013..e1a15c6b2 100644 --- a/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte +++ b/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte @@ -10,7 +10,7 @@ } async function addBinaryToProject() { await fetch( - `${$settings.backendUrl}/add_binary_to_project?id=${$selectedProject}&name=${f.name}`, + `${$settings.backendUrl}/add_binary_to_project?id=${$selectedProject.id}&name=${f.name}`, { method: "POST", headers: { @@ -22,6 +22,15 @@ if (!r.ok) { throw Error(JSON.stringify(await r.json(), undefined, 2)); } + $selectedProject = await fetch( + `${$settings.backendUrl}/get_project_by_id?id=${$selectedProject.id}` + ).then((r) => { + if (!r.ok) { + throw Error(r.statusText); + } + return r.json(); + }); + console.log($selectedProject); return await r.json(); }); } @@ -29,7 +38,7 @@ async function addScriptToProject(name, data) { data = await dataPromise; return await fetch( - `${$settings.backendUrl}/add_script_to_project?id=${$selectedProject}&name=${f.name}`, + `${$settings.backendUrl}/add_script_to_project?id=${$selectedProject.id}&name=${f.name}`, { method: "POST", headers: { @@ -41,6 +50,14 @@ if (!r.ok) { throw Error(JSON.stringify(await r.json(), undefined, 2)); } + $selectedProject = await fetch( + `${$settings.backendUrl}/get_project_by_id?id=${$selectedProject.id}` + ).then((r) => { + if (!r.ok) { + throw Error(r.statusText); + } + return r.json(); + }); return await r.json(); }); } diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 270f23794..5904d5c76 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -37,8 +37,8 @@ import ProjectManagerFocusableLabel from "./ProjectManagerFocusableLabel.svelte"; import ProjectManagerOptions from "./ProjectManagerOptions.svelte"; import ProjectManagerSelector from "./ProjectManagerSelector.svelte"; + import { selectedProject } from "../stores"; - export let project; let focus, selectedBinary, selectedScript; function openProject() {} @@ -56,7 +56,7 @@ />
@@ -70,7 +70,7 @@ />
diff --git a/frontend/src/StartView.svelte b/frontend/src/StartView.svelte index 761d2d16a..53d629239 100644 --- a/frontend/src/StartView.svelte +++ b/frontend/src/StartView.svelte @@ -115,7 +115,8 @@ rootResource, resourceNodeDataMap, browsedFiles, - fileinput; + fileinput, + project; let dragging = false, selectedPreExistingRoot = null, preExistingRootsPromise = new Promise(() => {}), @@ -196,24 +197,28 @@ } async function createNewProject() { - let result = await fetch( - `${$settings.backendUrl}/create_new_project`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - name: "test", - }), + let result = await fetch(`${$settings.backendUrl}/create_new_project`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: "test", + }), + }).then((r) => { + if (!r.ok) { + throw Error(r.statusText); } + return r.json(); + }); + $selectedProject = await fetch( + `${$settings.backendUrl}/get_project_by_id?id=${result.id}` ).then((r) => { if (!r.ok) { throw Error(r.statusText); } return r.json(); }); - $selectedProject = result.id; console.log($selectedProject); showProjectManager = true; } diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index 073578edb..54378d230 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -205,6 +205,7 @@ def __init__( web.post("/{resource_id}/search_data", self.search_data), web.post("/create_new_project", self.create_new_project), web.get("/get_projects", self.get_projects), + web.get("/get_project_by_id", self.get_project_by_id), web.post("/add_binary_to_project", self.add_binary_to_project), web.post("/add_script_to_project", self.add_script_to_project), web.get("/", self.get_static_files), @@ -1029,9 +1030,14 @@ async def create_new_project(self, request: Request) -> Response: self.projects.append(OfrakProject(os.path.join("/tmp/", name), name, id, {}, [])) return json_response({"id": id}) - async def get_projects(self, requests: Request) -> Response: + async def get_projects(self, request: Request) -> Response: return json_response([project.id for project in self.projects]) + async def get_project_by_id(self, request: Request) -> Response: + id = int(request.query.get("id")) + project = self._get_project_by_id(id) + return json_response(project.to_dict()) + async def add_binary_to_project(self, request: Request) -> Response: id = int(request.query.get("id")) name = request.query.get("name") diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index 508e4e74a..a8af8a241 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -192,3 +192,11 @@ def add_script(self, name: str, script_contents: str): self.scripts.append(name) with open(self.script_path(name, check=False), "w+") as f: f.write(script_contents) + + def to_dict(self): + return { + "name": self.name, + "id": self.project_id, + "binaries": [binary for binary in self.binaries.keys()], + "scripts": [script for script in self.scripts], + } From 96a46f51a498839fe66ed846a63ceefb68eed49a Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 18 Jul 2023 13:18:22 -0400 Subject: [PATCH 17/63] Get scripts from server --- .../ProjectManager/ProjectManagerAddFileToProject.svelte | 3 +-- ofrak_core/ofrak/gui/server.py | 9 ++++----- ofrak_core/ofrak/project/project.py | 1 + 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte b/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte index e1a15c6b2..b537d1296 100644 --- a/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte +++ b/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte @@ -35,8 +35,7 @@ }); } - async function addScriptToProject(name, data) { - data = await dataPromise; + async function addScriptToProject() { return await fetch( `${$settings.backendUrl}/add_script_to_project?id=${$selectedProject.id}&name=${f.name}`, { diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index 54378d230..7e4c70fdd 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -1047,12 +1047,11 @@ async def add_binary_to_project(self, request: Request) -> Response: return json_response([]) async def add_script_to_project(self, request: Request) -> Response: - body = await request.json() - id = body["id"] - name = body["name"] - data = body["data"] + id = int(request.query.get("id")) + name = request.query.get("name") + data = await request.read() project = self._get_project_by_id(id) - project.add_script(name, data) + project.add_script(name, data.decode()) return json_response([]) def _get_project_by_name(self, name) -> OfrakProject: diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index a8af8a241..864f9387f 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -190,6 +190,7 @@ def add_binary(self, name: str, contents: bytes): def add_script(self, name: str, script_contents: str): self.scripts.append(name) + os.makedirs(os.path.join(self.path, "scripts"), exist_ok=True) with open(self.script_path(name, check=False), "w+") as f: f.write(script_contents) From 52862f2cfbcb61fc1e327d236c5f9760d0d186b0 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 18 Jul 2023 14:45:51 -0400 Subject: [PATCH 18/63] Run a project, but resource view does not open automatically --- frontend/src/App.svelte | 6 +++- .../ProjectManagerAddFileToProject.svelte | 1 - .../ProjectManager/ProjectManagerView.svelte | 33 ++++++++++++++++--- frontend/src/StartView.svelte | 3 +- ofrak_core/ofrak/gui/package-lock.json | 6 ++++ ofrak_core/ofrak/gui/server.py | 26 +++++++++++---- ofrak_core/ofrak/project/project.py | 6 ++-- 7 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 ofrak_core/ofrak/gui/package-lock.json diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index c88be30b3..80e6a63d9 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -256,7 +256,11 @@ Answer by running riddle.answer('your answer here') from the console.`);
{/if} {:else if showProjectManager} - + {:else} {}); $: if (files) { f = files[0]; diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 5904d5c76..96db6df97 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -37,14 +37,37 @@ import ProjectManagerFocusableLabel from "./ProjectManagerFocusableLabel.svelte"; import ProjectManagerOptions from "./ProjectManagerOptions.svelte"; import ProjectManagerSelector from "./ProjectManagerSelector.svelte"; - import { selectedProject } from "../stores"; + import { selectedProject, settings, selected } from "../stores"; + import { remote_model_to_resource } from "../ofrak/remote_resource"; - let focus, selectedBinary, selectedScript; + let focus, + selectedBinary, + selectedScript, + resources, + showRootResource, + showProjectManager; - function openProject() {} + async function openProject() { + let rootModel = await fetch(`${$settings.backendUrl}/open_project`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: $selectedProject.id, + binary: selectedBinary, + script: selectedScript, + }), + }).then((r) => r.json()); + remote_model_to_resource(rootModel, resources); + $selected = rootModel.id; + showProjectManager = false; + showRootResource = true; + }
OFRAK Project Manager
+ @@ -57,7 +80,7 @@
@@ -71,7 +94,7 @@
diff --git a/frontend/src/StartView.svelte b/frontend/src/StartView.svelte index 53d629239..f1fbcd455 100644 --- a/frontend/src/StartView.svelte +++ b/frontend/src/StartView.svelte @@ -115,8 +115,7 @@ rootResource, resourceNodeDataMap, browsedFiles, - fileinput, - project; + fileinput; let dragging = false, selectedPreExistingRoot = null, preExistingRootsPromise = new Promise(() => {}), diff --git a/ofrak_core/ofrak/gui/package-lock.json b/ofrak_core/ofrak/gui/package-lock.json new file mode 100644 index 000000000..1ed357446 --- /dev/null +++ b/ofrak_core/ofrak/gui/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "gui", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index 7e4c70fdd..8b9506660 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -208,6 +208,7 @@ def __init__( web.get("/get_project_by_id", self.get_project_by_id), web.post("/add_binary_to_project", self.add_binary_to_project), web.post("/add_script_to_project", self.add_script_to_project), + web.post("/open_project", self.open_project), web.get("/", self.get_static_files), web.static( "/", @@ -1026,20 +1027,21 @@ async def search_data(self, request: Request) -> Response: async def create_new_project(self, request: Request) -> Response: body = await request.json() name = body.get("name") - id = len(self.projects) - self.projects.append(OfrakProject(os.path.join("/tmp/", name), name, id, {}, [])) - return json_response({"id": id}) + project = OfrakProject.create(os.path.join("/tmp/", name), name) + self.projects.append(project) + + return json_response({"id": project.project_id.hex()}) async def get_projects(self, request: Request) -> Response: return json_response([project.id for project in self.projects]) async def get_project_by_id(self, request: Request) -> Response: - id = int(request.query.get("id")) + id = request.query.get("id") project = self._get_project_by_id(id) return json_response(project.to_dict()) async def add_binary_to_project(self, request: Request) -> Response: - id = int(request.query.get("id")) + id = request.query.get("id") name = request.query.get("name") data = await request.read() project = self._get_project_by_id(id) @@ -1047,13 +1049,23 @@ async def add_binary_to_project(self, request: Request) -> Response: return json_response([]) async def add_script_to_project(self, request: Request) -> Response: - id = int(request.query.get("id")) + id = request.query.get("id") name = request.query.get("name") data = await request.read() project = self._get_project_by_id(id) project.add_script(name, data.decode()) return json_response([]) + async def open_project(self, request: Request) -> Response: + body = await request.json() + id = body["id"] + binary = body["binary"] + script = body["script"] + project = self._get_project_by_id(id) + resource = await project.init_adventure_binary(binary, script, self._ofrak_context) + self._job_ids[request.remote] = resource.get_job_id() + return json_response(self._serialize_resource(resource)) + def _get_project_by_name(self, name) -> OfrakProject: result = [project for project in self.projects if project.name == name] if len(result) > 1: @@ -1063,7 +1075,7 @@ def _get_project_by_name(self, name) -> OfrakProject: return result[0] def _get_project_by_id(self, id) -> OfrakProject: - result = [project for project in self.projects if project.project_id == id] + result = [project for project in self.projects if project.project_id.hex() == id] if len(result) > 1: raise AttributeError("Project ID Collision") if len(result) == 0: diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index 864f9387f..448a4ec91 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -153,13 +153,13 @@ def binary_path(self, binary_name, check: bool = True) -> str: return p async def init_adventure_binary( - self, binary_name: str, ofrak_context: OFRAKContext + self, binary_name: str, script_name: str, ofrak_context: OFRAKContext ) -> Resource: binary_metadata = self.binaries[binary_name] resource = await ofrak_context.create_root_resource_from_file(self.binary_path(binary_name)) if binary_metadata.init_script: - with open(self.script_path(binary_metadata.init_script)) as f: + with open(self.script_path(script_name)) as f: code = f.read() await resource.run(RunScriptModifier, RunScriptModifierConfig(code)) @@ -197,7 +197,7 @@ def add_script(self, name: str, script_contents: str): def to_dict(self): return { "name": self.name, - "id": self.project_id, + "id": self.project_id.hex(), "binaries": [binary for binary in self.binaries.keys()], "scripts": [script for script in self.scripts], } From c2f915839db34718fac69a10e44e3ca6ff84a83c Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 18 Jul 2023 15:18:36 -0400 Subject: [PATCH 19/63] Script runs on project start --- ofrak_core/ofrak/gui/server.py | 8 +++++++- ofrak_core/ofrak/project/project.py | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index 8b9506660..0ce2c0daf 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -1024,22 +1024,26 @@ async def search_data(self, request: Request) -> Response: return json_response(results) + @exceptions_to_http(SerializedError) async def create_new_project(self, request: Request) -> Response: body = await request.json() name = body.get("name") - project = OfrakProject.create(os.path.join("/tmp/", name), name) + project = OfrakProject.create(name, os.path.join("/tmp/", name)) self.projects.append(project) return json_response({"id": project.project_id.hex()}) + @exceptions_to_http(SerializedError) async def get_projects(self, request: Request) -> Response: return json_response([project.id for project in self.projects]) + @exceptions_to_http(SerializedError) async def get_project_by_id(self, request: Request) -> Response: id = request.query.get("id") project = self._get_project_by_id(id) return json_response(project.to_dict()) + @exceptions_to_http(SerializedError) async def add_binary_to_project(self, request: Request) -> Response: id = request.query.get("id") name = request.query.get("name") @@ -1048,6 +1052,7 @@ async def add_binary_to_project(self, request: Request) -> Response: project.add_binary(name, data) return json_response([]) + @exceptions_to_http(SerializedError) async def add_script_to_project(self, request: Request) -> Response: id = request.query.get("id") name = request.query.get("name") @@ -1056,6 +1061,7 @@ async def add_script_to_project(self, request: Request) -> Response: project.add_script(name, data.decode()) return json_response([]) + @exceptions_to_http(SerializedError) async def open_project(self, request: Request) -> Response: body = await request.json() id = body["id"] diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index 448a4ec91..3fb30c0cd 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -158,7 +158,7 @@ async def init_adventure_binary( binary_metadata = self.binaries[binary_name] resource = await ofrak_context.create_root_resource_from_file(self.binary_path(binary_name)) - if binary_metadata.init_script: + if script_name is not None: with open(self.script_path(script_name)) as f: code = f.read() await resource.run(RunScriptModifier, RunScriptModifierConfig(code)) From 89f875b3ba5250ed212af3565f79efbe42b6c050 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Tue, 18 Jul 2023 15:26:44 -0400 Subject: [PATCH 20/63] Run project opens resource view --- frontend/src/App.svelte | 2 ++ .../src/ProjectManager/ProjectManagerView.svelte | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 80e6a63d9..3d86fcb04 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -257,6 +257,8 @@ Answer by running riddle.answer('your answer here') from the console.`); {/if} {:else if showProjectManager} r.json()); - remote_model_to_resource(rootModel, resources); + rootResource = remote_model_to_resource(rootModel, resources); $selected = rootModel.id; showProjectManager = false; showRootResource = true; } + $: rootResourceLoadPromise = openProject;
OFRAK Project Manager
From 4a60c5347b44b9c7093a2cae5533bf3b87d6beaa Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Wed, 19 Jul 2023 09:49:47 -0400 Subject: [PATCH 21/63] Accidentally deleted script element --- frontend/src/ProjectManager/ProjectManagerView.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index a37a17c78..aac817f93 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -66,7 +66,7 @@ showRootResource = true; } $: rootResourceLoadPromise = openProject; - +
OFRAK Project Manager
From 6b1e0c2e20602503e3ec59d35cd5113c72b19123 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Wed, 19 Jul 2023 12:45:03 -0400 Subject: [PATCH 22/63] Select any project from frontend --- .../ProjectManager/ProjectManagerView.svelte | 2 +- frontend/src/StartView.svelte | 39 +++++++++++++++++-- ofrak_core/ofrak/gui/server.py | 10 ++--- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index aac817f93..a37a17c78 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -66,7 +66,7 @@ showRootResource = true; } $: rootResourceLoadPromise = openProject; - +
OFRAK Project Manager
diff --git a/frontend/src/StartView.svelte b/frontend/src/StartView.svelte index f1fbcd455..998e53c49 100644 --- a/frontend/src/StartView.svelte +++ b/frontend/src/StartView.svelte @@ -119,8 +119,9 @@ let dragging = false, selectedPreExistingRoot = null, preExistingRootsPromise = new Promise(() => {}), + preExistingProjectsPromise = new Promise(() => {}), tryHash = !!window.location.hash; - let mouseX, selectedAnimal; + let mouseX, selectedAnimal, showProjectOptions, newProjectName; const warnFileSize = 250 * 1024 * 1024; const fileChunkSize = warnFileSize; @@ -202,7 +203,7 @@ "Content-Type": "application/json", }, body: JSON.stringify({ - name: "test", + name: newProjectName, }), }).then((r) => { if (!r.ok) { @@ -312,6 +313,9 @@ preExistingRootsPromise = await fetch( `${$settings.backendUrl}/get_root_resources` ).then((r) => r.json()); + preExistingProjectsPromise = await fetch( + `${$settings.backendUrl}/get_all_projects` + ).then((r) => r.json()); }); @@ -386,8 +390,35 @@

Failed to get any pre-existing root resources!

The back end server may be down.

{/await} - + + {#await preExistingProjectsPromise then projects} + + + {/await} + {/if} + Response: return json_response({"id": project.project_id.hex()}) - @exceptions_to_http(SerializedError) - async def get_projects(self, request: Request) -> Response: - return json_response([project.id for project in self.projects]) - @exceptions_to_http(SerializedError) async def get_project_by_id(self, request: Request) -> Response: id = request.query.get("id") project = self._get_project_by_id(id) return json_response(project.to_dict()) + @exceptions_to_http(SerializedError) + async def get_all_projects(self, requet: Request) -> Response: + return json_response([project.to_dict() for project in self.projects]) + @exceptions_to_http(SerializedError) async def add_binary_to_project(self, request: Request) -> Response: id = request.query.get("id") From 918de3960121012a8ae5bf140ead2231f8eb7971 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Wed, 19 Jul 2023 14:37:50 -0400 Subject: [PATCH 23/63] Can clone project from git --- frontend/src/StartView.svelte | 28 +++++++++++++++------- ofrak_core/ofrak/gui/server.py | 13 +++++++++++ ofrak_core/ofrak/project/project.py | 36 +++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/frontend/src/StartView.svelte b/frontend/src/StartView.svelte index 998e53c49..6296c32ba 100644 --- a/frontend/src/StartView.svelte +++ b/frontend/src/StartView.svelte @@ -121,7 +121,7 @@ preExistingRootsPromise = new Promise(() => {}), preExistingProjectsPromise = new Promise(() => {}), tryHash = !!window.location.hash; - let mouseX, selectedAnimal, showProjectOptions, newProjectName; + let mouseX, selectedAnimal, showProjectOptions, newProjectName, gitUrl; const warnFileSize = 250 * 1024 * 1024; const fileChunkSize = warnFileSize; @@ -219,22 +219,25 @@ } return r.json(); }); - console.log($selectedProject); showProjectManager = true; } - async function getProjects() { - return await this.fetch(`/get_projects`, { - method: "GET", + async function cloneProjectFromGit() { + let result = await fetch(`${$settings.backendUrl}/clone_project_from_git`, { + method: "POST", headers: { "Content-Type": "application/json", }, - }).then(async (r) => { + body: JSON.stringify({ + url: gitUrl, + }), + }).then((r) => { if (!r.ok) { - throw Error(JSON.stringify(await r.json(), undefined, 2)); + throw Error(r.statusText); } - return await r.json(); + return r.json(); }); + showProjectManager = true; } async function handleDrop(e) { @@ -414,6 +417,15 @@ }}">Open Existing Project {/await} + + {/if} - -{/if} +
+ + {#if f} + {f.name}[{f.size}B] + + + {/if} +
diff --git a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte new file mode 100644 index 000000000..610f02731 --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte @@ -0,0 +1,26 @@ + + + diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index a37a17c78..47b46f8f2 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -1,7 +1,15 @@ diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index af351c482..216b8b03e 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -59,7 +59,7 @@ "Content-Type": "application/json", }, body: JSON.stringify({ - id: $selectedProject.id, + id: $selectedProject.session_id, binary: selectedBinary, script: selectedScript, }), diff --git a/frontend/src/StartView.svelte b/frontend/src/StartView.svelte index a1ac69824..5c9cea728 100644 --- a/frontend/src/StartView.svelte +++ b/frontend/src/StartView.svelte @@ -96,7 +96,7 @@ .project-options { display: flex; - flex-direction: row; + flex-direction: column; } .project-input { @@ -107,6 +107,9 @@ .project { display: flex; flex-direction: column; + justify-content: stretch; + align-items: stretch; + width: 50%; } .advanced { @@ -450,19 +453,22 @@ {:else if dragging}

Drop the file!

{:else if showProjectOptions} -

Open a Project

- {/if} - - - -
+

Project Options

- OR - -
+ /> + {/if} + {#if !showProjectOptions} + +
+ + OR + +
+ {/if} {#await preExistingRootsPromise} {:then preExistingRootResources} @@ -508,28 +514,42 @@ bind:value="{newProjectName}" placeholder="Project Name" /> -
+ + OR +
{#await preExistingProjectsPromise then projects} {/await}
+ + OR +
-
@@ -562,7 +584,7 @@ Back {:else} + {/if} +
diff --git a/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte b/frontend/src/ProjectManager/ProjectManagerAddScriptToProject.svelte similarity index 62% rename from frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte rename to frontend/src/ProjectManager/ProjectManagerAddScriptToProject.svelte index 41933653e..f4c7b88cb 100644 --- a/frontend/src/ProjectManager/ProjectManagerAddFileToProject.svelte +++ b/frontend/src/ProjectManager/ProjectManagerAddScriptToProject.svelte @@ -31,32 +31,6 @@ f = files[0]; files = null; } - async function addBinaryToProject() { - await fetch( - `${$settings.backendUrl}/add_binary_to_project?id=${$selectedProject.session_id}&name=${f.name}`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: await f.arrayBuffer(), - } - ).then(async (r) => { - if (!r.ok) { - throw Error(JSON.stringify(await r.json(), undefined, 2)); - } - $selectedProject = await fetch( - `${$settings.backendUrl}/get_project_by_id?id=${$selectedProject.session_id}` - ).then((r) => { - if (!r.ok) { - throw Error(r.statusText); - } - return r.json(); - }); - console.log($selectedProject); - return await r.json(); - }); - } async function addScriptToProject() { return await fetch( @@ -88,11 +62,8 @@
{#if f} - Add Script to Project {/if}
diff --git a/frontend/src/ProjectManager/ProjectManagerBinaryOptions.svelte b/frontend/src/ProjectManager/ProjectManagerBinaryOptions.svelte new file mode 100644 index 000000000..e75ebaacf --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerBinaryOptions.svelte @@ -0,0 +1,68 @@ + + + + +
+ +
diff --git a/frontend/src/ProjectManager/ProjectManagerSelector.svelte b/frontend/src/ProjectManager/ProjectManagerBinarySelector.svelte similarity index 70% rename from frontend/src/ProjectManager/ProjectManagerSelector.svelte rename to frontend/src/ProjectManager/ProjectManagerBinarySelector.svelte index 670e70d85..901b1f81a 100644 --- a/frontend/src/ProjectManager/ProjectManagerSelector.svelte +++ b/frontend/src/ProjectManager/ProjectManagerBinarySelector.svelte @@ -14,9 +14,19 @@
@@ -26,7 +36,7 @@
{/each} diff --git a/frontend/src/ProjectManager/ProjectManagerMainOptions.svelte b/frontend/src/ProjectManager/ProjectManagerMainOptions.svelte new file mode 100644 index 000000000..1e2efefb9 --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerMainOptions.svelte @@ -0,0 +1,9 @@ + + + + +
+

Welcome to the OFRAK Project Manager

+
diff --git a/frontend/src/ProjectManager/ProjectManagerOptions.svelte b/frontend/src/ProjectManager/ProjectManagerOptions.svelte index 4cfe0af8a..e503844fd 100644 --- a/frontend/src/ProjectManager/ProjectManagerOptions.svelte +++ b/frontend/src/ProjectManager/ProjectManagerOptions.svelte @@ -19,8 +19,8 @@
{#if focus && typeof focus == "string"} "{focus}" - {:else if focus} - + {:else if focus && typeof focus == "object"} + {:else} Click anywhere to see its options. {/if} diff --git a/frontend/src/ProjectManager/ProjectManagerScriptOptions.svelte b/frontend/src/ProjectManager/ProjectManagerScriptOptions.svelte new file mode 100644 index 000000000..e616ada8d --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerScriptOptions.svelte @@ -0,0 +1,68 @@ + + + + +
+ +
diff --git a/frontend/src/ProjectManager/ProjectManagerScriptSelector.svelte b/frontend/src/ProjectManager/ProjectManagerScriptSelector.svelte new file mode 100644 index 000000000..0095781cc --- /dev/null +++ b/frontend/src/ProjectManager/ProjectManagerScriptSelector.svelte @@ -0,0 +1,45 @@ + + + + +
+
+ {#each projectElementOptions as projectOption} +
+ +
+ {/each} +
+
diff --git a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte index 88d2caf24..bdaeec8c5 100644 --- a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte +++ b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte @@ -1,6 +1,7 @@ diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 216b8b03e..3f72fd758 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -34,17 +34,20 @@ @@ -87,10 +97,10 @@
-
- Response: async def get_all_projects(self, request: Request) -> Response: if self.projects is None: self._slurp_projects_from_dir() - return json_response([project.get_saved_metadata() for project in self.projects]) + return json_response([project.get_current_metadata() for project in self.projects]) + + @exceptions_to_http(SerializedError) + async def reset_project(self, request: Request) -> Response: + body = await request.json() + id = body["id"] + project = self._get_project_by_id(id) + project.reset_project() + return json_response([]) @exceptions_to_http(SerializedError) async def add_binary_to_project(self, request: Request) -> Response: @@ -1139,6 +1150,24 @@ async def save_project_data(self, request: Request) -> Response: project.write_metadata_to_disk() return json_response([]) + @exceptions_to_http(SerializedError) + async def delete_binary_from_project(self, request: Request) -> Response: + body = await request.json() + id = body["id"] + binary_name = body["binary"] + project = self._get_project_by_id(id) + project.delete_binary(binary_name) + return json_response([]) + + @exceptions_to_http(SerializedError) + async def delete_script_from_project(self, request: Request) -> Response: + body = await request.json() + id = body["id"] + script_name = body["script"] + project = self._get_project_by_id(id) + project.delete_script(script_name) + return json_response([]) + def _slurp_projects_from_dir(self) -> None: self.projects = set() if not os.path.exists(self.projects_dir): diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index 6a9af4a05..2109e7ae0 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -111,40 +111,6 @@ def clone_from_git(url: str, path: str) -> "OfrakProject": return project - @staticmethod - def _init_from_path(path: str) -> "OfrakProject": - name = os.path.basename(path) - if not os.path.exists(path): - raise ValueError(f"{path} does not exist") - if not os.path.isdir(path): - raise ValueError(f"{path} is not a directory") - binaries_path = os.path.join(path, "binaries") - scripts_path = os.path.join(path, "scripts") - - if not all( - [ - os.path.exists(binaries_path), - os.path.isdir(binaries_path), - os.path.exists(scripts_path), - os.path.isdir(scripts_path), - ] - ): - raise ValueError(f"{path} has invalid structure to be an Project") - scripts = [script_name for script_name in os.listdir(scripts_path)] - binaries = {} - for binary in os.listdir(binaries_path): - binaries[binary] = _OfrakProjectBinary([], None) - - project = OfrakProject( - path, - name, - uuid.uuid4().bytes, - binaries, - scripts, - ) - - return project - @staticmethod def init_from_path(path: str) -> "OfrakProject": """ @@ -309,13 +275,47 @@ def update_binary_data(self, name: str, init: str = None, associated: List[str] if associated is not None: binary.associated_scripts = associated - def to_dict(self): - return { - "name": self.name, - "id": self.project_id.hex(), - "binaries": [binary for binary in self.binaries.keys()], - "scripts": [script for script in self.scripts], - } + def delete_binary(self, name: str): + self.binaries.pop(name) + + def delete_script(self, name: str): + self.scripts.remove(name) + + def reset_project(self): + path = self.path + if not os.path.exists(path): + raise ValueError(f"{path} does not exist") + if not os.path.isdir(path): + raise ValueError(f"{path} is not a directory") + + metadata_path = os.path.join(path, "metadata.json") + binaries_path = os.path.join(path, "binaries") + scripts_path = os.path.join(path, "scripts") + + if not all( + [ + os.path.exists(metadata_path), + os.path.exists(binaries_path), + os.path.isdir(binaries_path), + os.path.exists(scripts_path), + os.path.isdir(scripts_path), + ] + ): + raise ValueError(f"{path} has invalid structure to be an Project") + + with open(metadata_path) as f: + raw_metadata = json.load(f) + + self.scripts = [script["name"] for script in raw_metadata["scripts"]] + + self.binaries = {} + + for info in raw_metadata["binaries"]: + self.binaries[info["name"]] = _OfrakProjectBinary( + info["associated_scripts"], info.get("init_script") + ) + self.name = raw_metadata["name"] + self.project_id = binascii.unhexlify(raw_metadata["project_id"]) def _get_binary(self, name): if not name in self.binaries.keys(): From c54e5a6c32fe54559725bca51b4285b4c3a75573 Mon Sep 17 00:00:00 2001 From: edward Date: Fri, 4 Aug 2023 11:56:34 -0400 Subject: [PATCH 36/63] see/change which scripts are associated with each binary --- .../ProjectManagerCheckbox.svelte | 47 ++++++++--- .../ProjectManagerSelector.svelte | 4 +- .../ProjectManagerToolbar.svelte | 6 +- .../ProjectManager/ProjectManagerView.svelte | 78 ++++++++++++++++--- ofrak_core/ofrak/gui/server.py | 7 +- ofrak_core/ofrak/project/project.py | 22 +++--- 6 files changed, 123 insertions(+), 41 deletions(-) diff --git a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte index e7bfde9c9..2d2817aa7 100644 --- a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte +++ b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte @@ -4,23 +4,52 @@ margin-left: 1em; margin-top: 1em; } + + .option { + margin-right: 1em; + display: inline-flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: flex-start; + align-items: center; + align-content: stretch; + white-space: nowrap; + user-select: none; + cursor: pointer; + border-style: none; + }
- {option} + {#if selection !== undefined} + + {/if} +
diff --git a/frontend/src/ProjectManager/ProjectManagerSelector.svelte b/frontend/src/ProjectManager/ProjectManagerSelector.svelte index 670e70d85..9c4e49f93 100644 --- a/frontend/src/ProjectManager/ProjectManagerSelector.svelte +++ b/frontend/src/ProjectManager/ProjectManagerSelector.svelte @@ -1,5 +1,5 @@
OFRAK Project Manager
@@ -90,11 +119,19 @@ newFocus="{ProjectManagerAddFileToProject}" />
- +
+
+ {#each binariesForProject as binaryName} +
+ +
+ {/each} +
+
@@ -104,11 +141,28 @@ newFocus="{ProjectManagerAddFileToProject}" />
- +
+
+ {#each $selectedProject.scripts as projectOption} +
+ {#if selectedBinaryName} + + {:else} + + {/if} +
+ {/each} +
+
diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index 210f8e75f..b11e77a6d 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -1134,8 +1134,11 @@ async def update_binary_data(self, request: Request) -> Response: @exceptions_to_http(SerializedError) async def save_project_data(self, request: Request) -> Response: body = await request.json() - id = body["id"] - project = self._get_project_by_id(id) + session_id = body["session_id"] + project = self._get_project_by_id(session_id) + for binary_name, binary_metadata in body["binaries"].items(): + project.binaries[binary_name].init_script = binary_metadata["init_script"] + project.binaries[binary_name].associated_scripts = binary_metadata["associated_scripts"] project.write_metadata_to_disk() return json_response([]) diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index 6a9af4a05..dc205b9b4 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -95,8 +95,8 @@ def clone_from_git(url: str, path: str) -> "OfrakProject": binaries = {} - for info in raw_metadata["binaries"]: - binaries[info["name"]] = _OfrakProjectBinary( + for binary_name, info in raw_metadata["binaries"].items(): + binaries[binary_name] = _OfrakProjectBinary( info["associated_scripts"], info.get("init_script") ) name = raw_metadata["name"] @@ -190,8 +190,8 @@ def init_from_path(path: str) -> "OfrakProject": binaries = {} - for info in raw_metadata["binaries"]: - binaries[info["name"]] = _OfrakProjectBinary( + for binary_name, info in raw_metadata["binaries"].items(): + binaries[binary_name] = _OfrakProjectBinary( info["associated_scripts"], info.get("init_script") ) name = raw_metadata["name"] @@ -251,14 +251,13 @@ def write_metadata_to_disk(self): } for script_name in self.scripts ], - "binaries": [ - { - "name": binary_name, + "binaries": { + binary_name: { "init_script": binary_info.init_script, "associated_scripts": binary_info.associated_scripts, } for binary_name, binary_info in self.binaries.items() - ], + }, } with open(os.path.join(self.path, "metadata.json"), "w") as f: json.dump(metadata, f) @@ -280,14 +279,13 @@ def get_current_metadata(self): } for script_name in self.scripts ], - "binaries": [ - { - "name": binary_name, + "binaries": { + binary_name: { "init_script": binary_info.init_script, "associated_scripts": binary_info.associated_scripts, } for binary_name, binary_info in self.binaries.items() - ], + }, } def add_binary(self, name: str, contents: bytes): From 4b5b687bbd716b11512d00acb517246fb16da43d Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 4 Aug 2023 14:49:26 -0400 Subject: [PATCH 37/63] Hide project option if no project and add .trash when deleting --- .../ProjectManagerToolbar.svelte | 4 +- frontend/src/ResourceTreeToolbar.svelte | 23 ++++++++ ofrak_core/ofrak/gui/server.py | 4 +- ofrak_core/ofrak/project/project.py | 53 ++++++++++++++++++- 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte index bdaeec8c5..61506c052 100644 --- a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte +++ b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte @@ -27,7 +27,7 @@ iconUrl: "/icons/binary.svg", shortcut: "B", onclick: async (e) => { - focus = ProjectManagerAddBinaryToProject; + focus = { object: ProjectManagerAddBinaryToProject, args: {} }; }, }, { @@ -35,7 +35,7 @@ iconUrl: "/icons/document.svg", shortcut: "S", onclick: async (e) => { - focus = ProjectManagerAddScriptToProject; + focus = { object: ProjectManagerAddScriptToProject, args: {} }; }, }, { diff --git a/frontend/src/ResourceTreeToolbar.svelte b/frontend/src/ResourceTreeToolbar.svelte index f539ff80c..297eea9ae 100644 --- a/frontend/src/ResourceTreeToolbar.svelte +++ b/frontend/src/ResourceTreeToolbar.svelte @@ -53,6 +53,25 @@ ]; } + $: { + projectFeatures = [ + { + text: "Project Manager", + iconUrl: "/icons/briefcase.svg", + onclick: async (e) => { + if ($selectedProject) { + let state = { + $selectProject: $selectedProject, + }; + showProjectManager = true; + showRootResource = false; + history.pushState(state, "", "/"); + } + }, + }, + ]; + } + $: { toolbarButtons = [ { @@ -298,6 +317,10 @@ ]; } + $: if ($settings.$selectedProject) { + toolbarButtons = [...toolbarButtons, ...projectFeatures]; + } + $: if ($settings.experimentalFeatures) { toolbarButtons = [...toolbarButtons, ...experimentalFeatures]; } diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index 0f4246424..0bcfac161 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -1158,14 +1158,14 @@ async def delete_binary_from_project(self, request: Request) -> Response: project = self._get_project_by_id(id) project.delete_binary(binary_name) return json_response([]) - + @exceptions_to_http(SerializedError) async def delete_script_from_project(self, request: Request) -> Response: body = await request.json() id = body["id"] script_name = body["script"] project = self._get_project_by_id(id) - project.delete_script(script_name) + project.delete_script(script_name) return json_response([]) def _slurp_projects_from_dir(self) -> None: diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index 2109e7ae0..4da9087cf 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -276,9 +276,25 @@ def update_binary_data(self, name: str, init: str = None, associated: List[str] binary.associated_scripts = associated def delete_binary(self, name: str): - self.binaries.pop(name) - + if not os.path.isdir(os.path.join(self.path, ".Trash")): + os.mkdir(os.path.join(self.path, ".Trash")) + if not os.path.isdir(os.path.join(os.path.join(self.path, ".Trash"), "binaries")): + os.mkdir(os.path.join(os.path.join(self.path, ".Trash"), "binaries")) + os.rename( + self.binary_path(name), + os.path.join(os.path.join(os.path.join(self.path, ".Trash"), "binaries"), name), + ) + self.binaries.pop(name) + def delete_script(self, name: str): + if not os.path.isdir(os.path.join(self.path, ".Trash")): + os.mkdir(os.path.join(self.path, ".Trash")) + if not os.path.isdir(os.path.join(os.path.join(self.path, ".Trash"), "scripts")): + os.mkdir(os.path.join(os.path.join(self.path, ".Trash"), "scripts")) + os.rename( + self.script_path(name), + os.path.join(os.path.join(os.path.join(self.path, ".Trash"), "scripts"), name), + ) self.scripts.remove(name) def reset_project(self): @@ -307,6 +323,21 @@ def reset_project(self): raw_metadata = json.load(f) self.scripts = [script["name"] for script in raw_metadata["scripts"]] + for script in self.scripts: + if not os.path.exists(self.script_path(script, check=False)): + if not os.path.exists( + os.path.join(os.path.join(os.path.join(self.path, ".Trash"), "scripts"), script) + ): + raise AttributeError( + f"Trying to restore script {script} but the file is missing from .Trash" + ) + else: + os.rename( + os.path.join( + os.path.join(os.path.join(self.path, ".Trash"), "scripts"), script + ), + self.script_path(script, check=False), + ) self.binaries = {} @@ -314,6 +345,24 @@ def reset_project(self): self.binaries[info["name"]] = _OfrakProjectBinary( info["associated_scripts"], info.get("init_script") ) + for binary in self.binaries.keys(): + if not os.path.exists(self.binary_path(binary, check=False)): + if not os.path.exists( + os.path.join( + os.path.join(os.path.join(self.path, ".Trash"), "binaries"), binary + ) + ): + raise AttributeError( + f"Trying to restore binary {binary} but the file is missing from .Trash" + ) + else: + os.rename( + os.path.join( + os.path.join(os.path.join(self.path, ".Trash"), "scripts"), script + ), + self.binary_path(script, check=False), + ) + self.name = raw_metadata["name"] self.project_id = binascii.unhexlify(raw_metadata["project_id"]) From 1ba884a00e411b99f8696be03d9368611967327a Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 4 Aug 2023 14:53:07 -0400 Subject: [PATCH 38/63] remove leading / --- frontend/src/ProjectManager/ProjectManagerToolbar.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte index 61506c052..28e6ae888 100644 --- a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte +++ b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte @@ -56,7 +56,7 @@ iconUrl: "/icons/reset.svg", shortcut: "r", onclick: async (e) => { - await fetch(`/${$settings.backendUrl}/reset_project`, { + await fetch(`${$settings.backendUrl}/reset_project`, { method: "POST", body: JSON.stringify({ id: $selectedProject.session_id, From 5563210ed8ac99083c05132b12451aba90d7a876 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 4 Aug 2023 14:56:15 -0400 Subject: [PATCH 39/63] another leading slash --- frontend/src/ProjectManager/ProjectManagerToolbar.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte index 28e6ae888..20411e9ee 100644 --- a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte +++ b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte @@ -43,7 +43,7 @@ iconUrl: "/icons/disk.svg", shortcut: "s", onclick: async (e) => { - await fetch(`/${$settings.backendUrl}/save_project_data`, { + await fetch(`${$settings.backendUrl}/save_project_data`, { method: "POST", body: JSON.stringify({ id: $selectedProject.session_id, From 19587ec3a79c25725a00bee834729636a8e65d86 Mon Sep 17 00:00:00 2001 From: edward Date: Fri, 4 Aug 2023 14:59:41 -0400 Subject: [PATCH 40/63] postmerge cleanups --- .../ProjectManagerBinarySelector.svelte | 44 ------------------ .../ProjectManagerScriptSelector.svelte | 45 ------------------- .../ProjectManagerToolbar.svelte | 2 +- .../ProjectManager/ProjectManagerView.svelte | 31 +++++++++---- 4 files changed, 24 insertions(+), 98 deletions(-) delete mode 100644 frontend/src/ProjectManager/ProjectManagerBinarySelector.svelte delete mode 100644 frontend/src/ProjectManager/ProjectManagerScriptSelector.svelte diff --git a/frontend/src/ProjectManager/ProjectManagerBinarySelector.svelte b/frontend/src/ProjectManager/ProjectManagerBinarySelector.svelte deleted file mode 100644 index fe4b854c7..000000000 --- a/frontend/src/ProjectManager/ProjectManagerBinarySelector.svelte +++ /dev/null @@ -1,44 +0,0 @@ - - - - -
-
- {#each projectElementOptions as projectOption} -
- -
- {/each} -
-
diff --git a/frontend/src/ProjectManager/ProjectManagerScriptSelector.svelte b/frontend/src/ProjectManager/ProjectManagerScriptSelector.svelte deleted file mode 100644 index 0095781cc..000000000 --- a/frontend/src/ProjectManager/ProjectManagerScriptSelector.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - - - -
-
- {#each projectElementOptions as projectOption} -
- -
- {/each} -
-
diff --git a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte index c5088a87f..74143089a 100644 --- a/frontend/src/ProjectManager/ProjectManagerToolbar.svelte +++ b/frontend/src/ProjectManager/ProjectManagerToolbar.svelte @@ -54,7 +54,7 @@ iconUrl: "/icons/reset.svg", shortcut: "r", onclick: async (e) => { - await fetch(`/${$settings.backendUrl}/reset_project`, { + await fetch(`${$settings.backendUrl}/reset_project`, { method: "POST", body: JSON.stringify({ id: $selectedProject.session_id, diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 74106155c..ac522c721 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -60,10 +60,12 @@ import ProjectManagerMainOptions from "./ProjectManagerMainOptions.svelte"; import { onMount } from "svelte"; import ProjectManagerCheckbox from "./ProjectManagerCheckbox.svelte"; + import ProjectManagerScriptOptions from "./ProjectManagerScriptOptions.svelte"; let focus, selectedBinaryName, - binaryFocus, + focusBinary, + focusScript, selectedScript = null; let binariesForProject = []; @@ -97,7 +99,6 @@ showRootResource = true; } - onMount(async () => { focus = { object: ProjectManagerMainOptions, @@ -106,9 +107,23 @@ }); $: rootResourceLoadPromise = openProject; $: { - focus = binaryFocus; - selectedBinaryName = binaryFocus; - binaryFocus = undefined; + focus = { + object: ProjectManagerScriptOptions, + args: { + name: focusBinary, + }, + }; + selectedBinaryName = focusBinary; + focusBinary = undefined; + } + $: { + focus = { + object: ProjectManagerScriptOptions, + args: { + name: focusScript, + }, + }; + focusScript = undefined; } @@ -137,7 +152,7 @@
{/each} @@ -162,12 +177,12 @@ bind:selection="{$selectedProject.binaries[ selectedBinaryName ].associated_scripts}" - bind:focus="{focus}" + bind:focus="{focusScript}" /> {:else} {/if} From df8fb03041bae89a2fa47fd7b2507989e51fda3c Mon Sep 17 00:00:00 2001 From: edward Date: Fri, 4 Aug 2023 15:00:08 -0400 Subject: [PATCH 41/63] remove unused imports --- frontend/src/ProjectManager/ProjectManagerView.svelte | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index ac522c721..6f33f0210 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -50,8 +50,6 @@ import Split from "../Split.svelte"; import ProjectManagerFocusableLabel from "./ProjectManagerFocusableLabel.svelte"; import ProjectManagerOptions from "./ProjectManagerOptions.svelte"; - import ProjectManagerBinarySelector from "./ProjectManagerBinarySelector.svelte"; - import ProjectManagerScriptSelector from "./ProjectManagerScriptSelector.svelte"; import { selectedProject, settings, selected } from "../stores"; import { remote_model_to_resource } from "../ofrak/remote_resource"; import ProjectManagerToolbar from "./ProjectManagerToolbar.svelte"; From 7b81048bbcbd3007584e6dacde7ab7630599d128 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 4 Aug 2023 15:12:47 -0400 Subject: [PATCH 42/63] oops --- ofrak_core/ofrak/gui/server.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index bcb2c42ee..bb1930b21 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -1152,7 +1152,6 @@ async def save_project_data(self, request: Request) -> Response: return json_response([]) @exceptions_to_http(SerializedError) -<<<<<<< HEAD async def delete_binary_from_project(self, request: Request) -> Response: body = await request.json() id = body["id"] @@ -1169,7 +1168,6 @@ async def delete_script_from_project(self, request: Request) -> Response: project = self._get_project_by_id(id) project.delete_script(script_name) return json_response([]) -======= async def get_project_script(self, request: Request) -> Response: project_id = request.query.get("project") script_name = request.query.get("script") @@ -1177,7 +1175,6 @@ async def get_project_script(self, request: Request) -> Response: script_body = project.get_script_body(script_name) return Response(text=script_body) ->>>>>>> 0a113db71428c57666b1bc06097386c41ab5c23c def _slurp_projects_from_dir(self) -> None: self.projects = set() From be0b6f000c3b7f09fdedcd4707964c04da2524d0 Mon Sep 17 00:00:00 2001 From: Dan Pesce Date: Fri, 4 Aug 2023 15:34:45 -0400 Subject: [PATCH 43/63] Do mypy's bidding --- ofrak_core/ofrak/gui/server.py | 38 +++++++++++++++++++---------- ofrak_core/ofrak/project/project.py | 4 ++- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index bb1930b21..22cceb2d3 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -1036,7 +1036,7 @@ async def search_data(self, request: Request) -> Response: @exceptions_to_http(SerializedError) async def create_new_project(self, request: Request) -> Response: if self.projects is None: - self._slurp_projects_from_dir() + self.projects = self._slurp_projects_from_dir() body = await request.json() name = body.get("name") project = OfrakProject.create(name, os.path.join(self.projects_dir, name)) @@ -1047,7 +1047,7 @@ async def create_new_project(self, request: Request) -> Response: @exceptions_to_http(SerializedError) async def clone_project_from_git(self, request: Request) -> Response: if self.projects is None: - self._slurp_projects_from_dir() + self.projects = self._slurp_projects_from_dir() def recurse_path_collisions(path: str, count: int) -> str: if count == 0: @@ -1078,7 +1078,7 @@ async def get_project_by_id(self, request: Request) -> Response: @exceptions_to_http(SerializedError) async def get_all_projects(self, request: Request) -> Response: if self.projects is None: - self._slurp_projects_from_dir() + self.projects = self._slurp_projects_from_dir() return json_response([project.get_current_metadata() for project in self.projects]) @exceptions_to_http(SerializedError) @@ -1092,7 +1092,9 @@ async def reset_project(self, request: Request) -> Response: @exceptions_to_http(SerializedError) async def add_binary_to_project(self, request: Request) -> Response: id = request.query.get("id") - name = request.query.get("name") + name_query = request.query.get("name") + if name_query is not None: + name = name_query data = await request.read() project = self._get_project_by_id(id) project.add_binary(name, data) @@ -1101,7 +1103,9 @@ async def add_binary_to_project(self, request: Request) -> Response: @exceptions_to_http(SerializedError) async def add_script_to_project(self, request: Request) -> Response: id = request.query.get("id") - name = request.query.get("name") + name_query = request.query.get("name") + if name_query is not None: + name = name_query data = await request.read() project = self._get_project_by_id(id) project.add_script(name, data.decode()) @@ -1113,9 +1117,13 @@ async def open_project(self, request: Request) -> Response: id = body["id"] binary = body["binary"] script = body["script"] + if request.remote is not None: + resource_id = request.remote + else: + raise AttributeError("No resource ID provided") project = self._get_project_by_id(id) resource = await project.init_adventure_binary(binary, script, self._ofrak_context) - self._job_ids[request.remote] = resource.get_job_id() + self._job_ids[resource_id] = resource.get_job_id() return json_response(self._serialize_resource(resource)) @exceptions_to_http(SerializedError) @@ -1129,7 +1137,7 @@ async def set_projects_path(self, request: Request) -> Response: if not os.path.exists(new_path): os.mkdir(new_path) self.projects_dir = new_path - self._slurp_projects_from_dir() + self.projects = self._slurp_projects_from_dir() return json_response(self.projects_dir) @exceptions_to_http(SerializedError) @@ -1168,28 +1176,32 @@ async def delete_script_from_project(self, request: Request) -> Response: project = self._get_project_by_id(id) project.delete_script(script_name) return json_response([]) + async def get_project_script(self, request: Request) -> Response: project_id = request.query.get("project") - script_name = request.query.get("script") + script_name_query = request.query.get("script") + if script_name_query is not None: + script_name = script_name_query project = self._get_project_by_id(project_id) script_body = project.get_script_body(script_name) return Response(text=script_body) - def _slurp_projects_from_dir(self) -> None: - self.projects = set() + def _slurp_projects_from_dir(self) -> Set: + projects = set() if not os.path.exists(self.projects_dir): os.makedirs(self.projects_dir) for dir in os.listdir(self.projects_dir): try: project = OfrakProject.init_from_path(os.path.join(self.projects_dir, dir)) - self.projects.add(project) + projects.add(project) except: pass + return projects def _get_project_by_name(self, name) -> Optional[OfrakProject]: if self.projects is None: - self._slurp_projects_from_dir() + self.projects = self._slurp_projects_from_dir() result = [project for project in self.projects if project.name == name] if len(result) > 1: raise AttributeError("Project Name Collision") @@ -1199,7 +1211,7 @@ def _get_project_by_name(self, name) -> Optional[OfrakProject]: def _get_project_by_id(self, id) -> OfrakProject: if self.projects is None: - self._slurp_projects_from_dir() + self.projects = self._slurp_projects_from_dir() result = [project for project in self.projects if project.session_id.hex() == id] if len(result) > 1: raise AttributeError("Project ID Collision") diff --git a/ofrak_core/ofrak/project/project.py b/ofrak_core/ofrak/project/project.py index 62fb5191c..cf755ec37 100644 --- a/ofrak_core/ofrak/project/project.py +++ b/ofrak_core/ofrak/project/project.py @@ -275,7 +275,9 @@ def add_script(self, name: str, script_contents: str): with open(self.script_path(name, check=False), "w+") as f: f.write(script_contents) - def update_binary_data(self, name: str, init: str = None, associated: List[str] = None): + def update_binary_data( + self, name: str, init: Optional[str] = None, associated: Optional[List[str]] = None + ): binary = self._get_binary(name) if init is not None: binary.init_script = init From c290a713a91cbeb972b3c56f03d26dd7d57a94c2 Mon Sep 17 00:00:00 2001 From: edward Date: Fri, 4 Aug 2023 18:20:59 -0400 Subject: [PATCH 44/63] make associated script checkboxes work with script reset --- .../ProjectManagerCheckbox.svelte | 7 ++++--- .../ProjectManagerToolbar.svelte | 3 ++- .../ProjectManager/ProjectManagerView.svelte | 20 +++++++++++-------- ofrak_core/ofrak/project/project.py | 4 ++-- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte index 2d2817aa7..f5847c5e0 100644 --- a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte +++ b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte @@ -26,9 +26,10 @@ selection = undefined, focus; let checked = selection?.includes(option); + let userChecked; - $: if (selection !== undefined) { - if (checked && !selection.includes(option)) { + $: if (selection !== undefined && userChecked !== undefined) { + if (userChecked && !selection.includes(option)) { selection.push(option); } else { const idx = selection.indexOf(option); @@ -42,7 +43,7 @@
{#if selection !== undefined} - + {/if}
diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 27efaa6f0..3558e9f7c 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -59,7 +59,6 @@ import { onMount } from "svelte"; import ProjectManagerCheckbox from "./ProjectManagerCheckbox.svelte"; import ProjectManagerScriptOptions from "./ProjectManagerScriptOptions.svelte"; - import ExclusiveCheckbox from "../ExclusiveCheckbox.svelte"; let focus, selectedBinaryName, @@ -150,7 +149,7 @@ {#each binariesForProject as binaryName}
@@ -173,24 +172,19 @@
{#if selectedBinaryName} {#key forceRefreshProject} - {/key} {:else} {/if} From a00f44641fcb490e4ef41ffb5fed7c003bd50e6b Mon Sep 17 00:00:00 2001 From: edward Date: Fri, 4 Aug 2023 20:25:39 -0400 Subject: [PATCH 48/63] add some on-hover hints for checkboxes, rename "Run" to "Launch" --- .../ProjectManagerCheckbox.svelte | 27 ++++++++++++++++--- .../ProjectManagerToolbar.svelte | 6 ++--- .../ProjectManager/ProjectManagerView.svelte | 25 ++++++++++++++++- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte index bcb6abe5d..223f9ba46 100644 --- a/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte +++ b/frontend/src/ProjectManager/ProjectManagerCheckbox.svelte @@ -30,7 +30,8 @@ export let ownValue, inclusiveSelectionGroup = undefined, exclusiveSelectionValue = undefined, - focus; + focus, + mouseoverInfo = {}; let inclusiveCheckboxChecked; $: if ( @@ -55,7 +56,17 @@
{#if inclusiveSelectionGroup !== undefined} - + {/if} {#if exclusiveSelectionValue !== undefined} - + { await fetch(`${$settings.backendUrl}/reset_project`, { method: "POST", diff --git a/frontend/src/ProjectManager/ProjectManagerView.svelte b/frontend/src/ProjectManager/ProjectManagerView.svelte index 3558e9f7c..5f18b3b1c 100644 --- a/frontend/src/ProjectManager/ProjectManagerView.svelte +++ b/frontend/src/ProjectManager/ProjectManagerView.svelte @@ -43,6 +43,12 @@ width: 100%; overflow: auto; } + + .hint { + font-size: medium; + height: 1em; + margin-bottom: 1em; + }