mirror of
https://github.com/CERT-Polska/drakvuf-sandbox.git
synced 2026-10-11 22:00:00 +00:00
Offline HTML analysis reports (#1158)
This commit is contained in:
@@ -3,6 +3,7 @@ from drakrun.lib.paths import DUMPS_DIR, DUMPS_ZIP, IPT_DIR, IPT_ZIP
|
||||
from .build_process_tree import build_process_tree
|
||||
from .capa_plugin.capa_processor import capa_analysis
|
||||
from .compress_ipt import compress_ipt
|
||||
from .generate_html_report import generate_html_report
|
||||
from .generate_report import generate_report
|
||||
from .generate_wireshark_key_file import generate_wireshark_key_file
|
||||
from .get_http_info import get_http_info
|
||||
@@ -85,6 +86,11 @@ POSTPROCESS_PLUGINS = [
|
||||
requires=[],
|
||||
generates=[],
|
||||
),
|
||||
PostprocessPlugin(
|
||||
function=generate_html_report,
|
||||
requires=["report.json"],
|
||||
generates=["report.html"],
|
||||
),
|
||||
PostprocessPlugin(
|
||||
function=index_logs, requires=["process_tree.json"], generates=["log_index"]
|
||||
),
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
|
||||
from drakrun.lib.paths import PACKAGE_DIR
|
||||
|
||||
from .plugin_base import PostprocessContext
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
HTML_TEMPLATE = PACKAGE_DIR / "web/frontend/dist/embedded/index.html"
|
||||
OFFLINE_FILES_PLACEHOLDER = "window.OFFLINE_FILES = {};"
|
||||
|
||||
|
||||
def png_bytes_to_data_uri(png_bytes: bytes):
|
||||
encoded = base64.b64encode(png_bytes).decode("ascii")
|
||||
return f"data:image/png;base64,{encoded}"
|
||||
|
||||
|
||||
def generate_html_report(context: PostprocessContext) -> None:
|
||||
offline_files = {
|
||||
"metadata.json": {
|
||||
**context.metadata.store_to_dict(),
|
||||
**context.extra_metadata,
|
||||
}
|
||||
}
|
||||
|
||||
report_file = context.analysis_dir / "report.json"
|
||||
with report_file.open("r") as f:
|
||||
offline_files["report.json"] = json.load(f)
|
||||
|
||||
process_tree_file = context.analysis_dir / "process_tree.json"
|
||||
if process_tree_file.exists():
|
||||
with process_tree_file.open("r") as f:
|
||||
offline_files["process_tree.json"] = json.load(f)
|
||||
|
||||
offline_files["screenshots"] = []
|
||||
screenshots_count = offline_files["metadata.json"].get("screenshots", 0)
|
||||
for which in range(screenshots_count):
|
||||
with (context.analysis_dir / f"screenshots/screenshot_{which+1}.png").open(
|
||||
"rb"
|
||||
) as f:
|
||||
screenshot_data_uri = png_bytes_to_data_uri(f.read())
|
||||
offline_files["screenshots"].append(screenshot_data_uri)
|
||||
|
||||
html_report = HTML_TEMPLATE.read_text().replace(
|
||||
OFFLINE_FILES_PLACEHOLDER, f"window.OFFLINE_FILES={json.dumps(offline_files)};"
|
||||
)
|
||||
(context.analysis_dir / "report.html").write_text(html_report)
|
||||
context.update_metadata({"html_report": True})
|
||||
@@ -389,3 +389,15 @@ def screenshot(path: ScreenshotRequestPath):
|
||||
mimetype="image/png",
|
||||
s3_config=config.s3,
|
||||
)
|
||||
|
||||
|
||||
@api.get("/html/<task_uid>")
|
||||
def get_html_report(path: AnalysisRequestPath):
|
||||
task_uid = path.task_uid
|
||||
return send_analysis_file(
|
||||
task_uid,
|
||||
"report.html",
|
||||
mimetype="text/html",
|
||||
s3_config=config.s3,
|
||||
download_name=f"report-{task_uid}.html",
|
||||
)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>DRAKVUF Sandbox</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="../src/html_report_main.jsx"></script>
|
||||
<script>
|
||||
window.OFFLINE_FILES = {};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,45 @@
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { viteSingleFile } from "vite-plugin-singlefile";
|
||||
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
|
||||
import { gzipSync } from "node:zlib";
|
||||
|
||||
function viteGzipBundle() {
|
||||
return {
|
||||
name: "vite:gzip-bundle-plugin",
|
||||
apply: "build",
|
||||
enforce: "post",
|
||||
generateBundle(_, bundle) {
|
||||
for (const [fileName, chunk] of Object.entries(bundle)) {
|
||||
if (chunk.type === "chunk" && fileName.endsWith(".js")) {
|
||||
console.log("[gzip] ", fileName);
|
||||
const originalCode = chunk.code;
|
||||
const gzipped = gzipSync(
|
||||
Buffer.from(originalCode, "utf-8"),
|
||||
);
|
||||
const base64 = gzipped.toString("base64");
|
||||
const loader = `await import(URL.createObjectURL(new Blob([await new Response((await fetch('data:;base64,${base64}')).body.pipeThrough(new DecompressionStream('gzip'))).text()],{type:'application/javascript'})))`;
|
||||
chunk.code = loader;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
root: "./embedded",
|
||||
plugins: [
|
||||
react(),
|
||||
cssInjectedByJsPlugin(),
|
||||
viteGzipBundle(),
|
||||
viteSingleFile(),
|
||||
],
|
||||
define: {
|
||||
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
|
||||
},
|
||||
build: {
|
||||
outDir: "../dist/embedded",
|
||||
emptyOutDir: true,
|
||||
},
|
||||
});
|
||||
Generated
+305
-92
@@ -36,7 +36,9 @@
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.19",
|
||||
"globals": "^16.0.0",
|
||||
"vite": "^6.4.1"
|
||||
"vite": "^6.4.1",
|
||||
"vite-plugin-css-injected-by-js": "^3.5.2",
|
||||
"vite-plugin-singlefile": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
@@ -79,6 +81,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
|
||||
"integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
@@ -1010,6 +1013,7 @@
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
|
||||
"integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
||||
},
|
||||
@@ -1195,260 +1199,350 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz",
|
||||
"integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz",
|
||||
"integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz",
|
||||
"integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz",
|
||||
"integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz",
|
||||
"integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz",
|
||||
"integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz",
|
||||
"integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz",
|
||||
"integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz",
|
||||
"integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz",
|
||||
"integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz",
|
||||
"integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz",
|
||||
"integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz",
|
||||
"integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz",
|
||||
"integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz",
|
||||
"integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz",
|
||||
"integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz",
|
||||
"integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz",
|
||||
"integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz",
|
||||
"integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz",
|
||||
"integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz",
|
||||
"integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==",
|
||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz",
|
||||
"integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz",
|
||||
"integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==",
|
||||
"node_modules/@rollup/rollup-linux-loong64-musl": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz",
|
||||
"integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz",
|
||||
"integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-musl": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz",
|
||||
"integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz",
|
||||
"integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz",
|
||||
"integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz",
|
||||
"integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz",
|
||||
"integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz",
|
||||
"integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz",
|
||||
"integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz",
|
||||
"integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz",
|
||||
"integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz",
|
||||
"integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz",
|
||||
"integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz",
|
||||
"integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==",
|
||||
"node_modules/@rollup/rollup-openbsd-x64": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz",
|
||||
"integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz",
|
||||
"integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz",
|
||||
"integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz",
|
||||
"integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz",
|
||||
"integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz",
|
||||
"integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz",
|
||||
"integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz",
|
||||
"integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@@ -1496,10 +1590,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
|
||||
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
|
||||
"dev": true
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
@@ -1516,6 +1611,7 @@
|
||||
"version": "19.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.2.tgz",
|
||||
"integrity": "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
@@ -1561,6 +1657,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -1679,6 +1776,19 @@
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.24.4",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
|
||||
@@ -1698,6 +1808,7 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001688",
|
||||
"electron-to-chromium": "^1.5.73",
|
||||
@@ -2035,6 +2146,7 @@
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz",
|
||||
"integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -2248,6 +2360,19 @@
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/find-root": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
|
||||
@@ -2574,6 +2699,16 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
@@ -2755,6 +2890,33 @@
|
||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
|
||||
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/micromatch/node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
@@ -2958,6 +3120,7 @@
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -3049,6 +3212,7 @@
|
||||
"version": "19.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
||||
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -3057,6 +3221,7 @@
|
||||
"version": "19.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
||||
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"scheduler": "^0.26.0"
|
||||
},
|
||||
@@ -3235,12 +3400,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.40.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz",
|
||||
"integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==",
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz",
|
||||
"integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.7"
|
||||
"@types/estree": "1.0.8"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
@@ -3250,26 +3417,31 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.40.0",
|
||||
"@rollup/rollup-android-arm64": "4.40.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.40.0",
|
||||
"@rollup/rollup-darwin-x64": "4.40.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.40.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.40.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.40.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.40.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.40.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.40.0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.40.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.40.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.40.0",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.40.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.40.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.40.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.40.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.40.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.40.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.40.0",
|
||||
"@rollup/rollup-android-arm-eabi": "4.57.1",
|
||||
"@rollup/rollup-android-arm64": "4.57.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.57.1",
|
||||
"@rollup/rollup-darwin-x64": "4.57.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.57.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.57.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.57.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.57.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.57.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.57.1",
|
||||
"@rollup/rollup-linux-loong64-gnu": "4.57.1",
|
||||
"@rollup/rollup-linux-loong64-musl": "4.57.1",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.57.1",
|
||||
"@rollup/rollup-linux-ppc64-musl": "4.57.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.57.1",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.57.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.57.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.57.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.57.1",
|
||||
"@rollup/rollup-openbsd-x64": "4.57.1",
|
||||
"@rollup/rollup-openharmony-arm64": "4.57.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.57.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.57.1",
|
||||
"@rollup/rollup-win32-x64-gnu": "4.57.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.57.1",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
@@ -3426,6 +3598,19 @@
|
||||
"url": "https://github.com/sponsors/SuperchupuDev"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
@@ -3530,6 +3715,7 @@
|
||||
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.4",
|
||||
@@ -3599,6 +3785,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-css-injected-by-js": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.2.tgz",
|
||||
"integrity": "sha512-2MpU/Y+SCZyWUB6ua3HbJCrgnF0KACAsmzOQt1UvRVJCGF6S8xdA3ZUhWcWdM9ivG4I5az8PnQmwwrkC2CAQrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"vite": ">2.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-singlefile": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-singlefile/-/vite-plugin-singlefile-2.3.0.tgz",
|
||||
"integrity": "sha512-DAcHzYypM0CasNLSz/WG0VdKOCxGHErfrjOoyIPiNxTPTGmO6rRD/te93n1YL/s+miXq66ipF1brMBikf99c6A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"micromatch": "^4.0.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^4.44.1",
|
||||
"vite": "^5.4.11 || ^6.0.0 || ^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"build": "vite build && vite build --config embedded_report.vite.config.js",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
@@ -38,7 +38,9 @@
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.19",
|
||||
"globals": "^16.0.0",
|
||||
"vite": "^6.4.1"
|
||||
"vite": "^6.4.1",
|
||||
"vite-plugin-css-injected-by-js": "^3.5.2",
|
||||
"vite-plugin-singlefile": "^2.3.0"
|
||||
},
|
||||
"prettier": {
|
||||
"tabWidth": 4
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import {
|
||||
getAnalysisSummary,
|
||||
getLog,
|
||||
getLogList,
|
||||
getProcessInfo,
|
||||
getProcessLog,
|
||||
} from "./api.js";
|
||||
import { getLog, getLogList, getProcessLog } from "./api.js";
|
||||
import { TabSwitcher, Tab, useTabContext } from "./TabSwitcher.jsx";
|
||||
import { getLogLoader, LogViewer } from "./LogViewer.jsx";
|
||||
import { AnalysisMetadataTable } from "./AnalysisMetadataTable.jsx";
|
||||
@@ -19,6 +13,7 @@ import axios, { CanceledError } from "axios";
|
||||
import { AnalysisSummary } from "./AnalysisSummary.jsx";
|
||||
import { ProcessBadge } from "./ProcessBadge.jsx";
|
||||
import { AnalysisFilesViewer } from "./AnalysisFiles.jsx";
|
||||
import { useAnalysisReport } from "./AnalysisReportContext.jsx";
|
||||
|
||||
export function AnalysisLogViewerTab({ analysisId }) {
|
||||
const logType = useTabContext()?.activeTab;
|
||||
@@ -136,6 +131,7 @@ function ProcessLogViewer({ analysisId, selectedProcess }) {
|
||||
const [activeTab, setActiveTab] = useState();
|
||||
const [processInfo, setProcessInfo] = useState();
|
||||
const [error, setError] = useState();
|
||||
const { getProcessInfo, isOffline } = useAnalysisReport();
|
||||
const loadProcessInfo = useCallback(
|
||||
async (processSeqId) => {
|
||||
try {
|
||||
@@ -194,11 +190,15 @@ function ProcessLogViewer({ analysisId, selectedProcess }) {
|
||||
selectedProcess={selectedProcess}
|
||||
processInfo={processInfo}
|
||||
/>
|
||||
<ProcessLogViewerTab
|
||||
analysisId={analysisId}
|
||||
selectedProcess={selectedProcess}
|
||||
processInfo={processInfo}
|
||||
/>
|
||||
{!isOffline ? (
|
||||
<ProcessLogViewerTab
|
||||
analysisId={analysisId}
|
||||
selectedProcess={selectedProcess}
|
||||
processInfo={processInfo}
|
||||
/>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
</TabSwitcher>
|
||||
</div>
|
||||
</div>
|
||||
@@ -220,6 +220,7 @@ function AnalysisReportTabs({
|
||||
setSelectedProcess,
|
||||
activeReportTab,
|
||||
setActiveReportTab,
|
||||
isOffline,
|
||||
}) {
|
||||
const getHeader = useCallback(
|
||||
(tab) => {
|
||||
@@ -256,9 +257,13 @@ function AnalysisReportTabs({
|
||||
setSelectedProcess={setSelectedProcess}
|
||||
/>
|
||||
</PaddedTab>
|
||||
<PaddedTab tab="General logs">
|
||||
<AnalysisLogViewer analysisId={analysis.id} />
|
||||
</PaddedTab>
|
||||
{!isOffline ? (
|
||||
<PaddedTab tab="General logs">
|
||||
<AnalysisLogViewer analysisId={analysis.id} />
|
||||
</PaddedTab>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
<PaddedTab tab="Process info">
|
||||
<ProcessLogViewer
|
||||
analysisId={analysis.id}
|
||||
@@ -270,19 +275,28 @@ function AnalysisReportTabs({
|
||||
<AnalysisScreenshotViewer analysis={analysis} />
|
||||
</PaddedTab>
|
||||
) : null}
|
||||
<PaddedTab tab="Analysis files">
|
||||
<AnalysisFilesViewer analysisId={analysis.id} />
|
||||
</PaddedTab>
|
||||
{!isOffline ? (
|
||||
<PaddedTab tab="Analysis files">
|
||||
<AnalysisFilesViewer analysisId={analysis.id} />
|
||||
</PaddedTab>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
</TabSwitcher>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function AnalysisReport({ analysis }) {
|
||||
export function AnalysisReport() {
|
||||
const [selectedProcess, setSelectedProcess] = useState();
|
||||
const [activeReportTab, setActiveReportTab] = useState();
|
||||
const [analysisSummary, setAnalysisSummary] = useState();
|
||||
const {
|
||||
analysisInfo: analysis,
|
||||
getAnalysisSummary,
|
||||
isOffline,
|
||||
} = useAnalysisReport();
|
||||
const plugins = analysis.options?.plugins;
|
||||
const baseUrl = axios.defaults.baseURL;
|
||||
const analysisId = analysis.id;
|
||||
@@ -298,7 +312,7 @@ export function AnalysisReport({ analysis }) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
}, [analysisId]);
|
||||
}, [analysisId, getAnalysisSummary]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchSummary();
|
||||
@@ -324,47 +338,66 @@ export function AnalysisReport({ analysis }) {
|
||||
</div>
|
||||
<div className="col-6">
|
||||
<AnalysisMetadataTable analysis={analysis} />
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<a href={`${baseUrl}/pcap_file/${analysis.id}`}>
|
||||
<button className="btn btn-primary m-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faDownload}
|
||||
className="me-2"
|
||||
/>
|
||||
Download PCAP
|
||||
</button>
|
||||
</a>
|
||||
{Array.isArray(plugins) &&
|
||||
plugins.includes("tlsmon") ? (
|
||||
<a href={`${baseUrl}/pcap_keys/${analysis.id}`}>
|
||||
{!isOffline ? (
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<a href={`${baseUrl}/pcap_file/${analysis.id}`}>
|
||||
<button className="btn btn-primary m-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faDownload}
|
||||
className="me-2"
|
||||
/>
|
||||
TLS keys
|
||||
Download PCAP
|
||||
</button>
|
||||
</a>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
{Array.isArray(plugins) &&
|
||||
plugins.includes("memdump") ? (
|
||||
<a href={`${baseUrl}/dumps/${analysis.id}`}>
|
||||
<button className="btn btn-primary m-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faDownload}
|
||||
className="me-2"
|
||||
/>
|
||||
Memory dumps
|
||||
</button>
|
||||
</a>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
{Array.isArray(plugins) &&
|
||||
plugins.includes("tlsmon") ? (
|
||||
<a
|
||||
href={`${baseUrl}/pcap_keys/${analysis.id}`}
|
||||
>
|
||||
<button className="btn btn-primary m-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faDownload}
|
||||
className="me-2"
|
||||
/>
|
||||
TLS keys
|
||||
</button>
|
||||
</a>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
{Array.isArray(plugins) &&
|
||||
plugins.includes("memdump") ? (
|
||||
<a href={`${baseUrl}/dumps/${analysis.id}`}>
|
||||
<button className="btn btn-primary m-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faDownload}
|
||||
className="me-2"
|
||||
/>
|
||||
Memory dumps
|
||||
</button>
|
||||
</a>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
{analysis["html_report"] ? (
|
||||
<a href={`${baseUrl}/html/${analysis.id}`}>
|
||||
<button className="btn btn-primary m-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faDownload}
|
||||
className="me-2"
|
||||
/>
|
||||
HTML report
|
||||
</button>
|
||||
</a>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
[]
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="row py-4">
|
||||
@@ -376,6 +409,7 @@ export function AnalysisReport({ analysis }) {
|
||||
setSelectedProcess={onSelectProcess}
|
||||
activeReportTab={activeReportTab}
|
||||
setActiveReportTab={setActiveReportTab}
|
||||
isOffline={isOffline}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import React, { useContext, useMemo } from "react";
|
||||
import {
|
||||
getAnalysisSummary,
|
||||
getProcessInfo,
|
||||
getAnalysisProcessTree,
|
||||
} from "./api.js";
|
||||
|
||||
const AnalysisReportContext = React.createContext({});
|
||||
|
||||
let BASE_URL = "";
|
||||
if (import.meta.env.VITE_API_SERVER) {
|
||||
BASE_URL = import.meta.env.VITE_API_SERVER;
|
||||
} else {
|
||||
BASE_URL = "/api";
|
||||
}
|
||||
|
||||
export function useAnalysisReport() {
|
||||
return useContext(AnalysisReportContext);
|
||||
}
|
||||
|
||||
export function OnlineAnalysisReportProvider({ analysisInfo, children }) {
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
analysisInfo,
|
||||
getAnalysisSummary,
|
||||
getProcessInfo,
|
||||
getAnalysisProcessTree,
|
||||
getScreenshotURL: (analysis_id, screenshot_idx) =>
|
||||
`${BASE_URL}/screenshot/${analysis_id}/${screenshot_idx}`,
|
||||
isOffline: false,
|
||||
}),
|
||||
[analysisInfo],
|
||||
);
|
||||
return (
|
||||
<AnalysisReportContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</AnalysisReportContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function OfflineAnalysisReportProvider({ reportData, children }) {
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
analysisInfo: reportData["metadata.json"],
|
||||
getAnalysisSummary: () =>
|
||||
new Promise((resolve) => {
|
||||
resolve(reportData["report.json"]);
|
||||
}),
|
||||
getProcessInfo: ({ processSeqId }) =>
|
||||
new Promise((resolve) => {
|
||||
// Conversion between schemas if /api/report and /api/process_info
|
||||
const processes = reportData["report.json"].processes;
|
||||
const processInfo = processes[processSeqId];
|
||||
const ppid =
|
||||
processInfo["parent_seqid"] !== null
|
||||
? processes[processInfo["parent_seqid"]].pid
|
||||
: null;
|
||||
resolve({
|
||||
logs: {},
|
||||
process: {
|
||||
...processInfo,
|
||||
// evtid: We don't have it in report.json and don't need it
|
||||
// as we don't have offline logs for now. If needed, change
|
||||
// this code to fetch information from process_tree.json
|
||||
// instead of report.json (process_tree needs tree traversal)
|
||||
evtid_from: 0,
|
||||
evtid_to: 0,
|
||||
ppid: ppid,
|
||||
procname: processInfo["name"],
|
||||
ts_from: processInfo["started_at"],
|
||||
ts_to: processInfo["exited_at"],
|
||||
},
|
||||
});
|
||||
}),
|
||||
getAnalysisProcessTree: () =>
|
||||
new Promise((resolve) => {
|
||||
resolve(reportData["process_tree.json"]);
|
||||
}),
|
||||
getScreenshotURL: (analysis_id, screenshot_idx) =>
|
||||
reportData["screenshots"] &&
|
||||
reportData["screenshots"][screenshot_idx - 1],
|
||||
isOffline: true,
|
||||
}),
|
||||
[reportData],
|
||||
);
|
||||
return (
|
||||
<AnalysisReportContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</AnalysisReportContext.Provider>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +1,9 @@
|
||||
import Zoom from "react-medium-image-zoom";
|
||||
import "react-medium-image-zoom/dist/styles.css";
|
||||
|
||||
let BASE_URL = "";
|
||||
if (import.meta.env.VITE_API_SERVER) {
|
||||
BASE_URL = import.meta.env.VITE_API_SERVER;
|
||||
} else {
|
||||
BASE_URL = "/api";
|
||||
}
|
||||
import { useAnalysisReport } from "./AnalysisReportContext.jsx";
|
||||
|
||||
export function AnalysisScreenshotViewer({ analysis }) {
|
||||
const { getScreenshotURL } = useAnalysisReport();
|
||||
return (
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
@@ -18,7 +13,7 @@ export function AnalysisScreenshotViewer({ analysis }) {
|
||||
<Zoom>
|
||||
<img
|
||||
alt={`screenshot-${idx + 1}`}
|
||||
src={`${BASE_URL}/screenshot/${analysis.id}/${idx + 1}`}
|
||||
src={getScreenshotURL(analysis.id, idx + 1)}
|
||||
className="img-thumbnail"
|
||||
style={{ cursor: "pointer" }}
|
||||
/>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
AnalysisPendingStatusBox,
|
||||
} from "./AnalysisPendingView.jsx";
|
||||
import { AnalysisReport } from "./AnalysisReport.jsx";
|
||||
import { OnlineAnalysisReportProvider } from "./AnalysisReportContext.jsx";
|
||||
|
||||
function AnalysisViewComponent({ analysisId }) {
|
||||
const checkInterval = useRef(null);
|
||||
@@ -76,7 +77,11 @@ function AnalysisViewComponent({ analysisId }) {
|
||||
if (isStatusPending(analysisInfo?.status)) {
|
||||
return <AnalysisPendingView analysis={analysisInfo} />;
|
||||
}
|
||||
return <AnalysisReport analysis={analysisInfo} />;
|
||||
return (
|
||||
<OnlineAnalysisReportProvider analysisInfo={analysisInfo}>
|
||||
<AnalysisReport />
|
||||
</OnlineAnalysisReportProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AnalysisView() {
|
||||
|
||||
@@ -10,7 +10,7 @@ import AnalysisView from "./AnalysisView.jsx";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faFolder, faUpload, faGear } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
function AppHeader() {
|
||||
export function AppHeader() {
|
||||
return (
|
||||
<nav className="sb-topnav navbar navbar-expand navbar-dark bg-dark">
|
||||
<Link className="navbar-brand ps-3" to="/">
|
||||
@@ -65,7 +65,7 @@ function AppSidenav() {
|
||||
);
|
||||
}
|
||||
|
||||
function AppFooter() {
|
||||
export function AppFooter() {
|
||||
return (
|
||||
<footer className="py-4 bg-light mt-auto">
|
||||
<div className="container-fluid px-4">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { getAnalysisProcessTree } from "./api.js";
|
||||
import { ProcessTree } from "./ProcessTree.jsx";
|
||||
import { useAnalysisReport } from "./AnalysisReportContext.jsx";
|
||||
|
||||
function isProcessInteresting(process) {
|
||||
return process.procname.endsWith("explorer.exe");
|
||||
@@ -51,6 +51,7 @@ export function ProcessTreeView({
|
||||
const [uncollapsed, setUncollapsed] = useState(new Set());
|
||||
const [processTree, setProcessTree] = useState();
|
||||
const [error, setError] = useState();
|
||||
const { getAnalysisProcessTree } = useAnalysisReport();
|
||||
|
||||
useEffect(() => {
|
||||
getAnalysisProcessTree({ analysisId })
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import React, { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
|
||||
import "bootstrap";
|
||||
import "bootstrap/dist/css/bootstrap.css";
|
||||
import "./App.css";
|
||||
import "startbootstrap-sb-admin/dist/css/styles.css";
|
||||
|
||||
import { HashRouter } from "react-router-dom";
|
||||
import { AppHeader, AppFooter } from "./App";
|
||||
import { OfflineAnalysisReportProvider } from "./AnalysisReportContext.jsx";
|
||||
import { AnalysisReport } from "./AnalysisReport.jsx";
|
||||
|
||||
function EmbeddedReport() {
|
||||
return (
|
||||
<div className="container-fluid px-4">
|
||||
<h1 className="m-4 h4">Analysis report</h1>
|
||||
{window.OFFLINE_FILES ? (
|
||||
<OfflineAnalysisReportProvider
|
||||
reportData={window.OFFLINE_FILES}
|
||||
>
|
||||
<AnalysisReport />
|
||||
</OfflineAnalysisReportProvider>
|
||||
) : (
|
||||
"There are no analysis data embedded in the file"
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function EmbeddedReportApp() {
|
||||
return (
|
||||
<>
|
||||
<AppHeader />
|
||||
<div id="layoutSidenav">
|
||||
<div id="layoutSidenav_content">
|
||||
<main>
|
||||
<EmbeddedReport />
|
||||
</main>
|
||||
<AppFooter />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")).render(
|
||||
<StrictMode>
|
||||
<HashRouter>
|
||||
<EmbeddedReportApp />
|
||||
</HashRouter>
|
||||
</StrictMode>,
|
||||
);
|
||||
@@ -112,7 +112,7 @@ def get_s3_prefix(analysis_id):
|
||||
return "/".join([*analysis_id[0:4], analysis_id])
|
||||
|
||||
|
||||
def read_analysis_json(analysis_id: str, path: str, s3_config: S3StorageConfigSection):
|
||||
def read_analysis_file(analysis_id: str, path: str, s3_config: S3StorageConfigSection):
|
||||
if not is_s3_enabled(s3_config):
|
||||
base_path = ANALYSES_DIR / analysis_id
|
||||
path_to_file = check_path(base_path / path, base_path)
|
||||
@@ -131,7 +131,11 @@ def read_analysis_json(analysis_id: str, path: str, s3_config: S3StorageConfigSe
|
||||
raise FileNotFoundError from e
|
||||
else:
|
||||
raise
|
||||
return data
|
||||
|
||||
|
||||
def read_analysis_json(analysis_id: str, path: str, s3_config: S3StorageConfigSection):
|
||||
data = read_analysis_file(analysis_id, path, s3_config)
|
||||
parsed_data = json.loads(data)
|
||||
return parsed_data
|
||||
|
||||
|
||||
Reference in New Issue
Block a user