diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index fa1bc9d3..5cb562e5 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -47,13 +47,13 @@ jobs: if: matrix.info.os == 'ubuntu-24.04' run: git clone https://github.com/puffyCid/artemis.git && cd artemis/forensics && cargo build --release --examples && cp ../target/release/examples/script_tester ../../tests/linux && cp ../target/release/examples/script_tester ../../tests/applications - - name: Install esbuild macOS + - name: Install esbuild and colorama macOS if: matrix.info.os == 'macOS-latest' - run: brew install esbuild + run: brew install esbuild && pip3 install --break-system-packages --user colorama - - name: Install esbuild Linux + - name: Install esbuild and colorama Linux if: matrix.info.os == 'ubuntu-24.04' - run: sudo apt install esbuild + run: sudo apt install esbuild && pip3 install --break-system-packages --user colorama - name: Install esbuild Windows if: matrix.info.os == 'windows-latest' @@ -61,7 +61,7 @@ jobs: - name: Compile and run macOS tests if: matrix.info.os == 'macOS-latest' - run: cd tests/macos && sudo bash compile_tests.sh + run: cd tests/macos && sudo python3 compile_tests.py - name: Compile and run Windows tests if: matrix.info.os == 'windows-latest' @@ -69,8 +69,8 @@ jobs: - name: Compile and run Linux tests if: matrix.info.os == 'ubuntu-24.04' - run: cd tests/linux && sudo bash compile_tests.sh + run: cd tests/linux && sudo python3 compile_tests.py - name: Compile and run Application tests if: matrix.info.os == 'ubuntu-24.04' - run: cd tests/applications && sudo bash compile_tests.sh + run: cd tests/applications && sudo python3 compile_tests.py diff --git a/.gitignore b/.gitignore index 282ed272..34a342dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store tests/*/*/*.js *script_tester* -*node_modules* \ No newline at end of file +*node_modules* +*tmp* \ No newline at end of file diff --git a/README.md b/README.md index b3a2ccf4..6c5be25a 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ An in depth guide is documented at https://puffycid.github.io/artemis-api or [VSCode](https://code.visualstudio.com/) 2. Create a TypeScript file (ex: main.ts) 3. Import `artemis-api` into your project and start scripting! +4. Compile your script to JavaScript +5. Run with artemis! Basic example @@ -18,15 +20,32 @@ Basic example import { processListing } from "./artemis-api/mod"; function main() { - const md5 = true; + const md5 = false; const sha1 = false; const sha256 = false; - const binary_info = true; + const binary_info = false; const proc_list = processListing(md5, sha1, sha256, binary_info); + for(const entry of proc_list) { + console.log(`Process name is ${entry.name}`r); + } + return proc_list; } main(); ``` +> esbuild --bundle --outfile=main.js main.ts + +``` +> artemis -j main.js + +Process name is: mullvad-daemon +Process name is: codium +Process name is: electron +Process name is: bridge-gui +Process name is: syncthing +Process name is: artemis +... +``` diff --git a/artemis-docs/docs/API/API Scenarios/browsers.md b/artemis-docs/docs/API/API Scenarios/browsers.md new file mode 100644 index 00000000..11322e2d --- /dev/null +++ b/artemis-docs/docs/API/API Scenarios/browsers.md @@ -0,0 +1,216 @@ +--- +description: How to extract data from browsers +--- + +# Browswer Artifacts + +Artemis supports extracting forensic artifacts for a lot of different browser applications: + +- Chrome +- Edge +- Chromium +- FireFox +- Epiphany +- Falkon + +Example artifacts artemis supports include: URL history, cookies, bookmarks, preferences, and a lot more + +Using the API we can easily extract all supported artifacts and timeline them into a format that we can then easily upload to [Timesketch](https://timesketch.org/). + +## Retrospect + +The easiest want to extract browser artifacts is to use the API function `retrospect`. +This function has very similar capabilities as the tool [Hindsight](https://github.com/obsidianforensics/hindsight). +It will automatically parse and extract all supported artifacts from a provided browser application. + +An example is below: + +```typescript +import { Chrome, Format, Output, OutputType, PlatformType } from "./artemis-api/mod"; + +function main() { + // Change this if you are going to run on a different platform. + // Ex: Linux (PlatformType.Linux) or macOS (PlatformType.Darwin) + const plat = PlatformType.Windows; + + // If we acquired a user's Chrome profile + // We could also provide that as an alternative path + // Ex: /home/analyst/Downloads/user1_chrome + // This is optional + const alt_path = undefined; + // This is optional. The default value is false + const enable_unfold = false; + + // Initialize a Chrome application class + // By default this will extract Chrome artifacts for all users on the PlatformType + // This example will attempt to extract Chrome artifacts for the Platform.Type Windows + // If the alt_path != undefined. That will override the default Chrome paths for the provided platform + // Ex: If alt_path = "/home/analyst/Downloads/user1_chrome" then that will override the default Chrome paths + const chrome = new Chrome(plat, enable_unfold, alt_path); + + // Since `retrospect` is handling everything + // We have to specify how `retrospect` should output our data + const out: Output = { + /** Directory will be created if it does not exist */ + name: "chrome_info", + /** Directory will be created if it does not exist */ + directory: "./tmp", + /** JSONL is the easiest format to upload to Timesketch */ + format: Format.JSONL, + compress: false, + /** This can be set to false. The artemsi API will automatically timeline for us */ + timeline: false, + endpoint_id: "", + collection_id: 0, + /** Artemis also supports uploading to GCP, AZURE, and AWS */ + output: OutputType.LOCAL + }; + + // Now timeline all supported artifacts + chrome.retrospect(out); +} + +main(); +``` + +Now we can compile the code above to JavaScript using [esbuild](https://esbuild.github.io/) and then run with artemis! + +- esbuild --bundle --outfile=main.js main.ts +- artemis -j main.js + +You should get output at `./tmp/chrome_info`. + +### Multi Browser Support + +Retrospect supports additional browsers besides Chromium based browsers. You can run against all browsers supported by artemis! + +```typescript +import { Chrome, Firefox, Chromium, Edge, Epiphany, Falkon, + Format, Output, OutputType, PlatformType } from "./artemis-api/mod"; + +function main() { + // Change this if you are going to run on a different platform. + // Ex: Windows (PlatformType.Windows) or macOS (PlatformType.Darwin) + const plat = PlatformType.Linux; + + // If we acquired a user's Chrome profile + // We could also provide that as an alternative path + // Ex: /home/analyst/Downloads/user1_chrome + // This is optional + const alt_path = undefined; + // This is optional. The default value is false + const enable_unfold = false; + + // Initialize a Chrome application class + // By default this will extract Chrome artifacts for all users on the PlatformType + // This example will attempt to extract Chrome artifacts for the Platform.Type Windows + // If the alt_path != undefined. That will override the default Chrome paths for the provided platform + // Ex: If alt_path = "/home/analyst/Downloads/user1_chrome" then that will override the default Chrome paths + const chrome = new Chrome(plat, enable_unfold, alt_path); + + const fire = new Firefox(plat); + const edge = new Edge(plat); + const chromium = new Chromium(plat); + // Epiphany only supports the Linux platform. + // But we can also provide an alt_path if we want to parse on a non-linux platform + const epiphany = new Epiphany(); + const falkon = new Falkon(plat); + + // Since `retrospect` is handling everything + // We have to specify how `retrospect` should output our data + const out: Output = { + /** Directory will be created if it does not exist */ + name: "browsers_info", + /** Directory will be created if it does not exist */ + directory: "./tmp", + /** JSONL is the easiest format to upload to Timesketch */ + format: Format.JSONL, + compress: false, + /** This can be set to false. The artemsi API will automatically timeline for us */ + timeline: false, + endpoint_id: "", + collection_id: 0, + /** Artemis also supports uploading to GCP, AZURE, and AWS */ + output: OutputType.LOCAL + }; + + // Now timeline all supported artifacts for all browsers! + chrome.retrospect(out); + edge.retrospect(out); + fire.retrospect(out); + chromium.retrospect(out); + epiphany.retrospect(out); + falkon.retrospect(out); +} + +main(); +``` + +Now we can compile the code above to JavaScript using [esbuild](https://esbuild.github.io/) and then run with artemis! + +- esbuild --bundle --outfile=main.js main.ts +- artemis -j main.js + +You should get output at `./tmp/browsers_info`. + +:::info + +You can shrink to size of you JavaScript script by using the minify option in esbuild +- esbuild --minify --bundle --outfile=main.js main.ts + +::: + +### Unfold + +Artemis has one optional feature that can be used to enhance browser artifacts. This feature is called `unfold`. +Unfold is a URL parser that attempts to extract data in URLs. It is very similar to the tool [unfurl](https://github.com/obsidianforensics/unfurl). +By default unfold is **disabled**. + +But enabling unfold is very easy! Just add it as an parameter when initializing a browser artifact class. + +An example is below: +```typescript +import { Chrome, Format, Output, OutputType, PlatformType } from "./artemis-api/mod"; + +function main() { + // Change this if you are going to run on a different platform. + // Ex: Linux (PlatformType.Linux) or macOS (PlatformType.Darwin) + const plat = PlatformType.Windows; + const enable_unfold = true; + + // Initialize a Chrome application class + // By default this will extract Chrome artifacts for all users on the PlatformType + // When unfold is enabled, artemis will attempt to extract additional information from URLs + const chrome = new Chrome(plat, enable_unfold); + + // Since `retrospect` is handling everything + // We have to specify how `retrospect` should output our data + const out: Output = { + /** Directory will be created if it does not exist */ + name: "chrome_info", + /** Directory will be created if it does not exist */ + directory: "./tmp", + /** JSONL is the easiest format to upload to Timesketch */ + format: Format.JSONL, + compress: false, + /** This can be set to false. The artemsi API will automatically timeline for us */ + timeline: false, + endpoint_id: "", + collection_id: 0, + /** Artemis also supports uploading to GCP, AZURE, and AWS */ + output: OutputType.LOCAL + }; + + // Now timeline all supported artifacts + chrome.retrospect(out); +} + +main(); +``` + +Now we can compile the code above to JavaScript using [esbuild](https://esbuild.github.io/) and then run with artemis! + +- esbuild --bundle --outfile=main.js main.ts +- artemis -j main.js + +You should get output at `./tmp/chrome_info`. \ No newline at end of file diff --git a/artemis-docs/docs/API/API Scenarios/itunes.md b/artemis-docs/docs/API/API Scenarios/itunes.md index fc318d36..1d3d2be3 100644 --- a/artemis-docs/docs/API/API Scenarios/itunes.md +++ b/artemis-docs/docs/API/API Scenarios/itunes.md @@ -36,6 +36,7 @@ function main() { compress: false, endpoint_id: "", collection_id: 0, + timeline: false, output: OutputType.LOCAL, }; const result = extractBackup( diff --git a/artemis-docs/docs/API/Artifacts/applications.md b/artemis-docs/docs/API/Artifacts/applications.md index e1b3bff2..720fb186 100644 --- a/artemis-docs/docs/API/Artifacts/applications.md +++ b/artemis-docs/docs/API/Artifacts/applications.md @@ -41,6 +41,7 @@ function main() { const history_data = client.history(start, limit); const ext = client.extensions(); + const edge_history = edge.history(); return ext; } @@ -135,6 +136,47 @@ Return Chromium bookmarks for all users. Return Chromium local storage data for all users. +#### sessions() -> ChromiumSession[] + +Return Chromium sessions for all users. + +#### retrospect(output) + +A powerfull function that will timeline all supported Chromium artifacts + +| Param | Type | Description | +| ---------------- | ------------- | ----------------------------------- | +| output | Output | Output object to output all results | + +Sample TypeScript code: +```typescript +import { Chrome, Edge, Format, Output, OutputType, PlatformType } from "./artemis-api/mod"; +function main() { + // Unfurls URLs. Based on [Unfurl](https://github.com/obsidianforensics/unfurl) + const enable_unfold = true; + const client = new Edge(PlatformType.Windows, enable_unfold); + const out: Output = { + name: "browsers", + directory: "./tmp", + format: Format.JSONL, + compress: false, + timeline: false, + endpoint_id: "", + collection_id: 0, + output: OutputType.LOCAL + }; + + // All artifacts will be parsed and timelined to JSONL + client.retrospect(out); + + const chrome_client = new Chrome(PlatformType.Windows, enable_unfold); + // All artifacts will be parsed and timelined to JSONL + chrome_client.retrospect(out); +} + +main(); +``` + ### FireFox Browser Class A basic TypeScript class to extract data from the FireFox browser. You may optionally enable Unfold URL parsing (default is disabled) and provide an alternative glob to the base FireFox directory. @@ -222,6 +264,13 @@ By default artemis will get the first 100 entries for all users. Return FireFox addons for all users. FireFox addons exists as a JSON file. +#### retrospect(output) + +A powerfull function that will timeline all supported FireFox artifacts + +| Param | Type | Description | +| ---------------- | ------------- | ----------------------------------- | +| output | Output | Output object to output all results | ### Nextcloud Client Class @@ -274,20 +323,23 @@ Return a list of files opened by LibreOffice for all users. | -------- | ------------ | -------------------- | | platform | PlatformType | OS platform to parse | -### fileHistory(platform, alt_glob) -> FileHistory[] | ApplicationError +### fileHistory(platform, include_content, alt_glob) -> FileHistory[] | ApplicationError Parse the local file history for VSCode. Returns list of history entries. Also -supports VSCodium. +supports VSCodium. You may also provide an optional alternative glob path to the entries.json file. By default artemis will parse the default locations for VSCode. -An altnerative glob will override the platform type. +An alternative glob will override the platform type. +You may also choose to include the content of the history files. By default this is not included. +If you include the file content the output will be very large. -| Param | Type | Description | -| -------- | ------------ | ---------------------------------------------- | -| platform | PlatformType | OS platform to parse | -| alt_glob | string | optional alternative glob path to entries.json | +| Param | Type | Description | +| --------------- | ------------ | ------------------------------------------------------ | +| platform | PlatformType | OS platform to parse | +| include_content | boolean | Include content of the history files. Default is false | +| alt_glob | string | optional alternative glob path to entries.json | ### getExtensions(platform, path) -> Extensions[] | ApplicationError @@ -354,11 +406,10 @@ file. | platform | PlatformType | OS platform to parse. Supports Windows and macOS (Darwin) | | alt_file | string | Optional path to a MRU plist or NTUSER.DAT | -### onedriveDetails(platform, alt_path, user) -> OneDriveDetails | ApplicationError +### OneDrive Class -Extract Microsoft OneDrive artifacts. Supports both macOS and Windows. By -default will parse OneDrive artifacts for **all** users. You may provide a -single user as an optional arguement to only parse data for a specific user. +A basic TypeScript class to extract OneDrive forensic artifacts. Supports both macOS and Windows. +By default artemis will parse OneDrive artifacts for **all** users. You may provide a single user as an optional arguement to only parse data for a specific user. You may also provide an optional alternative path to a folder containing OneDrive artifacts. You must include the trailing slash. The folder should @@ -369,11 +420,88 @@ contain the following artifacts: - general.keystore - SyncEngineDatabase.db -| Param | Type | Description | -| -------- | ------------ | ---------------------------------------------------------- | -| platform | PlatformType | OS platform to parse. Supports Windows and macOS (Darwin) | -| alt_path | string | Optional path to a directory containing OneDrive artifacts | -| user | string | Optional single user to parse instead of all users | +Sample TypeScript code: +```typescript +import { Format, OneDrive, Output, OutputType, PlatformType } from "./artemis-api/mod"; + +function main() { + const results = new OneDrive(PlatformType.Windows); + const output: Output = { + name: "local", + directory: "tmp", + format: Format.JSONL, + compress: false, + timeline: false, + endpoint_id: "", + collection_id: 0, + output: OutputType.LOCAL + }; + + results.oneDriveRetrospect(output); +} + +main(); +``` + +#### oneDriveProfiles() -> OnedriveProfile[] + +Returns an array of all file path atifacts associated with OneDrive users + +#### oneDriveKeys(files, output, metadata_runtime) -> KeyInfo[] + +Returns an array of keys used by OneDrive. By default this function will find the keys for all users. You may provide a specific subset of files or users instead of all users. + +You may also provide an optional Output object to output results to a file instead of returning an array of KeyInfo. + +| Param | Type | Description | +| ---------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| files | string[] | Parse only key files from the provided array | +| output | Output | Output object to output all results to a file instead of return an array | +| metadata_runtime | boolean | Specificy if artemis should append runtime metadata when outputting to a file based on the Output object. Default is no metadata will be appended | + +#### oneDriveAccounts(files, output, metadata_runtime) -> OneDriveAccount[] + +Returns an array of OneDrive account information. By default this function will find the accounts for all users. You may provide a specific subset of files or users instead of all users. + +You may also provide an optional Output object to output results to a file instead of returning an array of OneDriveAccount. + +| Param | Type | Description | +| ---------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| files | string[] | Parse only account files from the provided array | +| output | Output | Output object to output all results to a file instead of return an array | +| metadata_runtime | boolean | Specificy if artemis should append runtime metadata when outputting to a file based on the Output object. Default is no metadata will be appended | + +#### oneDriveLogs(files, output, metadata_runtime) -> OneDriveLog[] + +Returns an array of OneDrive log information. By default this function will find the logs for all users. You may provide a specific subset of files or users instead of all users. + +You may also provide an optional Output object to output results to a file instead of returning an array of OneDriveLog. + +| Param | Type | Description | +| ---------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| files | string[] | Parse only log files from the provided array | +| output | Output | Output object to output all results to a file instead of return an array | +| metadata_runtime | boolean | Specificy if artemis should append runtime metadata when outputting to a file based on the Output object. Default is no metadata will be appended | + +#### oneDriveSyncDatabase(files, output, metadata_runtime) -> OneDriveSyncEngineRecord[] + +Returns an array of OneDrive Sync database information. By default this function will find the databases for all users. You may provide a specific subset of files or users instead of all users. + +You may also provide an optional Output object to output results to a file instead of returning an array of OneDriveSyncEngineRecord. + +| Param | Type | Description | +| ---------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| files | string[] | Parse only database files from the provided array | +| output | Output | Output object to output all results to a file instead of return an array | +| metadata_runtime | boolean | Specificy if artemis should append runtime metadata when outputting to a file based on the Output object. Default is no metadata will be appended | + +#### oneDriveRetrospect(output) + +A powerfull function that will timeline all supported OneDrive artifacts + +| Param | Type | Description | +| ---------------- | ------------- | ----------------------------------- | +| output | Output | Output object to output all results | ### LevelDb Class @@ -440,4 +568,27 @@ AnyDesk config information. | Param | Type | Description | | -------- | ------------ | --------------------------------------------------------------------------------------------------- | -| is_alt | boolean | Optional. Set to true if you provided an alternative directory when initializing the AnyDesk class | \ No newline at end of file +| is_alt | boolean | Optional. Set to true if you provided an alternative directory when initializing the AnyDesk class | + +### Syncthing Class + +A basic TypeScript class to extract data from Syncthing logs. + +Sample TypeScript code: +```typescript +import { PlatformType, Syncthing } from "./artemis-api/mod"; + + +function main() { + const client = new Syncthing(PlatformType.Linux); + const results = client.logs(); + console.log(JSON.stringify(results)); +} + +main(); +``` + + +#### logs() -> SyncthingLogs[] + +Return all plaintext log entries for the Syncthing application diff --git a/artemis-docs/docs/API/Artifacts/linux.md b/artemis-docs/docs/API/Artifacts/linux.md index 0027d521..86f430d8 100644 --- a/artemis-docs/docs/API/Artifacts/linux.md +++ b/artemis-docs/docs/API/Artifacts/linux.md @@ -346,4 +346,44 @@ function main() { } main(); -``` \ No newline at end of file +``` + +### queryLogons(alt_path) -> LastLogons[] | LinuxError + +Query the new wtmp sqlite database + +| Param | Type | Description | +| -------- | ------ | ---------------- | +| alt_path | string | Alt path wtmp.db | + + +### readRawFileExt4(path, device) -> Uint8Array | LinuxError + +Read a file at provided path by parsing the EXT4 filesystem. You will need to provide a device file to read. Ex: /dev/sda1 + +| Param | Type | Description | +| ------ | ------ | ------------------- | +| path | string | Path to file read | +| device | string | Path to device file | + +### readRawInodeExt4(inode, device) -> Uint8Array | LinuxError + +Read a file at provided inode by parsing the EXT4 filesystem. You will need to provide a device file to read. Ex: /dev/sda1 + +| Param | Type | Description | +| ----- | ------ | ------------------- | +| path | string | Path to file read | +| inode | string | Path to device file | + + +### readRawDirExt4(path, start, device) -> FileEntry[] | LinuxError + +Search for files or directories at provided path by parsing the EXT4 filesystem. You will need to provide a device file to read. Ex: /dev/sda1 + +You may provide a starting to begin the search. The path string may be any valid Rust regex string + +| Param | Type | Description | +| ------ | ------ | ----------------------- | +| path | string | Path to file read | +| start | string | Path to start searching | +| device | string | Path to device file | \ No newline at end of file diff --git a/artemis-docs/docs/API/Artifacts/windows.md b/artemis-docs/docs/API/Artifacts/windows.md index 65e8d6f8..8acf1d1c 100644 --- a/artemis-docs/docs/API/Artifacts/windows.md +++ b/artemis-docs/docs/API/Artifacts/windows.md @@ -514,9 +514,9 @@ Parse SYSTEM Registry to get list of USB devices that have been connected Parse Windows System.evtx file to extract Service Install events. -| Param | Type | Description | -| ----- | ------ | ---------------------------- | -| path | string | Path to the System.evtx file | +| Param | Type | Description | +| ----- | ------ | ----------------------------------- | +| path | string | Option path to the System.evtx file | ### Outlook Class @@ -595,4 +595,81 @@ You may provided an optional alternative path to Security.evtx. | Param | Type | Description | | ----- | ------ | ------------------------------------------ | -| path | string | Optional alternative path to Security.evtx | \ No newline at end of file +| path | string | Optional alternative path to Security.evtx | + +#### wifiNetworksWindows(path) -> Wifi[] | WindowsError + +Parses the Windows SOFTWARE Registry file and attempts extract WiFi networks connected to. +You may provided an optional alternative path to the SOFTWARE Registry file. + +| Param | Type | Description | +| ----- | ------ | ------------------------------------------ | +| path | string | Optional alternative path to Security.evtx | + +### ADCertificates Class + +A basic class to help interact and extract data from AD Certificates ESE databases. + +Sample TypeScript code: +```typescript +import { ADCertificates } from "./artemis-api/mod"; +import { WindowsError } from "./artemis-api/src/windows/errors"; + +function main() { + // You may also provide an optional alternative path to the ESE database + const client = new ADCertificates(); + const catalog = client.catalogInfo(); + if (catalog instanceof WindowsError) { + return; + } + const first_page = client.tableInfo(catalog, "Certificates").table_page; + const cert_pages = client.getPages(first_page); + if (cert_pages instanceof WindowsError) { + return; + } + // Depending on size of EDB file you should customize the number of pages you use + // The larger the pages array the more memory required + // 100 pages should be a reasonable default + const certs = client.getCertificates(cert_pages, client.tableInfo(catalog, "Certificates")) + console.log(JSON.stringify(certs)); +} + +main(); +``` + +#### getCertificates(pages, info) -> Certificates[] | WindowsError + +Get list of certificates from the database. + +| Param | Type | Description | +| ----- | --------- | --------------------------------------------------------- | +| pages | number[] | Number of pages to parse from the ESE database | +| info | TableInfo | Table info object that can be obtained with the ESE class | + + +#### getRequests(pages, info) -> Requests[] | WindowsError + +Get list of requests from the database. + +| Param | Type | Description | +| ----- | --------- | --------------------------------------------------------- | +| pages | number[] | Number of pages to parse from the ESE database | +| info | TableInfo | Table info object that can be obtained with the ESE class | + +#### requestAttributes(pages, info) -> RequestAttributes[] | WindowsError + +Get list of requests attributes from the database. + +| Param | Type | Description | +| ----- | --------- | --------------------------------------------------------- | +| pages | number[] | Number of pages to parse from the ESE database | +| info | TableInfo | Table info object that can be obtained with the ESE class | + + +### getRunKeys(path) -> RegistryRunKey[] + +Parse Windows Registry files and extract Run key entries. You may provide an optional path to a Registry file. By default all user NTUSER.DAT and SOFTWARE files are parsed + +| Param | Type | Description | +| ------- | ------- | -------------------------------- | +| path | string | Optional path to a Registry file | \ No newline at end of file diff --git a/artemis-docs/docs/Artifacts/Application Artifacts/chrome.md b/artemis-docs/docs/Artifacts/Application Artifacts/chrome.md index 126b6fa1..d1430763 100644 --- a/artemis-docs/docs/Artifacts/Application Artifacts/chrome.md +++ b/artemis-docs/docs/Artifacts/Application Artifacts/chrome.md @@ -21,6 +21,10 @@ Artemis supports parsing the list of artifacts below: - Preferences - Detect Incidental Party State (DIPS) - Local Storage +- Browser sessions +- Favicons +- Shortcuts +- Retrospect - A powerful capability that timelines all artifacts. It is based on [Hindsight](https://github.com/obsidianforensics/hindsight) You have to use the artemis [api](../../API/overview.md) in order to collect Chrome data. Since Chrome is based on Chromium, many of the Chrome artifacts will be identical to Chromium @@ -87,6 +91,14 @@ export interface ChromiumHistory { unfold: Url | undefined; /**Path to the HISTORY sqlite file */ db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "URL Visited"; + artifact: "URL History"; + data_type: string; + browser: BrowserType; } /** @@ -153,6 +165,14 @@ export interface ChromiumDownloads { url: string; /**Path to the HISTORY sqlite file */ db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "File Download Start"; + artifact: "File Download"; + data_type: string; + browser: BrowserType; } export interface ChromiumCookies { @@ -177,6 +197,14 @@ export interface ChromiumCookies { is_same_party: number; last_update: string; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Cookie Expires"; + artifact: "Website Cookie"; + data_type: string; + browser: BrowserType; } export interface ChromiumAutofill { @@ -188,16 +216,17 @@ export interface ChromiumAutofill { /**Default is 1 */ count: number; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Autofill Created"; + artifact: "Website Autofill"; + data_type: string; + browser: BrowserType; } export interface ChromiumBookmarks { - bookmark_bar: ChromiumBookmarkChildren[]; - other: ChromiumBookmarkChildren[]; - synced: ChromiumBookmarkChildren[]; - path: string; -} - -export interface ChromiumBookmarkChildren { date_added: string; date_last_used: string; guid: string; @@ -206,7 +235,25 @@ export interface ChromiumBookmarkChildren { type: string; url: string; meta_info: Record; + bookmark_type: BookmarkType; + path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Bookmark Added"; + artifact: "Browser Bookmark"; + data_type: string; + browser: BrowserType; } + +export enum BookmarkType { + Bar = "Bookmark Bar", + Sync = "Synced", + Other = "Other", + Unknown = "Unknown", +} + export interface ChromiumLogins { origin_url: string; action_url?: string; @@ -239,12 +286,20 @@ export interface ChromiumLogins { keychain_identifier?: string; sender_profile_image_url?: string; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Last Login"; + artifact: "Website Login"; + data_type: string; + browser: BrowserType; } /** * Detect Incidental Party State (DIPS) collects metrics on websites */ -export interface Dips { +export interface ChromiumDips { site: string; first_site_storage?: string | null; last_site_storage?: string | null; @@ -258,6 +313,14 @@ export interface Dips { last_web_authn_assertion: string | null; /**Path to DIPS database */ path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "First Interaction"; + artifact: "Browser DIPS"; + data_type: string; + browser: BrowserType; } export interface ChromiumProfiles { @@ -271,4 +334,46 @@ export enum BrowserType { EDGE = "Microsoft Edge", CHROMIUM = "Google Chromium" } + +export enum ChromiumCookieType { + Unknown = "Unknown", + Http = "HTTP", + Script = "Script", + Other = "Other", +} + +/** + * Object representing a Local Storage LevelDb entry. + * This object is Timesketch compatible. It does **not** need to be timelined + */ +export interface ChromiumLocalStorage extends LevelDbEntry { + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Local Storage Entry Write" | "Local Storage Write Ahead Log"; + artifact: "Level Database"; + data_type: "applications:leveldb:entry"; +} + +export interface ChromiumSession { + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Last Active"; + artifact: "Browser Session"; + data_type: string; + session_id: string; + last_active: string; + url: string; + title: string; + session_type: SessionType; + path: string; +} + +export enum SessionType { + Session = "Session", + Tab = "Tab", +} ``` diff --git a/artemis-docs/docs/Artifacts/Application Artifacts/chromium.md b/artemis-docs/docs/Artifacts/Application Artifacts/chromium.md index 6d682e27..c6edc2aa 100644 --- a/artemis-docs/docs/Artifacts/Application Artifacts/chromium.md +++ b/artemis-docs/docs/Artifacts/Application Artifacts/chromium.md @@ -27,6 +27,10 @@ Artemis supports parsing the list of artifacts below: - Preferences - Detect Incidental Party State (DIPS) - Local Storage +- Browser sessions +- Favicons +- Shortcuts +- Retrospect - A powerful capability that timelines all artifacts. It is based on [Hindsight](https://github.com/obsidianforensics/hindsight) You have to use the artemis [api](../../API/overview.md) in order to collect Chromium data @@ -92,6 +96,14 @@ export interface ChromiumHistory { unfold: Url | undefined; /**Path to the HISTORY sqlite file */ db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "URL Visited"; + artifact: "URL History"; + data_type: string; + browser: BrowserType; } /** @@ -158,6 +170,14 @@ export interface ChromiumDownloads { url: string; /**Path to the HISTORY sqlite file */ db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "File Download Start"; + artifact: "File Download"; + data_type: string; + browser: BrowserType; } export interface ChromiumCookies { @@ -182,6 +202,14 @@ export interface ChromiumCookies { is_same_party: number; last_update: string; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Cookie Expires"; + artifact: "Website Cookie"; + data_type: string; + browser: BrowserType; } export interface ChromiumAutofill { @@ -193,16 +221,17 @@ export interface ChromiumAutofill { /**Default is 1 */ count: number; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Autofill Created"; + artifact: "Website Autofill"; + data_type: string; + browser: BrowserType; } export interface ChromiumBookmarks { - bookmark_bar: ChromiumBookmarkChildren[]; - other: ChromiumBookmarkChildren[]; - synced: ChromiumBookmarkChildren[]; - path: string; -} - -export interface ChromiumBookmarkChildren { date_added: string; date_last_used: string; guid: string; @@ -211,7 +240,25 @@ export interface ChromiumBookmarkChildren { type: string; url: string; meta_info: Record; + bookmark_type: BookmarkType; + path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Bookmark Added"; + artifact: "Browser Bookmark"; + data_type: string; + browser: BrowserType; } + +export enum BookmarkType { + Bar = "Bookmark Bar", + Sync = "Synced", + Other = "Other", + Unknown = "Unknown", +} + export interface ChromiumLogins { origin_url: string; action_url?: string; @@ -244,12 +291,20 @@ export interface ChromiumLogins { keychain_identifier?: string; sender_profile_image_url?: string; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Last Login"; + artifact: "Website Login"; + data_type: string; + browser: BrowserType; } /** * Detect Incidental Party State (DIPS) collects metrics on websites */ -export interface Dips { +export interface ChromiumDips { site: string; first_site_storage?: string | null; last_site_storage?: string | null; @@ -263,6 +318,14 @@ export interface Dips { last_web_authn_assertion: string | null; /**Path to DIPS database */ path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "First Interaction"; + artifact: "Browser DIPS"; + data_type: string; + browser: BrowserType; } export interface ChromiumProfiles { @@ -276,4 +339,46 @@ export enum BrowserType { EDGE = "Microsoft Edge", CHROMIUM = "Google Chromium" } + +export enum ChromiumCookieType { + Unknown = "Unknown", + Http = "HTTP", + Script = "Script", + Other = "Other", +} + +/** + * Object representing a Local Storage LevelDb entry. + * This object is Timesketch compatible. It does **not** need to be timelined + */ +export interface ChromiumLocalStorage extends LevelDbEntry { + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Local Storage Entry Write" | "Local Storage Write Ahead Log"; + artifact: "Level Database"; + data_type: "applications:leveldb:entry"; +} + +export interface ChromiumSession { + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Last Active"; + artifact: "Browser Session"; + data_type: string; + session_id: string; + last_active: string; + url: string; + title: string; + session_type: SessionType; + path: string; +} + +export enum SessionType { + Session = "Session", + Tab = "Tab", +} ``` diff --git a/artemis-docs/docs/Artifacts/Application Artifacts/edge.md b/artemis-docs/docs/Artifacts/Application Artifacts/edge.md index 5a542375..da777079 100644 --- a/artemis-docs/docs/Artifacts/Application Artifacts/edge.md +++ b/artemis-docs/docs/Artifacts/Application Artifacts/edge.md @@ -21,6 +21,10 @@ Artemis supports parsing the list of artifacts below: - Preferences - Detect Incidental Party State (DIPS) - Local Storage +- Browser sessions +- Favicons +- Shortcuts +- Retrospect - A powerful capability that timelines all artifacts. It is based on [Hindsight](https://github.com/obsidianforensics/hindsight) You have to use the artemis [api](../../API/overview.md) in order to collect Edge data. Since Edge is based on Chromium, many of the Edge artifacts will be identical to Chromium @@ -87,6 +91,14 @@ export interface ChromiumHistory { unfold: Url | undefined; /**Path to the HISTORY sqlite file */ db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "URL Visited"; + artifact: "URL History"; + data_type: string; + browser: BrowserType; } /** @@ -153,6 +165,14 @@ export interface ChromiumDownloads { url: string; /**Path to the HISTORY sqlite file */ db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "File Download Start"; + artifact: "File Download"; + data_type: string; + browser: BrowserType; } export interface ChromiumCookies { @@ -177,6 +197,14 @@ export interface ChromiumCookies { is_same_party: number; last_update: string; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Cookie Expires"; + artifact: "Website Cookie"; + data_type: string; + browser: BrowserType; } export interface ChromiumAutofill { @@ -188,16 +216,17 @@ export interface ChromiumAutofill { /**Default is 1 */ count: number; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Autofill Created"; + artifact: "Website Autofill"; + data_type: string; + browser: BrowserType; } export interface ChromiumBookmarks { - bookmark_bar: ChromiumBookmarkChildren[]; - other: ChromiumBookmarkChildren[]; - synced: ChromiumBookmarkChildren[]; - path: string; -} - -export interface ChromiumBookmarkChildren { date_added: string; date_last_used: string; guid: string; @@ -206,7 +235,25 @@ export interface ChromiumBookmarkChildren { type: string; url: string; meta_info: Record; + bookmark_type: BookmarkType; + path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Bookmark Added"; + artifact: "Browser Bookmark"; + data_type: string; + browser: BrowserType; } + +export enum BookmarkType { + Bar = "Bookmark Bar", + Sync = "Synced", + Other = "Other", + Unknown = "Unknown", +} + export interface ChromiumLogins { origin_url: string; action_url?: string; @@ -239,12 +286,20 @@ export interface ChromiumLogins { keychain_identifier?: string; sender_profile_image_url?: string; db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Last Login"; + artifact: "Website Login"; + data_type: string; + browser: BrowserType; } /** * Detect Incidental Party State (DIPS) collects metrics on websites */ -export interface Dips { +export interface ChromiumDips { site: string; first_site_storage?: string | null; last_site_storage?: string | null; @@ -258,6 +313,14 @@ export interface Dips { last_web_authn_assertion: string | null; /**Path to DIPS database */ path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "First Interaction"; + artifact: "Browser DIPS"; + data_type: string; + browser: BrowserType; } export interface ChromiumProfiles { @@ -271,4 +334,46 @@ export enum BrowserType { EDGE = "Microsoft Edge", CHROMIUM = "Google Chromium" } + +export enum ChromiumCookieType { + Unknown = "Unknown", + Http = "HTTP", + Script = "Script", + Other = "Other", +} + +/** + * Object representing a Local Storage LevelDb entry. + * This object is Timesketch compatible. It does **not** need to be timelined + */ +export interface ChromiumLocalStorage extends LevelDbEntry { + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Local Storage Entry Write" | "Local Storage Write Ahead Log"; + artifact: "Level Database"; + data_type: "applications:leveldb:entry"; +} + +export interface ChromiumSession { + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Last Active"; + artifact: "Browser Session"; + data_type: string; + session_id: string; + last_active: string; + url: string; + title: string; + session_type: SessionType; + path: string; +} + +export enum SessionType { + Session = "Session", + Tab = "Tab", +} ``` diff --git a/artemis-docs/docs/Artifacts/Application Artifacts/firefox.md b/artemis-docs/docs/Artifacts/Application Artifacts/firefox.md index 893fa21b..3b77b174 100644 --- a/artemis-docs/docs/Artifacts/Application Artifacts/firefox.md +++ b/artemis-docs/docs/Artifacts/Application Artifacts/firefox.md @@ -49,6 +49,16 @@ main(); Dependent on browser artifact user wants to parse. ```typescript +import { Url } from "../http/unfold"; + +/** + * Firefox history is stored in a SQLITE file. + * `artemis` uses the `sqlite` crate to read the SQLITE file. It can even read the file if Firefox is running. + * + * References: + * - https://kb.mozillazine.org/Places.sqlite + */ + /** * An interface representing the Firefox SQLITE tables: `moz_places` and `moz_origins` */ @@ -87,6 +97,11 @@ export interface FirefoxHistory { host: string; unfold: Url | undefined; db_path: string; + message: string; + datetime: string; + timestamp_desc: "URL Visited"; + artifact: "URL History"; + data_type: "application:firefox:history:entry"; } /** @@ -113,32 +128,74 @@ export interface FirefoxDownloads { last_modified: string; /**Downloaded file name */ name: string; + /**SQLITE row id */ + moz_places_id: number; + /**Page URL */ + url: string; + /**Page title */ + title: string; + /**URL in reverse */ + rev_host: string; + /**Page visit count */ + visit_count: number; + /**Hidden value */ + hidden: number; + /**Typed value */ + typed: number; + /**Frequency value */ + frequency: number; + /**Last visit time */ + last_visit_date: string; + /**GUID for entry */ + guid: string; + /**Foreign count value */ + foreign_count: number; + /**Hash of URL */ + url_hash: number; + /**Page description */ + description: string; + /**Preview image URL value */ + preview_image_url: string; db_path: string; + message: string; + datetime: string; + timestamp_desc: "File Download Start"; + artifact: "File Download"; + data_type: "application:firefox:downloads:entry"; } export interface FirefoxCookies { id: number; origin_attributes: string; - name?: string; - value?: string; - host?: string; - path?: string; - expiry?: number; - last_accessed?: string; - creation_time?: string; - is_secure?: boolean; - is_http_only?: boolean; + name: string; + value: string; + host: string; + path: string; + expiry: string; + last_accessed: string; + creation_time: string; + is_secure: boolean; + is_http_only: boolean; in_browser_element: boolean; same_site: boolean; - raw_same_site: boolean; scheme_map: number; db_path: string; + message: string; + datetime: string; + timestamp_desc: "Cookie Expires"; + artifact: "Website Cookie"; + data_type: "application:firefox:cookies:entry"; } export interface FirefoxFavicons { icon_url: string; expires: string; db_path: string; + message: string; + datetime: string; + timestamp_desc: "Favicon Expires"; + artifact: "URL Favicon"; + data_type: "application:firefox:favicons:entry"; } export interface FirefoxProfiles { @@ -156,6 +213,11 @@ export interface FirefoxStorage { accessed: number; persisted: number; db_path: string; + message: string; + datetime: string; + timestamp_desc: "Website Storage Last Accessed"; + artifact: "Website Storage"; + data_type: "application:firefox:storage:entry"; } export enum Respository { @@ -165,4 +227,23 @@ export enum Respository { Unknown = "Unknown", Temporary = "Temporary", } + +export interface FirefoxAddons { + installed: string; + updated: string; + active: boolean; + visible: boolean; + author: string; + version: string; + path: string; + db_path: string; + message: string; + datetime: string; + name: string; + description: string; + creator: string; + timestamp_desc: "Extension Installed"; + artifact: "Browser Extension"; + data_type: "application:firefox:extension:entry"; +} ``` diff --git a/artemis-docs/docs/Artifacts/Application Artifacts/libreoffice.md b/artemis-docs/docs/Artifacts/Application Artifacts/libreoffice.md index 3fc04d7c..998a5018 100644 --- a/artemis-docs/docs/Artifacts/Application Artifacts/libreoffice.md +++ b/artemis-docs/docs/Artifacts/Application Artifacts/libreoffice.md @@ -37,7 +37,7 @@ An array of `RecentFilesLibreOffice` entries. /** * List of files opened by LibreOffice */ -interface RecentFilesLibreOffice { +export interface RecentFilesLibreOffice { /**Path to file */ path: string; /**Document title */ @@ -54,5 +54,10 @@ interface RecentFilesLibreOffice { thumbnail: string; /**Path to registrymodifications.xcu */ source: string; + message: string; + datetime: "1970-01-01T00:00:00Z"; + timestamp_desc: "N/A"; + artifact: "LibreOffice Recent Files", + data_type: "application:libreoffice:recentfiles:entry", } ``` diff --git a/artemis-docs/docs/Artifacts/Application Artifacts/onedrive.md b/artemis-docs/docs/Artifacts/Application Artifacts/onedrive.md index 725ac5ca..5b655b49 100644 --- a/artemis-docs/docs/Artifacts/Application Artifacts/onedrive.md +++ b/artemis-docs/docs/Artifacts/Application Artifacts/onedrive.md @@ -14,7 +14,7 @@ cloud. Artemis supports parsing several artifacts containing OneDrive metadata such as: - Basic support for OneDrive Logs (ODL files, version 3 only) -- SQLITE files +- SyncDatabase files - Registry files (NTUSER.DAT) - PLIST files @@ -30,15 +30,25 @@ Other Parsers: # Collection You have to use the artemis [api](../../API/overview.md) in order to collect -Microsoft Office information. +Microsoft OneDrive information. ```typescript -import { PlatformType } from "./artemis-api/mod"; -import { onedriveDetails } from "./artemis-api/src/applications/onedrive/parser"; +import { Format, OneDrive, Output, OutputType, PlatformType } from "./artemis-api/mod"; function main() { - const values = onedriveDetails(PlatformType.Windows); - console.log(values); + const results = new OneDrive(PlatformType.Windows); + const output: Output = { + name: "local", + directory: "tmp", + format: Format.JSONL, + compress: false, + timeline: false, + endpoint_id: "", + collection_id: 0, + output: OutputType.LOCAL + }; + + results.oneDriveRetrospect(output); } main(); @@ -46,16 +56,9 @@ main(); # Output Structure -`OneDriveDetails` object containing artifacts associated with OneDrive +Depending on the functions called several objects can be returned ```typescript -export interface OneDriveDetails { - logs: OneDriveLog[]; - files: OneDriveSyncEngineRecord[]; - accounts: OneDriveAccount[]; - keys: KeyInfo[]; -} - export interface OneDriveLog { path: string; filename: string; @@ -67,23 +70,11 @@ export interface OneDriveLog { version: string; os_version: string; description: string; -} - -export interface OneDriveSyncEngine { - scopes: OneDriveSyncEngineScope[]; - records: OneDriveSyncEngineRecord[]; -} - -export interface OneDriveSyncEngineScope { - scope_id: string; - site_id?: string; - web_id?: string; - list_id?: string; - tenant_id?: string; - url?: string; - remote_path?: string; - permissions?: number; - library_type?: number; + message: string; + datetime: string; + timestamp_desc: "OneDrive Log Entry Created"; + artifact: "OneDrive Log"; + data_type: "applications:onedrive:logs:entry"; } export interface OneDriveSyncEngineRecord { @@ -111,31 +102,36 @@ export interface OneDriveSyncEngineRecord { modified_by: string; last_write_count: number; db_path: string; -} - -export interface OneDriveSyncEngineFolder { - parent_scope_id: string; - parent_resource_id: string; - resource_id: string; - etag: string; - folder: string; - folder_status: number | null; - permissions: number | null; - volume_id: number | null; - item_index: number | null; - parents: string[]; + message: string; + datetime: string; + timestamp_desc: "OneDrive Sync Last Change"; + artifact: "OneDrive Sync Record"; + data_type: "applications:onedrive:sync:entry"; } export interface OneDriveAccount { email: string; device_id: string; account_id: string; + /**Not available on macOS */ last_signin: string; cid: string; + message: string; + datetime: string; + timestamp_desc: "OneDrive Last Signin"; + artifact: "OneDrive Account Info"; + data_type: "applications:onedrive:account:entry"; } export interface KeyInfo { path: string; key: string; } + +export interface OnedriveProfile { + sync_db: string[]; + odl_files: string[]; + key_file: string[]; + config_file: string[]; +} ``` diff --git a/artemis-docs/docs/Artifacts/Application Artifacts/syncthing.md b/artemis-docs/docs/Artifacts/Application Artifacts/syncthing.md new file mode 100644 index 00000000..844828de --- /dev/null +++ b/artemis-docs/docs/Artifacts/Application Artifacts/syncthing.md @@ -0,0 +1,46 @@ +--- +description: An open source peer to peer file synchronization application +keywords: + - cloud storage +--- + +# Syncthing + +Syncthing is a popular open source peer to peer file synchronization application. It can be used to save and share files to a remote devices. + +Artemis supports parsing Syncthing logs on Linux platforms. + +# Collection + +You have to use the artemis [api](../../API/overview.md) in order to collect Syncthing client data + + +```typescript +import { PlatformType, Syncthing } from "./artemis-api/mod"; + + +function main() { + const client = new Syncthing(PlatformType.Linux); + const results = client.logs(); + console.log(JSON.stringify(results)); +} + +main(); +``` + +# Output Structure + +Dependent on artifacts the user wants to parse. + +```typescript +export interface SyncthingLogs { + full_path: string; + tag: string; + datetime: string; + timestamp_desc: "Syncthing Log Entry"; + level: string; + message: string; + artifact: "Syncthing Log"; + data_type: "application:syncthing:log:entry"; +} +``` diff --git a/artemis-docs/docs/Artifacts/Application Artifacts/vscode.md b/artemis-docs/docs/Artifacts/Application Artifacts/vscode.md index 35ebcb21..a196386e 100644 --- a/artemis-docs/docs/Artifacts/Application Artifacts/vscode.md +++ b/artemis-docs/docs/Artifacts/Application Artifacts/vscode.md @@ -48,13 +48,26 @@ export interface FileHistory { /**Version of History format */ version: number; /**To source file */ - path: string; - /**History of source file */ - entries: Entries[]; + path?: string; + /**Path to source file */ + resource: string; /**Path to history source */ history_path: string; + message: string; + datetime: string; + timestamp_desc: "File Saved"; + artifact: "File History"; + data_type: "applications:vscode:filehistory:entry"; + /**Name of history file */ + id: string; + /**Time when file was saved */ + file_saved: number | string; + /**Based64 encoded file content */ + content?: string; + source?: string; + sourceDescription?: string; + [ key: string ]: unknown; } - /** * Metadata related to file history entry */ diff --git a/artemis-docs/docs/Artifacts/FreeBSD Artifacts/packages.md b/artemis-docs/docs/Artifacts/FreeBSD Artifacts/packages.md index f122370c..096777ef 100644 --- a/artemis-docs/docs/Artifacts/FreeBSD Artifacts/packages.md +++ b/artemis-docs/docs/Artifacts/FreeBSD Artifacts/packages.md @@ -46,7 +46,7 @@ export interface Pkg { comment: string; desc: string; mtree_id: number | null; - message: string | null; + pkg_message: string | null; arch: string; maintainer: string; www: string | null; @@ -60,5 +60,10 @@ export interface Pkg { dep_formula: string | null; vital: boolean; manifest_digest: string | null; + message: string; + datetime: string; + timestamp_desc: "Package Installed"; + artifact: "FreeBSD PKG"; + data_type: "freebsd:pkg:entry"; } ``` diff --git a/artemis-docs/docs/Artifacts/Linux Artifacts/abrt.md b/artemis-docs/docs/Artifacts/Linux Artifacts/abrt.md index 1e51e541..47fea832 100644 --- a/artemis-docs/docs/Artifacts/Linux Artifacts/abrt.md +++ b/artemis-docs/docs/Artifacts/Linux Artifacts/abrt.md @@ -45,5 +45,10 @@ export interface Abrt { backtrace: string | Record; environment: string; home: string; + message: string; + datetime: string; + timestamp_desc: "Abrt Last Occurrence"; + artifact: "Abrt"; + data_type: "linux:abrt:entry"; } ``` diff --git a/artemis-docs/docs/Artifacts/Linux Artifacts/gnomeappusage.md b/artemis-docs/docs/Artifacts/Linux Artifacts/gnomeappusage.md index 9e4f3b47..507cb1ba 100644 --- a/artemis-docs/docs/Artifacts/Linux Artifacts/gnomeappusage.md +++ b/artemis-docs/docs/Artifacts/Linux Artifacts/gnomeappusage.md @@ -35,13 +35,19 @@ An array of `AppUsage` entries. * Information about GNOME Application usage */ export interface AppUsage { - /**Application ID */ - id: string; - /**Application rank score */ - score: number; - /**Application last seen timestamp */ - "last-seen": string; - /**Path to the parsed application_state file */ - source: string; + /**Application ID */ + id: string; + /**Application rank score */ + score: number; + /**Application last seen timestamp */ + "last-seen": string; + /**Path to the parsed application_state file */ + source: string; + message: string; + datetime: string; + timestamp_desc: "Last Seen"; + artifact: "GNOME Application Usage"; + data_type: "linux:gnome:usage:entry", } + ``` diff --git a/artemis-docs/docs/Artifacts/Linux Artifacts/gnomeextensions.md b/artemis-docs/docs/Artifacts/Linux Artifacts/gnomeextensions.md index eb97ac73..90683693 100644 --- a/artemis-docs/docs/Artifacts/Linux Artifacts/gnomeextensions.md +++ b/artemis-docs/docs/Artifacts/Linux Artifacts/gnomeextensions.md @@ -40,35 +40,40 @@ An array of `Extension` entries. * Information about installed GNOME extensions */ export interface Extension { - /**Path to extension metadata.json file */ - extension_path: string; - /**Name of the extension */ - name: string; - /**Extension description */ - description: string; - /**Author (UUID) of the extension */ - uuid: string; - /**Extension version */ - version: number; - /**Supported GNOME Shell versions */ - "shell-version": string[]; - /**Extension Type: User or System */ - extension_type: ExtensionType; - /**Other JSON key entries */ - [key: string]: unknown; - /**metadata.json created */ - created: string; - /**metadata.json modified */ - modified: string; - /**metadata.json accessed */ - accessed: string; - /**metadata.json changed */ - changed: string; + /**Path to extension metadata.json file */ + extension_path: string; + /**Name of the extension */ + name: string; + /**Extension description */ + description: string; + /**Author (UUID) of the extension */ + uuid: string; + /**Extension version */ + version: number; + /**Supported GNOME Shell versions */ + "shell-version": string[]; + /**Extension Type: User or System */ + extension_type: ExtensionType; + /**Other JSON key entries */ + [ key: string ]: unknown; + /**metadata.json created */ + created: string; + /**metadata.json modified */ + modified: string; + /**metadata.json accessed */ + accessed: string; + /**metadata.json changed */ + changed: string; + message: string; + datetime: string; + timestamp_desc: "Created"; + artifact: "GNOME Extension"; + data_type: "linux:gnome:extensions:entry", } export enum ExtensionType { - User = "User", - System = "System", - Unknown = "Unknown", + User = "User", + System = "System", + Unknown = "Unknown", } ``` diff --git a/artemis-docs/docs/Artifacts/Linux Artifacts/gvfs.md b/artemis-docs/docs/Artifacts/Linux Artifacts/gvfs.md index e2f8d967..c13c06ee 100644 --- a/artemis-docs/docs/Artifacts/Linux Artifacts/gvfs.md +++ b/artemis-docs/docs/Artifacts/Linux Artifacts/gvfs.md @@ -83,21 +83,26 @@ An array of `GvfsEntry` entries. ````typescript export interface GvfsEntry { - /**Name of GvfsEntry */ - name: string; - /**Attributes associated with the entry. Example: - * ```json - * "metadata": { - "download-uri": "https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/14.1/FreeBSD-14.1-RELEASE-amd64-disc1.iso" - }, - * ``` - */ - metadata: Record; - /**Full path of the GvfsEntry */ - path: string; - /**Last change timestamp of the **metadata** */ - last_change: string; - /**GFVS file source */ - source: string; + /**Name of GvfsEntry */ + name: string; + /**Attributes associated with the entry. Example: + * ```json + * "metadata": { + "download-uri": "https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/14.1/FreeBSD-14.1-RELEASE-amd64-disc1.iso" + }, + * ``` + */ + metadata: Record; + /**Full path of the GvfsEntry */ + path: string; + /**Last change timestamp of the **metadata** */ + last_change: string; + /**GFVS file source */ + source: string; + message: string; + datetime: string; + timestamp_desc: "Last Changed"; + artifact: "GNOME Virtual Filesystem"; + data_type: "linux:gnome:gvfs:entry", } ```` diff --git a/artemis-docs/docs/Artifacts/Linux Artifacts/logons.md b/artemis-docs/docs/Artifacts/Linux Artifacts/logons.md index 708e3829..deb85d92 100644 --- a/artemis-docs/docs/Artifacts/Linux Artifacts/logons.md +++ b/artemis-docs/docs/Artifacts/Linux Artifacts/logons.md @@ -3,6 +3,7 @@ description: Linux logon info keywords: - linux - binary + - sqlite --- # Logons @@ -14,15 +15,7 @@ information on Linux: - wtmp - Historical logons - btmp - Failed logons - utmp - Users currently logged on - -In addition, [Journal](./journals.md) files may also contain logon information -Currently artemis supports all three (3) files above when obtaining Logon -information. When collecting Logon information artemis will only parse: wtmp, -utmp, and btmp files. - -If you want to check for logons in `Journal` files, you can try to apply a -[filter](../../Intro/Scripting/filterscripts.md) to the [Journal](./journals.md) -artifact +- wtmp.db - Historical logons (Requires Artemis API) Other Parsers: @@ -91,4 +84,22 @@ export interface Logon { /**Status of logon entry: `Success` or `Failed` */ status: string; } + +An array of `LastLogons` entries when querying the wtmp.db file + +export interface LastLogons { + id: number; + type: number; + user: string; + login: string; + logout: string; + tty: string; + remote: string; + service: string; + message: string; + datetime: string; + timestamp_desc: "User Logon"; + artifact: "wtmpdb Logons"; + data_type: "linux:wtmpdb:entry"; +} ``` diff --git a/artemis-docs/docs/Artifacts/Linux Artifacts/rpm.md b/artemis-docs/docs/Artifacts/Linux Artifacts/rpm.md index 6253d2b2..cd0a814c 100644 --- a/artemis-docs/docs/Artifacts/Linux Artifacts/rpm.md +++ b/artemis-docs/docs/Artifacts/Linux Artifacts/rpm.md @@ -38,8 +38,7 @@ function main() { let offset = 0; const limit = 100; - let count = 1; - while (count !== 0) { + while (true) { const status = getRpmInfo(offset, limit); if (status instanceof LinuxError) { break; @@ -49,7 +48,6 @@ function main() { } offset += limit; - count = status.length; console.log(JSON.stringify(status)); } } @@ -75,5 +73,11 @@ export interface RpmPackages { package_group: string; summary: string; url: string; + message: string; + datetime: string; + timestamp_desc: "RPM Package Installed"; + artifact: "RPM Package"; + data_type: "linux:rpm:entry"; } + ``` diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/certificates.md b/artemis-docs/docs/Artifacts/Windows Artfacts/certificates.md new file mode 100644 index 00000000..ffa7e755 --- /dev/null +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/certificates.md @@ -0,0 +1,115 @@ +--- +description: Windows Active Directory Certificates +keywords: + - windows + - ese +--- + +# Active Directory Certs + +Artemis supports parsing AD certificates from ESE databases on Windows servers. Parsing this data may be useful to identify vulnerable certificates on a system. + +## References +- [CrowdStrike White Paper](https://www.crowdstrike.com/wp-content/uploads/2023/12/investigating-active-directory-certificate-abuse.pdf) + +# Collection + +You have to use the artemis [api](../../API/overview.md) in order to collect parse AD certificates. + +# Sample API Script + +```typescript +import { ADCertificates } from "./artemis-api/mod"; +import { WindowsError } from "./artemis-api/src/windows/errors"; + +function main() { + // You may also provide an optional alternative path to the ESE database + const client = new ADCertificates(); + const catalog = client.catalogInfo(); + if (catalog instanceof WindowsError) { + return; + } + const first_page = client.tableInfo(catalog, "Certificates").table_page; + const cert_pages = client.getPages(first_page); + if (cert_pages instanceof WindowsError) { + return; + } + // Depending on size of EDB file you should customize the number of pages you use + // The larger the pages array the more memory required + const certs = client.getCertificates(cert_pages, client.tableInfo(catalog, "Certificates")) + console.log(JSON.stringify(certs)); +} + +main(); +``` + +# Output Structure + +Depends on functions called from the ADCertificates class. + +```typescript +export interface Certificates { + common_name: string; + request_id: number; + /** Base64 encoded */ + raw_cert: string; + hash: string; + serial_number: string; + distinguished_name: string; + domain: string; +} + +export interface Requests { + request_id: number; + request_type: RequestType; + status_code_number: number; + status_code: StatusCode; + disposition_message: string; + requester_name: string; + caller_name: string; + request_attributes: string; + submitted: string; + resolved: string; +} + +export interface RequestAttributes { + request_id: number; + name: string; + value: string; +} + +export enum RequestType { + PKCS10_Full = "PKCS10, Full Response", + PKCS10 = "PKCS10", + Unknown = "Unknown", +} + +/** + * Various status codes for certificate requests + * There are [alot](https://github.com/fox-it/dissect.database/pull/7/files#diff-60ccdb935072fd3aa71d6810f7c3aa7ca8ef42aadc6ce9e39ed5f54c5cc36d31R28) + * Only some listed so far + */ +export enum StatusCode { + Completed = "Operation Completed Successfully", + BadRequestSubject = "Bad Request Subject", + NoRequest = "No Request", + Empty = "Property Empty", + InvalidCA = "Invalid CA Certificte", + Suspended = "Server Suspended", + EncodingLength = "Encoding Length", + Conflict = "Role Conflict", + Restrict = "Restricted Officer", + NotConfigured = "Key Archival Not Configured", + Kra = "No Valid KRA", + BadRequest = "Bad Request Key Archival", + NoAdmin = "No CA Admin Defined", + BadRenewal = "Bad Renewal Cert Attribute", + NoSessions = "No DB Sessions", + Fault = "Alignment Fault", + Denied = "Enroll Denied", + TemplateDenied = "Template Denied", + Downlevel = "Downlevel DC SSL or Upgrade", + NoPolicy = "No Policy Server", + Unknown = "Unknown", +} +``` diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/eventlog_providers.md b/artemis-docs/docs/Artifacts/Windows Artfacts/eventlog_providers.md new file mode 100644 index 00000000..3a813c1d --- /dev/null +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/eventlog_providers.md @@ -0,0 +1,54 @@ +--- +description: Windows EventLog Providers +keywords: + - windows + - registry +--- + +# EventLog Providers + +Artemis supports extracting the registered Windows EventLog providers from the Windows SYSTEM and SOFTWARE Registry files. + +# Collection + +You have to use the artemis [api](../../API/overview.md) in order to collect EventLog providers rules. + +# Sample API Script + +```typescript +import { getEventlogProviders } from "./artemis-api/mod"; +function main() { + const events = getEventlogProviders(); + console.log(JSON.stringify(events)); + +} + +main(); +``` + +# Output Structure + +An array of `RegistryEventlogProviders` + +```typescript +export interface RegistryEventlogProviders { + registry_file: string; + key_path: string; + name: string; + channel_names: string[]; + message_file: string; + last_modified: string; + parameter_file: string; + guid: string; + enabled: boolean; + channel_types: ChannelType[]; +} + +export enum ChannelType { + Admin = "Admin", + Operational = "Operational", + Analytic = "Analytic", + Debug = "Debug", + Unknown = "Unknown", +} +``` diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/firewall_rules.md b/artemis-docs/docs/Artifacts/Windows Artfacts/firewall_rules.md index 0e6ca07f..efb3f704 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/firewall_rules.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/firewall_rules.md @@ -1,5 +1,6 @@ --- description: Windows Firewall Rules +keywords: - windows - registry --- diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/runkeys.md b/artemis-docs/docs/Artifacts/Windows Artfacts/runkeys.md new file mode 100644 index 00000000..9016a733 --- /dev/null +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/runkeys.md @@ -0,0 +1,50 @@ +--- +description: Windows Registry Run Keys + - windows + - registry +--- + +# Registry Run Keys + +Artemis supports extracting the Windows Registry Run key information from several different Registry files: +- NTUSER.DAT +- SOFTWARE + +# Collection + +You have to use the artemis [api](../../API/overview.md) in order to collect Windows Run Keys. + +# Sample API Script + +```typescript +import { getRunKeys } from "./artemis-api/mod"; + +function main() { + const results = getRunKeys(); + console.log(JSON.stringify(results)); +} + +main(); +``` + +# Output Structure + +An array of `RegistryRunKey` + +```typescript +export interface RegistryRunKey { + key_modified: string; + key_path: string; + registry_path: string; + registry_file: string; + path: string; + /**When file was created */ + created: string; + has_signature: boolean; + md5: string; + sha1: string; + sha256: string; + value: string; + name: string; +} +``` diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/ual.md b/artemis-docs/docs/Artifacts/Windows Artfacts/ual.md index 027437e3..21303ab6 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/ual.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/ual.md @@ -15,16 +15,15 @@ This database is **not** related to to the M365 UAL (Unified Audit Logging). # Collection -You have to use the artemis [api](../../API/overview.md) in order to collect UAL -keys. +You have to use the artemis [api](../../API/overview.md) in order to collect UAL keys. # Sample API Script ```typescript -import { FileError } from ".././artemis-api/src/filesystem/errors"; -import { glob } from ".././artemis-api/src/filesystem/files"; -import { WindowsError } from ".././artemis-api/src/windows/errors"; -import { UserAccessLogging } from ".././artemis-api/src/windows/ese/ual"; +import { FileError } from "./artemis-api/src/filesystem/errors"; +import { glob } from "./artemis-api/src/filesystem/files"; +import { WindowsError } from "./artemis-api/src/windows/errors"; +import { UserAccessLogging } from "./artemis-api/src/windows/ese/ual"; function main() { const glob_path = "C:\\System32\\LogFiles\\Sum\\*.mdb"; diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/wifi.md b/artemis-docs/docs/Artifacts/Windows Artfacts/wifi.md new file mode 100644 index 00000000..629a3dea --- /dev/null +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/wifi.md @@ -0,0 +1,72 @@ +--- +description: Windows WiFi connections +keywords: + - windows + - registry +--- + +# WiFi + +Artemis supports extracting WiFi access points that the Windows system has connected +to. By default it will try to parse WiFi networks at SOFTWARE Registry file. + +# Collection + +You have to use the artemis [api](../../API/overview.md) in order to get WiFi +network. + +# Sample API Script + +```typescript +import { wifiNetworksWindows } from "./artemis-api/mod"; + +function main() { + const results = wifiNetworksWindows(); + console.log(JSON.stringify(results)); +} + +main(); +``` + +# Output Structure + +An array of `Wifi` + +```typescript +export interface Wifi { + name: string; + description: string; + managed: boolean; + category: WifiCategory; + created_local_time: string; + name_type: NameType; + id: string; + last_connected_local_time: string; + registry_path: string; + registry_file: string; + message: string; + datetime: string; + timestamp_desc: "Registry Key Modified"; + artifact: "WiFi Network"; + data_type: "windows:registry:wifi:entry"; +} + +export enum WifiCategory { + Public = "Public", + Private = "Private", + Domain = "Domain", + Unknown = "Unknown", +} + +/** + * From: https://community.spiceworks.com/t/what-are-the-nametype-values-for-the-networklist-registry-keys/526112/6 + */ +export enum NameType { + Wired = "Wired", + Vpn = "VPN", + Wireless = "Wireless", + Mobile = "Mobile", + Unknown = "Unknown", + +} +``` diff --git a/artemis-docs/docs/Artifacts/macOS Artifacts/wifi.md b/artemis-docs/docs/Artifacts/macOS Artifacts/wifi.md index d7212e9a..9d181156 100644 --- a/artemis-docs/docs/Artifacts/macOS Artifacts/wifi.md +++ b/artemis-docs/docs/Artifacts/macOS Artifacts/wifi.md @@ -7,7 +7,7 @@ keywords: # WiFi -Artemis supports extract WiFi access points that the macOS system has connected +Artemis supports extracting WiFi access points that the macOS system has connected to. By default it will try to parse WiFi networks at /Library/Preferences/com.apple.wifi.known-networks.plist. diff --git a/artemis-docs/docs/Artifacts/overview.md b/artemis-docs/docs/Artifacts/overview.md index 666bd978..0ea6ff8c 100644 --- a/artemis-docs/docs/Artifacts/overview.md +++ b/artemis-docs/docs/Artifacts/overview.md @@ -18,11 +18,11 @@ A breakdown of artifacts by OS is below. | OS | Number of Artifacts | | --------------------------------- | ------------------- | -| [Windows](./windows.md) | 42 | +| [Windows](./windows.md) | 46 | | [macOS](./macos.md) | 43 | | [Linux](./linux.md) | 23 | | [FreeBSD](./freebsd.md) | 8 | -| [Applications](./applications.md) | 12 | +| [Applications](./applications.md) | 13 | Artemis also supports parsing apps and artifacts from unencrypted iTunes backups diff --git a/artemis-docs/package-lock.json b/artemis-docs/package-lock.json index 38b53271..7ef453af 100644 --- a/artemis-docs/package-lock.json +++ b/artemis-docs/package-lock.json @@ -8,32 +8,33 @@ "name": "artemis-docs", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.9.1", - "@docusaurus/preset-classic": "^3.9.1", - "@docusaurus/theme-mermaid": "^3.9.1", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.0.0", - "prism-react-renderer": "^2.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "@docusaurus/core": "^3.9.2", + "@docusaurus/preset-classic": "^3.9.2", + "@docusaurus/theme-mermaid": "^3.9.2", + "@mdx-js/react": "^3.1.1", + "clsx": "^2.1.1", + "prism-react-renderer": "^2.4.1", + "react": "^19.2.0", + "react-dom": "^19.2.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.9.1", - "@tsconfig/docusaurus": "^2.0.2", - "typescript": "~5.2.2" + "@docusaurus/module-type-aliases": "^3.9.2", + "@tsconfig/docusaurus": "^2.0.7", + "typescript": "~5.9.3" }, "engines": { "node": ">=16.14" } }, "node_modules/@ai-sdk/gateway": { - "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-1.0.30.tgz", - "integrity": "sha512-QdrSUryr/CLcsCISokLHOImcHj1adGXk1yy4B3qipqLhcNc33Kj/O/3crI790Qp85oDx7sc4vm7R4raf9RA/kg==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.17.tgz", + "integrity": "sha512-oVAG6q72KsjKlrYdLhWjRO7rcqAR8CjokAbYuyVZoCO4Uh2PH/VzZoxZav71w2ipwlXhHCNaInGYWNs889MMDA==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.10" + "@ai-sdk/provider-utils": "3.0.18", + "@vercel/oidc": "3.0.5" }, "engines": { "node": ">=18" @@ -55,14 +56,14 @@ } }, "node_modules/@ai-sdk/provider-utils": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.10.tgz", - "integrity": "sha512-T1gZ76gEIwffep6MWI0QNy9jgoybUHE7TRaHB5k54K8mF91ciGFlbtCGxDYhMH3nCRergKwYFIDeFF0hJSIQHQ==", + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz", + "integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", - "eventsource-parser": "^3.0.5" + "eventsource-parser": "^3.0.6" }, "engines": { "node": ">=18" @@ -72,13 +73,13 @@ } }, "node_modules/@ai-sdk/react": { - "version": "2.0.56", - "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-2.0.56.tgz", - "integrity": "sha512-7glIc65IZYFx+GZIcvMFdp+lkJnpsgRJNGRhStF6naUXtCrhjC5SyyXFMwZk+GMk3ZK9Kb83zdnWqtO7LOXGuA==", + "version": "2.0.104", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-2.0.104.tgz", + "integrity": "sha512-vpRNUwOrHXSsywZuEge78/LPbYMR/3tkBnwijGpIGnORMa/SzYhuVsE+sZBFVo/v0m5K/tg+CXNNvuJrVZ/MBQ==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider-utils": "3.0.10", - "ai": "5.0.56", + "@ai-sdk/provider-utils": "3.0.18", + "ai": "5.0.104", "swr": "^2.2.5", "throttleit": "2.1.0" }, @@ -96,15 +97,15 @@ } }, "node_modules/@algolia/abtesting": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.5.0.tgz", - "integrity": "sha512-W/ohRkbKQsqDWALJg28X15KF7Tcyg53L1MfdOkLgvkcCcofdzGHSimHHeNG05ojjFw9HK8+VPhe/Vwq4MozIJg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.11.0.tgz", + "integrity": "sha512-a7oQ8dwiyoyVmzLY0FcuBqyqcNSq78qlcOtHmNBumRlHCSnXDcuoYGBGPN1F6n8JoGhviDDsIaF/oQrzTzs6Lg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" @@ -143,99 +144,99 @@ } }, "node_modules/@algolia/client-abtesting": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.39.0.tgz", - "integrity": "sha512-Vf0ZVe+qo3sHDrCinouJqlg8VoxM4Qo/KxNIqMYybkuctutfnp3kIY9OmESplOQ/9NGBthU9EG+4d5fBibWK/A==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.45.0.tgz", + "integrity": "sha512-WTW0VZA8xHMbzuQD5b3f41ovKZ0MNTIXkWfm0F2PU+XGcLxmxX15UqODzF2sWab0vSbi3URM1xLhJx+bXbd1eQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.39.0.tgz", - "integrity": "sha512-V16ITZxYIwcv1arNce65JZmn94Ft6vKlBZ//gXw8AvIH32glJz1KcbaVAUr9p7PYlGZ/XVHP6LxDgrpNdtwgcA==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.45.0.tgz", + "integrity": "sha512-I3g7VtvG/QJOH3tQO7E7zWTwBfK/nIQXShFLR8RvPgWburZ626JNj332M3wHCYcaAMivN9WJG66S2JNXhm6+Xg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.39.0.tgz", - "integrity": "sha512-UCJTuwySEQeiKPWV3wruhuI/wHbDYenHzgL9pYsvh6r/u5Z+g61ip1iwdAlFp02CnywzI9O7+AQPh2ManYyHmQ==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.45.0.tgz", + "integrity": "sha512-/nTqm1tLiPtbUr+8kHKyFiCOfhRfgC+JxLvOCq471gFZZOlsh6VtFRiKI60/zGmHTojFC6B0mD80PB7KeK94og==", "license": "MIT", "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-insights": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.39.0.tgz", - "integrity": "sha512-s0ia8M/ZZR+iO2uLNTBrlQdEb6ZMAMcKMHckp5mcoglxrf8gHifL4LmdhGKdAxAn3UIagtqIP0RCnIymHUbm7A==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.45.0.tgz", + "integrity": "sha512-suQTx/1bRL1g/K2hRtbK3ANmbzaZCi13487sxxmqok+alBDKKw0/TI73ZiHjjFXM2NV52inwwcmW4fUR45206Q==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.39.0.tgz", - "integrity": "sha512-vZPIt7Lw+toNsHZUiPhNIc1Z3vUjDp7nzn6AMOaPC73gEuTq2iLPNvM06CSB6aHePo5eMeJIP5YEKBUQUA/PJA==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.45.0.tgz", + "integrity": "sha512-CId/dbjpzI3eoUhPU6rt/z4GrRsDesqFISEMOwrqWNSrf4FJhiUIzN42Ac+Gzg69uC0RnzRYy60K1y4Na5VSMw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.39.0.tgz", - "integrity": "sha512-jcPQr3iKTWNVli2NYHPv02aNLwixDjPCpOgMp9CZTvEiPI6Ec4jHX+oFr3LDZagOFY9e1xJhc/JrgMGGW1sHnw==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.45.0.tgz", + "integrity": "sha512-tjbBKfA8fjAiFtvl9g/MpIPiD6pf3fj7rirVfh1eMIUi8ybHP4ovDzIaE216vHuRXoePQVCkMd2CokKvYq1CLw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.39.0.tgz", - "integrity": "sha512-/IYpF10BpthGZEJQZMhMqV4AqWr5avcWfZm/SIKK1RvUDmzGqLoW/+xeJVX9C8ZnNkIC8hivbIQFaNaRw0BFZQ==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.45.0.tgz", + "integrity": "sha512-nxuCid+Nszs4xqwIMDw11pRJPes2c+Th1yup/+LtpjFH8QWXkr3SirNYSD3OXAeM060HgWWPLA8/Fxk+vwxQOA==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" @@ -248,81 +249,81 @@ "license": "MIT" }, "node_modules/@algolia/ingestion": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.39.0.tgz", - "integrity": "sha512-IgSHKUiuecqLfBlXiuCSdRTdsO3/yvpmXrMFz8fAJ8M4QmDtHkOuD769dmybRYqsbYMHivw+lir4BgbRGMtOIQ==", + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.45.0.tgz", + "integrity": "sha512-t+1doBzhkQTeOOjLHMlm4slmXBhvgtEGQhOmNpMPTnIgWOyZyESWdm+XD984qM4Ej1i9FRh8VttOGrdGnAjAng==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.39.0.tgz", - "integrity": "sha512-8Xnd4+609SKC/hqVsuFc4evFBmvA2765/4NcH+Dpr756SKPbL1BY0X8kVxlmM3YBLNqnduSQxHxpDJUK58imCA==", + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.45.0.tgz", + "integrity": "sha512-IaX3ZX1A/0wlgWZue+1BNWlq5xtJgsRo7uUk/aSiYD7lPbJ7dFuZ+yTLFLKgbl4O0QcyHTj1/mSBj9ryF1Lizg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.39.0.tgz", - "integrity": "sha512-D7Ye2Ss/5xqUkQUxKm/VqEJLt5kARd9IMmjdzlxaKhGgNlOemTay0lwBmOVFuJRp7UODjp5c9+K+B8g0ORObIw==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.45.0.tgz", + "integrity": "sha512-1jeMLoOhkgezCCPsOqkScwYzAAc1Jr5T2hisZl0s32D94ZV7d1OHozBukgOjf8Dw+6Hgi6j52jlAdUWTtkX9Mg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "@algolia/client-common": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.39.0.tgz", - "integrity": "sha512-mgPte1ZJqpk9dkVs44J3wKAbHATvHZNlSpzhMdjMLIg/3qTycSZyDiomLiSlxE8CLsxyBAOJWnyKRHfom+Z1rg==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.45.0.tgz", + "integrity": "sha512-46FIoUkQ9N7wq4/YkHS5/W9Yjm4Ab+q5kfbahdyMpkBPJ7IBlwuNEGnWUZIQ6JfUZuJVojRujPRHMihX4awUMg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0" + "@algolia/client-common": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.39.0.tgz", - "integrity": "sha512-LIrCkrxu1WnO3ev1+w6NnZ12JZL/o+2H9w6oWnZAjQZIlA/Ym6M9QHkt+OQ/SwkuoiNkW3DAo+Pi4A2V9FPtqg==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.45.0.tgz", + "integrity": "sha512-XFTSAtCwy4HdBhSReN2rhSyH/nZOM3q3qe5ERG2FLbYId62heIlJBGVyAPRbltRwNlotlydbvSJ+SQ0ruWC2cw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0" + "@algolia/client-common": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.39.0.tgz", - "integrity": "sha512-6beG+egPwXmvhAg+m0STCj+ZssDcjrLzf4L05aKm2nGglMXSSPz0cH/rM+kVD9krNfldiMctURd4wjojW1fV0w==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.45.0.tgz", + "integrity": "sha512-8mTg6lHx5i44raCU52APsu0EqMsdm4+7Hch/e4ZsYZw0hzwkuaMFh826ngnkYf9XOl58nHoou63aZ874m8AbpQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.39.0" + "@algolia/client-common": "5.45.0" }, "engines": { "node": ">= 14.0.0" @@ -341,15 +342,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@antfu/utils": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", - "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -365,29 +357,29 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -413,13 +405,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -466,17 +458,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", - "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.3", + "@babel/traverse": "^7.28.5", "semver": "^6.3.1" }, "engines": { @@ -496,13 +488,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", - "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "regexpu-core": "^6.2.0", + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "engines": { @@ -547,13 +539,13 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", - "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -667,9 +659,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -712,12 +704,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.4" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -727,13 +719,13 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", - "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -970,9 +962,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.4.tgz", - "integrity": "sha512-1yxmvN0MJHOhPVmAsmoW5liWwoILobu/d/ShymZmj867bAdxGbehIrew1DuLpw2Ukv+qDSSPQdYW1dLNE7t11A==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz", + "integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1053,13 +1045,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", - "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1147,9 +1139,9 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", - "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz", + "integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1240,9 +1232,9 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", - "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz", + "integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1302,15 +1294,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", - "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", + "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-module-transforms": "^7.28.3", "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1447,9 +1439,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", - "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz", + "integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1652,9 +1644,9 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz", - "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.5.tgz", + "integrity": "sha512-20NUVgOrinudkIBzQ2bNxP08YpKprUkRTiRSd2/Z5GOdPImJGkoN4Z7IQe1T5AdyKI1i5L6RBmluqdSzvaq9/w==", "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", @@ -1757,13 +1749,13 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", - "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", + "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1" @@ -1839,16 +1831,16 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz", - "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.5.tgz", + "integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.0", + "@babel/compat-data": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", @@ -1861,42 +1853,42 @@ "@babel/plugin-transform-async-generator-functions": "^7.28.0", "@babel/plugin-transform-async-to-generator": "^7.27.1", "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.0", + "@babel/plugin-transform-block-scoping": "^7.28.5", "@babel/plugin-transform-class-properties": "^7.27.1", "@babel/plugin-transform-class-static-block": "^7.28.3", - "@babel/plugin-transform-classes": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.4", "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-dotall-regex": "^7.27.1", "@babel/plugin-transform-duplicate-keys": "^7.27.1", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", "@babel/plugin-transform-dynamic-import": "^7.27.1", "@babel/plugin-transform-explicit-resource-management": "^7.28.0", - "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-exponentiation-operator": "^7.28.5", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/plugin-transform-for-of": "^7.27.1", "@babel/plugin-transform-function-name": "^7.27.1", "@babel/plugin-transform-json-strings": "^7.27.1", "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.5", "@babel/plugin-transform-member-expression-literals": "^7.27.1", "@babel/plugin-transform-modules-amd": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.28.5", "@babel/plugin-transform-modules-umd": "^7.27.1", "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", "@babel/plugin-transform-new-target": "^7.27.1", "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.28.0", + "@babel/plugin-transform-object-rest-spread": "^7.28.4", "@babel/plugin-transform-object-super": "^7.27.1", "@babel/plugin-transform-optional-catch-binding": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.28.5", "@babel/plugin-transform-parameters": "^7.27.7", "@babel/plugin-transform-private-methods": "^7.27.1", "@babel/plugin-transform-private-property-in-object": "^7.27.1", "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.3", + "@babel/plugin-transform-regenerator": "^7.28.4", "@babel/plugin-transform-regexp-modifiers": "^7.27.1", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", @@ -1946,14 +1938,14 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz", - "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", + "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.28.0", "@babel/plugin-transform-react-jsx": "^7.27.1", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1" @@ -1966,16 +1958,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", - "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-typescript": "^7.27.1" + "@babel/plugin-transform-typescript": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1985,9 +1977,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2020,17 +2012,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", + "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", + "@babel/types": "^7.28.5", "debug": "^4.3.1" }, "engines": { @@ -2038,13 +2030,13 @@ } }, "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -2339,9 +2331,9 @@ } }, "node_modules/@csstools/postcss-cascade-layers/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -2760,9 +2752,9 @@ } }, "node_modules/@csstools/postcss-is-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -3159,9 +3151,9 @@ } }, "node_modules/@csstools/postcss-scope-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -3331,21 +3323,44 @@ "node": ">=10.0.0" } }, + "node_modules/@docsearch/core": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.3.1.tgz", + "integrity": "sha512-ktVbkePE+2h9RwqCUMbWXOoebFyDOxHqImAqfs+lC8yOU+XwEW4jgvHGJK079deTeHtdhUNj0PXHSnhJINvHzQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": ">= 16.8.0 < 20.0.0", + "react": ">= 16.8.0 < 20.0.0", + "react-dom": ">= 16.8.0 < 20.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/@docsearch/css": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.1.0.tgz", - "integrity": "sha512-nuNKGjHj/FQeWgE9t+i83QD/V67QiaAmGY7xS9TVCRUiCqSljOgIKlsLoQZKKVwEG8f+OWKdznzZkJxGZ7d06A==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.3.2.tgz", + "integrity": "sha512-K3Yhay9MgkBjJJ0WEL5MxnACModX9xuNt3UlQQkDEDZJZ0+aeWKtOkxHNndMRkMBnHdYvQjxkm6mdlneOtU1IQ==", "license": "MIT" }, "node_modules/@docsearch/react": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.1.0.tgz", - "integrity": "sha512-4GHI7TT3sJZ2Vs4Kjadv7vAkMrTsJqHvzvxO3JA7UT8iPRKaDottG5o5uNshPWhVVaBYPC35Ukf8bfCotGpjSg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.3.2.tgz", + "integrity": "sha512-74SFD6WluwvgsOPqifYOviEEVwDxslxfhakTlra+JviaNcs7KK/rjsPj89kVEoQc9FUxRkAofaJnHIR7pb4TSQ==", "license": "MIT", "dependencies": { "@ai-sdk/react": "^2.0.30", "@algolia/autocomplete-core": "1.19.2", - "@docsearch/css": "4.1.0", + "@docsearch/core": "4.3.1", + "@docsearch/css": "4.3.2", "ai": "^5.0.30", "algoliasearch": "^5.28.0", "marked": "^16.3.0", @@ -3372,22 +3387,10 @@ } } }, - "node_modules/@docsearch/react/node_modules/marked": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.3.0.tgz", - "integrity": "sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" - } - }, "node_modules/@docusaurus/babel": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.1.tgz", - "integrity": "sha512-/uoi3oG+wvbVWNBRfPrzrEslOSeLxrQEyWMywK51TLDFTANqIRivzkMusudh5bdDty8fXzCYUT+tg5t697jYqg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", + "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", @@ -3400,8 +3403,8 @@ "@babel/runtime": "^7.25.9", "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.9.1", - "@docusaurus/utils": "3.9.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -3411,17 +3414,17 @@ } }, "node_modules/@docusaurus/bundler": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.1.tgz", - "integrity": "sha512-E1c9DgNmAz4NqbNtiJVp4UgjLtr8O01IgtXD/NDQ4PZaK8895cMiTOgb3k7mN0qX8A3lb8vqyrPJ842+yMpuUg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", + "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.9.1", - "@docusaurus/cssnano-preset": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", + "@docusaurus/babel": "3.9.2", + "@docusaurus/cssnano-preset": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", "babel-loader": "^9.2.1", "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", @@ -3454,18 +3457,18 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.1.tgz", - "integrity": "sha512-FWDk1LIGD5UR5Zmm9rCrXRoxZUgbwuP6FBA7rc50DVfzqDOMkeMe3NyJhOsA2dF0zBE3VbHEIMmTjKwTZJwbaA==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.9.1", - "@docusaurus/bundler": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", + "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.9.2", + "@docusaurus/bundler": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3515,9 +3518,9 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.1.tgz", - "integrity": "sha512-2y7+s7RWQMqBg+9ejeKwvZs7Bdw/hHIVJIodwMXbs2kr+S48AhcmAfdOh6Cwm0unJb0hJUshN0ROwRoQMwl3xg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", + "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", "license": "MIT", "dependencies": { "cssnano-preset-advanced": "^6.1.2", @@ -3530,9 +3533,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.1.tgz", - "integrity": "sha512-C9iFzXwHzwvGlisE4bZx+XQE0JIqlGAYAd5LzpR7fEDgjctu7yL8bE5U4nTNywXKHURDzMt4RJK8V6+stFHVkA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz", + "integrity": "sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==", "license": "MIT", "dependencies": { "chalk": "^4.1.2", @@ -3543,14 +3546,14 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.1.tgz", - "integrity": "sha512-/1PY8lqry8jCt0qZddJSpc0U2sH6XC27kVJZfpA7o2TiQ3mdBQyH5AVbj/B2m682B1ounE+XjI0LdpOkAQLPoA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", + "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -3582,12 +3585,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.1.tgz", - "integrity": "sha512-YBce3GbJGGcMbJTyHcnEOMvdXqg41pa5HsrMCGA5Rm4z0h0tHS6YtEldj0mlfQRhCG7Y0VD66t2tb87Aom+11g==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.2.tgz", + "integrity": "sha512-8qVe2QA9hVLzvnxP46ysuofJUIc/yYQ82tvA/rBTrnpXtCjNSFLxEZfd5U8cYZuJIVlkPxamsIgwd5tGZXfvew==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.9.1", + "@docusaurus/types": "3.9.2", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3601,19 +3604,19 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.1.tgz", - "integrity": "sha512-vT6kIimpJLWvW9iuWzH4u7VpTdsGlmn4yfyhq0/Kb1h4kf9uVouGsTmrD7WgtYBUG1P+TSmQzUUQa+ALBSRTig==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.2.tgz", + "integrity": "sha512-3I2HXy3L1QcjLJLGAoTvoBnpOwa6DPUa3Q0dMK19UTY9mhPkKQg/DYhAGTiBUKcTR0f08iw7kLPqOhIgdV3eVQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", @@ -3635,20 +3638,20 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.1.tgz", - "integrity": "sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/module-type-aliases": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", + "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/module-type-aliases": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -3668,16 +3671,16 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.1.tgz", - "integrity": "sha512-/1wFzRnXYASI+Nv9ck9IVPIMw0O5BGQ8ZVhDzEwhkL+tl44ycvSnY6PIe6rW2HLxsw61Z3WFwAiU8+xMMtMZpg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.2.tgz", + "integrity": "sha512-s4849w/p4noXUrGpPUF0BPqIAfdAe76BLaRGAGKZ1gTDNiGxGcpsLcwJ9OTi1/V8A+AzvsmI9pkjie2zjIQZKA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -3691,15 +3694,15 @@ } }, "node_modules/@docusaurus/plugin-css-cascade-layers": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.1.tgz", - "integrity": "sha512-/QyW2gRCk/XE3ttCK/ERIgle8KJ024dBNKMu6U5SmpJvuT2il1n5jR/48Pp/9wEwut8WVml4imNm6X8JsL5A0Q==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.2.tgz", + "integrity": "sha512-w1s3+Ss+eOQbscGM4cfIFBlVg/QKxyYgj26k5AnakuHkKxH6004ZtuLe5awMBotIYF2bbGDoDhpgQ4r/kcj4rQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "tslib": "^2.6.0" }, "engines": { @@ -3707,14 +3710,14 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.1.tgz", - "integrity": "sha512-qPeAuk0LccC251d7jg2MRhNI+o7niyqa924oEM/AxnZJvIpMa596aAxkRImiAqNN6+gtLE1Hkrz/RHUH2HDGsA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.2.tgz", + "integrity": "sha512-j7a5hWuAFxyQAkilZwhsQ/b3T7FfHZ+0dub6j/GxKNFJp2h9qk/P1Bp7vrGASnvA9KNQBBL1ZXTe7jlh4VdPdA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", "fs-extra": "^11.1.1", "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" @@ -3728,14 +3731,14 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.1.tgz", - "integrity": "sha512-k4Qq2HphqOrIU/CevGPdEO1yJnWUI8m0zOJsYt5NfMJwNsIn/gDD6gv/DKD+hxHndQT5pacsfBd4BWHZVNVroQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.2.tgz", + "integrity": "sha512-mAwwQJ1Us9jL/lVjXtErXto4p4/iaLlweC54yDUK1a97WfkC6Z2k5/769JsFgwOwOP+n5mUQGACXOEQ0XDuVUw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "tslib": "^2.6.0" }, "engines": { @@ -3747,14 +3750,14 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.1.tgz", - "integrity": "sha512-n9BURBiQyJKI/Ecz35IUjXYwXcgNCSq7/eA07+ZYcDiSyH2p/EjPf8q/QcZG3CyEJPZ/SzGkDHePfcVPahY4Gg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.2.tgz", + "integrity": "sha512-YJ4lDCphabBtw19ooSlc1MnxtYGpjFV9rEdzjLsUnBCeis2djUyCozZaFhCg6NGEwOn7HDDyMh0yzcdRpnuIvA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -3767,14 +3770,14 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.1.tgz", - "integrity": "sha512-rZAQZ25ZuXaThBajxzLjXieTDUCMmBzfAA6ThElQ3o7Q+LEpOjCIrwGFau0KLY9HeG6x91+FwwsAM8zeApYDrg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.2.tgz", + "integrity": "sha512-LJtIrkZN/tuHD8NqDAW1Tnw0ekOwRTfobWPsdO15YxcicBo2ykKF0/D6n0vVBfd3srwr9Z6rzrIWYrMzBGrvNw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "tslib": "^2.6.0" }, "engines": { @@ -3786,17 +3789,17 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.1.tgz", - "integrity": "sha512-k/bf5cXDxAJUYTzqatgFJwmZsLUbIgl6S8AdZMKGG2Mv2wcOHt+EQNN9qPyWZ5/9cFj+Q8f8DN+KQheBMYLong==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.2.tgz", + "integrity": "sha512-WLh7ymgDXjG8oPoM/T4/zUP7KcSuFYRZAUTl8vR6VzYkfc18GBM4xLhcT+AKOwun6kBivYKUJf+vlqYJkm+RHw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -3810,15 +3813,15 @@ } }, "node_modules/@docusaurus/plugin-svgr": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.1.tgz", - "integrity": "sha512-TeZOXT2PSdTNR1OpDJMkYqFyX7MMhbd4t16hQByXksgZQCXNyw3Dio+KaDJ2Nj+LA4WkOvsk45bWgYG5MAaXSQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.2.tgz", + "integrity": "sha512-n+1DE+5b3Lnf27TgVU5jM1d4x5tUh2oW5LTsBxJX4PsAPV0JGcmI6p3yLYtEY0LRVEIJh+8RsdQmRE66wSV8mw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@svgr/core": "8.1.0", "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", @@ -3833,26 +3836,26 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.1.tgz", - "integrity": "sha512-ZHga2xsxxsyd0dN1BpLj8S889Eu9eMBuj2suqxdw/vaaXu/FjJ8KEGbcaeo6nHPo8VQcBBnPEdkBtSDm2TfMNw==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/plugin-content-blog": "3.9.1", - "@docusaurus/plugin-content-docs": "3.9.1", - "@docusaurus/plugin-content-pages": "3.9.1", - "@docusaurus/plugin-css-cascade-layers": "3.9.1", - "@docusaurus/plugin-debug": "3.9.1", - "@docusaurus/plugin-google-analytics": "3.9.1", - "@docusaurus/plugin-google-gtag": "3.9.1", - "@docusaurus/plugin-google-tag-manager": "3.9.1", - "@docusaurus/plugin-sitemap": "3.9.1", - "@docusaurus/plugin-svgr": "3.9.1", - "@docusaurus/theme-classic": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/theme-search-algolia": "3.9.1", - "@docusaurus/types": "3.9.1" + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.2.tgz", + "integrity": "sha512-IgyYO2Gvaigi21LuDIe+nvmN/dfGXAiMcV/murFqcpjnZc7jxFAxW+9LEjdPt61uZLxG4ByW/oUmX/DDK9t/8w==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/plugin-content-blog": "3.9.2", + "@docusaurus/plugin-content-docs": "3.9.2", + "@docusaurus/plugin-content-pages": "3.9.2", + "@docusaurus/plugin-css-cascade-layers": "3.9.2", + "@docusaurus/plugin-debug": "3.9.2", + "@docusaurus/plugin-google-analytics": "3.9.2", + "@docusaurus/plugin-google-gtag": "3.9.2", + "@docusaurus/plugin-google-tag-manager": "3.9.2", + "@docusaurus/plugin-sitemap": "3.9.2", + "@docusaurus/plugin-svgr": "3.9.2", + "@docusaurus/theme-classic": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/theme-search-algolia": "3.9.2", + "@docusaurus/types": "3.9.2" }, "engines": { "node": ">=20.0" @@ -3863,24 +3866,24 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.1.tgz", - "integrity": "sha512-LrAIu/mQ04nG6s1cssC0TMmICD8twFIIn/hJ5Pd9uIPQvtKnyAKEn12RefopAul5KfMo9kixPaqogV5jIJr26w==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/module-type-aliases": "3.9.1", - "@docusaurus/plugin-content-blog": "3.9.1", - "@docusaurus/plugin-content-docs": "3.9.1", - "@docusaurus/plugin-content-pages": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/theme-translations": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.2.tgz", + "integrity": "sha512-IGUsArG5hhekXd7RDb11v94ycpJpFdJPkLnt10fFQWOVxAtq5/D7hT6lzc2fhyQKaaCE62qVajOMKL7OiAFAIA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/module-type-aliases": "3.9.2", + "@docusaurus/plugin-content-blog": "3.9.2", + "@docusaurus/plugin-content-docs": "3.9.2", + "@docusaurus/plugin-content-pages": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/theme-translations": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "infima": "0.2.0-alpha.45", @@ -3903,15 +3906,15 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.1.tgz", - "integrity": "sha512-j9adi961F+6Ps9d0jcb5BokMcbjXAAJqKkV43eo8nh4YgmDj7KUNDX4EnOh/MjTQeO06oPY5cxp3yUXdW/8Ggw==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.2.tgz", + "integrity": "sha512-6c4DAbR6n6nPbnZhY2V3tzpnKnGL+6aOsLvFL26VRqhlczli9eWG0VDUNoCQEPnGwDMhPS42UhSAnz5pThm5Ag==", "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.9.1", - "@docusaurus/module-type-aliases": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", + "@docusaurus/mdx-loader": "3.9.2", + "@docusaurus/module-type-aliases": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3931,16 +3934,16 @@ } }, "node_modules/@docusaurus/theme-mermaid": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.9.1.tgz", - "integrity": "sha512-aKMFlQfxueVBPdCdrNSshG12fOkJXSn1sb6EhI/sGn3UpiTEiazJm4QLP6NoF78mqq8O5Ar2Yll+iHWLvCsuZQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.9.2.tgz", + "integrity": "sha512-5vhShRDq/ntLzdInsQkTdoKWSzw8d1jB17sNPYhA/KvYYFXfuVEGHLM6nrf8MFbV8TruAHDG21Fn3W4lO8GaDw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.1", - "@docusaurus/module-type-aliases": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/module-type-aliases": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "mermaid": ">=11.6.0", "tslib": "^2.6.0" }, @@ -3959,19 +3962,19 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.1.tgz", - "integrity": "sha512-WjM28bzlgfT6nHlEJemkwyGVpvGsZWPireV/w+wZ1Uo64xCZ8lNOb4xwQRukDaLSed3oPBN0gSnu06l5VuCXHg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.2.tgz", + "integrity": "sha512-GBDSFNwjnh5/LdkxCKQHkgO2pIMX1447BxYUBG2wBiajS21uj64a+gH/qlbQjDLxmGrbrllBrtJkUHxIsiwRnw==", "license": "MIT", "dependencies": { "@docsearch/react": "^3.9.0 || ^4.1.0", - "@docusaurus/core": "3.9.1", - "@docusaurus/logger": "3.9.1", - "@docusaurus/plugin-content-docs": "3.9.1", - "@docusaurus/theme-common": "3.9.1", - "@docusaurus/theme-translations": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-validation": "3.9.1", + "@docusaurus/core": "3.9.2", + "@docusaurus/logger": "3.9.2", + "@docusaurus/plugin-content-docs": "3.9.2", + "@docusaurus/theme-common": "3.9.2", + "@docusaurus/theme-translations": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-validation": "3.9.2", "algoliasearch": "^5.37.0", "algoliasearch-helper": "^3.26.0", "clsx": "^2.0.0", @@ -3990,9 +3993,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.1.tgz", - "integrity": "sha512-mUQd49BSGKTiM6vP9+JFgRJL28lMIN3PUvXjF3rzuOHMByUZUBNwCt26Z23GkKiSIOrRkjKoaBNTipR/MHdYSQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.2.tgz", + "integrity": "sha512-vIryvpP18ON9T9rjgMRFLr2xJVDpw1rtagEGf8Ccce4CkTrvM/fRB8N2nyWYOW5u3DdjkwKw5fBa+3tbn9P4PA==", "license": "MIT", "dependencies": { "fs-extra": "^11.1.1", @@ -4003,9 +4006,9 @@ } }, "node_modules/@docusaurus/types": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.1.tgz", - "integrity": "sha512-ElekJ29sk39s5LTEZMByY1c2oH9FMtw7KbWFU3BtuQ1TytfIK39HhUivDEJvm5KCLyEnnfUZlvSNDXeyk0vzAA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", + "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", @@ -4039,14 +4042,14 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.1.tgz", - "integrity": "sha512-YAL4yhhWLl9DXuf5MVig260a6INz4MehrBGFU/CZu8yXmRiYEuQvRFWh9ZsjfAOyaG7za1MNmBVZ4VVAi/CiJA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.2.tgz", + "integrity": "sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.1", - "@docusaurus/types": "3.9.1", - "@docusaurus/utils-common": "3.9.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/types": "3.9.2", + "@docusaurus/utils-common": "3.9.2", "escape-string-regexp": "^4.0.0", "execa": "5.1.1", "file-loader": "^6.2.0", @@ -4071,12 +4074,12 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.1.tgz", - "integrity": "sha512-4M1u5Q8Zn2CYL2TJ864M51FV4YlxyGyfC3x+7CLuR6xsyTVNBNU4QMcPgsTHRS9J2+X6Lq7MyH6hiWXyi/sXUQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.2.tgz", + "integrity": "sha512-I53UC1QctruA6SWLvbjbhCpAw7+X7PePoe5pYcwTOEXD/PxeP8LnECAhTHHwWCblyUX5bMi4QLRkxvyZ+IT8Aw==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.9.1", + "@docusaurus/types": "3.9.2", "tslib": "^2.6.0" }, "engines": { @@ -4084,14 +4087,14 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.1.tgz", - "integrity": "sha512-5bzab5si3E1udrlZuVGR17857Lfwe8iFPoy5AvMP9PXqDfoyIKT7gDQgAmxdRDMurgHaJlyhXEHHdzDKkOxxZQ==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.2.tgz", + "integrity": "sha512-l7yk3X5VnNmATbwijJkexdhulNsQaNDwoagiwujXoxFbWLcxHQqNQ+c/IAlzrfMMOfa/8xSBZ7KEKDesE/2J7A==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.1", - "@docusaurus/utils": "3.9.1", - "@docusaurus/utils-common": "3.9.1", + "@docusaurus/logger": "3.9.2", + "@docusaurus/utils": "3.9.2", + "@docusaurus/utils-common": "3.9.2", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -4124,31 +4127,14 @@ "license": "MIT" }, "node_modules/@iconify/utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", - "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", "license": "MIT", "dependencies": { - "@antfu/install-pkg": "^1.0.0", - "@antfu/utils": "^8.1.0", + "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", - "debug": "^4.4.0", - "globals": "^15.14.0", - "kolorist": "^1.8.0", - "local-pkg": "^1.0.0", - "mlly": "^1.7.4" - } - }, - "node_modules/@iconify/utils/node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "mlly": "^1.8.0" } }, "node_modules/@jest/schemas": { @@ -4210,9 +4196,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -4220,9 +4206,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -4252,9 +4238,9 @@ } }, "node_modules/@jsonjoy.com/buffers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.0.0.tgz", - "integrity": "sha512-NDigYR3PHqCnQLXYyoLbnEdzMMvzeiCWo1KOut7Q0CoIqg9tUAPKJ1iq/2nFhc5kZtexzutNY0LFjdwWL3Dw3Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", "license": "Apache-2.0", "engines": { "node": ">=10.0" @@ -4284,18 +4270,19 @@ } }, "node_modules/@jsonjoy.com/json-pack": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.14.0.tgz", - "integrity": "sha512-LpWbYgVnKzphN5S6uss4M25jJ/9+m6q6UJoeN6zTkK4xAGhKsiBRPVeF7OYMWonn5repMQbE5vieRXcMUrKDKw==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/base64": "^1.1.2", - "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/buffers": "^1.2.0", "@jsonjoy.com/codegen": "^1.0.0", - "@jsonjoy.com/json-pointer": "^1.0.1", + "@jsonjoy.com/json-pointer": "^1.0.2", "@jsonjoy.com/util": "^1.9.0", "hyperdyperid": "^1.2.0", - "thingies": "^2.5.0" + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" }, "engines": { "node": ">=10.0" @@ -4392,9 +4379,9 @@ } }, "node_modules/@mdx-js/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", - "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", + "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", "dependencies": { "@types/mdx": "^2.0.0" @@ -4409,9 +4396,9 @@ } }, "node_modules/@mermaid-js/parser": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.4.0.tgz", - "integrity": "sha512-wla8XOWvQAwuqy+gxiZqY+c7FokraOTHRWMsbB4AgRx9Sy7zKslNyejy7E+a77qHfey5GXw/ik3IXv/NHMJgaA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", + "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", "license": "MIT", "dependencies": { "langium": "3.3.1" @@ -4843,9 +4830,9 @@ } }, "node_modules/@tsconfig/docusaurus": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/docusaurus/-/docusaurus-2.0.3.tgz", - "integrity": "sha512-3l1L5PzWVa7l0691TjnsZ0yOIEwG9DziSqu5IPZPlI5Dowi7z42cEym8Y35GHbgHvPcBfNxfrbxm7Cncn4nByQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@tsconfig/docusaurus/-/docusaurus-2.0.7.tgz", + "integrity": "sha512-sDDxcltg2pcV0U3sQf5EMaX4/ER+x3IXmUc5EXuz4JnFDyxfGhTG7zGKJ8cLLZzjZALgdTK2LSKQbFLSKuGvQQ==", "dev": true, "license": "MIT" }, @@ -4926,9 +4913,9 @@ } }, "node_modules/@types/d3-array": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", - "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", "license": "MIT" }, "node_modules/@types/d3-axis": { @@ -4978,9 +4965,9 @@ "license": "MIT" }, "node_modules/@types/d3-dispatch": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", - "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", "license": "MIT" }, "node_modules/@types/d3-drag": { @@ -5170,9 +5157,9 @@ } }, "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==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/estree-jsx": { @@ -5185,21 +5172,21 @@ } }, "node_modules/@types/express": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", - "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", - "@types/serve-static": "*" + "@types/serve-static": "^1" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "version": "4.19.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", + "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -5254,9 +5241,9 @@ "license": "MIT" }, "node_modules/@types/http-proxy": { - "version": "1.17.16", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", - "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", + "version": "1.17.17", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -5320,12 +5307,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz", - "integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==", + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.16.0" } }, "node_modules/@types/node-forge": { @@ -5356,12 +5343,12 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.1.5", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.5.tgz", - "integrity": "sha512-piErsCVVbpMMT2r7wbawdZsq4xMvIAhQuac2gedQHysu1TZYEigE6pnFfgZT+/jQnrRuF5r+SHzuehFjfRjr4g==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", + "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", "dependencies": { - "csstype": "^3.0.2" + "csstype": "^3.2.2" } }, "node_modules/@types/react-router": { @@ -5412,12 +5399,11 @@ } }, "node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "license": "MIT", "dependencies": { - "@types/mime": "^1", "@types/node": "*" } }, @@ -5431,14 +5417,24 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", "license": "MIT", "dependencies": { "@types/http-errors": "*", "@types/node": "*", - "@types/send": "*" + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" } }, "node_modules/@types/sockjs": { @@ -5473,9 +5469,9 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", "license": "MIT", "dependencies": { "@types/yargs-parser": "*" @@ -5493,6 +5489,15 @@ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, + "node_modules/@vercel/oidc": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.0.5.tgz", + "integrity": "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -5695,9 +5700,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -5706,6 +5711,18 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -5750,14 +5767,14 @@ } }, "node_modules/ai": { - "version": "5.0.56", - "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.56.tgz", - "integrity": "sha512-Rl++Ogg6DxzFkVHAOJZzhqcqvqtBLGOP9mMxJOGr2EJWj5HH5zjqDcnRh6x5vBoca5kj/Gd0rvUZFMnyI+sRiw==", + "version": "5.0.104", + "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.104.tgz", + "integrity": "sha512-MZOkL9++nY5PfkpWKBR3Rv+Oygxpb9S16ctv8h91GvrSif7UnNEdPMVZe3bUyMd2djxf0AtBk/csBixP0WwWZQ==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/gateway": "1.0.30", + "@ai-sdk/gateway": "2.0.17", "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.10", + "@ai-sdk/provider-utils": "3.0.18", "@opentelemetry/api": "1.9.0" }, "engines": { @@ -5813,34 +5830,34 @@ } }, "node_modules/algoliasearch": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.39.0.tgz", - "integrity": "sha512-DzTfhUxzg9QBNGzU/0kZkxEV72TeA4MmPJ7RVfLnQwHNhhliPo7ynglEWJS791rNlLFoTyrKvkapwr/P3EXV9A==", - "license": "MIT", - "dependencies": { - "@algolia/abtesting": "1.5.0", - "@algolia/client-abtesting": "5.39.0", - "@algolia/client-analytics": "5.39.0", - "@algolia/client-common": "5.39.0", - "@algolia/client-insights": "5.39.0", - "@algolia/client-personalization": "5.39.0", - "@algolia/client-query-suggestions": "5.39.0", - "@algolia/client-search": "5.39.0", - "@algolia/ingestion": "1.39.0", - "@algolia/monitoring": "1.39.0", - "@algolia/recommend": "5.39.0", - "@algolia/requester-browser-xhr": "5.39.0", - "@algolia/requester-fetch": "5.39.0", - "@algolia/requester-node-http": "5.39.0" + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.45.0.tgz", + "integrity": "sha512-wrj4FGr14heLOYkBKV3Fbq5ZBGuIFeDJkTilYq/G+hH1CSlQBtYvG2X1j67flwv0fUeQJwnWxxRIunSemAZirA==", + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.11.0", + "@algolia/client-abtesting": "5.45.0", + "@algolia/client-analytics": "5.45.0", + "@algolia/client-common": "5.45.0", + "@algolia/client-insights": "5.45.0", + "@algolia/client-personalization": "5.45.0", + "@algolia/client-query-suggestions": "5.45.0", + "@algolia/client-search": "5.45.0", + "@algolia/ingestion": "1.45.0", + "@algolia/monitoring": "1.45.0", + "@algolia/recommend": "5.45.0", + "@algolia/requester-browser-xhr": "5.45.0", + "@algolia/requester-fetch": "5.45.0", + "@algolia/requester-node-http": "5.45.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.26.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz", - "integrity": "sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw==", + "version": "3.26.1", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.26.1.tgz", + "integrity": "sha512-CAlCxm4fYBXtvc5MamDzP6Svu8rW4z9me4DCBY1rQ2UDJ0u0flWmusQ8M3nOExZsLLRcUwUPoRAPMrhzOG3erw==", "license": "MIT", "dependencies": { "@algolia/events": "^4.0.1" @@ -5991,9 +6008,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", "funding": [ { "type": "opencollective", @@ -6010,9 +6027,9 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -6118,9 +6135,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.7.tgz", - "integrity": "sha512-bxxN2M3a4d1CRoQC//IqsR5XrLh0IJ8TCv2x6Y9N0nckNz/rTjZB3//GGscZziZOxmjP55rzxg/ze7usFI9FqQ==", + "version": "2.8.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.32.tgz", + "integrity": "sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -6274,9 +6291,9 @@ } }, "node_modules/browserslist": { - "version": "4.26.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", - "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", + "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", "funding": [ { "type": "opencollective", @@ -6293,11 +6310,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.3", - "caniuse-lite": "^1.0.30001741", - "electron-to-chromium": "^1.5.218", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.8.25", + "caniuse-lite": "^1.0.30001754", + "electron-to-chromium": "^1.5.249", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" @@ -6454,9 +6471,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001745", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001745.tgz", - "integrity": "sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==", + "version": "1.0.30001757", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", + "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", "funding": [ { "type": "opencollective", @@ -6904,9 +6921,9 @@ "license": "MIT" }, "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", "license": "MIT" }, "node_modules/config-chain": { @@ -6919,6 +6936,12 @@ "proto-list": "~1.2.1" } }, + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, "node_modules/configstore": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", @@ -7063,9 +7086,9 @@ } }, "node_modules/core-js": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", - "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==", + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz", + "integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -7074,12 +7097,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.45.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.1.tgz", - "integrity": "sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==", + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", + "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", "license": "MIT", "dependencies": { - "browserslist": "^4.25.3" + "browserslist": "^4.28.0" }, "funding": { "type": "opencollective", @@ -7087,9 +7110,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.45.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.45.1.tgz", - "integrity": "sha512-OHnWFKgTUshEU8MK+lOs1H8kC8GkTi9Z1tvNkxrCcw9wl3MJIO7q2ld77wjWn4/xuGrVu2X+nME1iIIPBSdyEQ==", + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.47.0.tgz", + "integrity": "sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -7205,9 +7228,9 @@ } }, "node_modules/css-blank-pseudo/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -7279,9 +7302,9 @@ } }, "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -7422,9 +7445,9 @@ } }, "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "license": "BSD-2-Clause", "engines": { "node": ">= 6" @@ -7592,15 +7615,15 @@ "license": "CC0-1.0" }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/cytoscape": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.32.0.tgz", - "integrity": "sha512-5JHBC9n75kz5851jeklCPmZWcg3hUe6sjqJvyk3+hVqFaKcHwHgxsjeN1yLmggoUc6STbtm9/NQyabQehfjvWQ==", + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", + "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", "license": "MIT", "engines": { "node": ">=0.10" @@ -8096,9 +8119,9 @@ } }, "node_modules/dagre-d3-es": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz", - "integrity": "sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", + "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", "license": "MIT", "dependencies": { "d3": "^7.9.0", @@ -8106,9 +8129,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "license": "MIT" }, "node_modules/debounce": { @@ -8118,9 +8141,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -8193,9 +8216,9 @@ } }, "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", + "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", @@ -8209,9 +8232,9 @@ } }, "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", "license": "MIT", "engines": { "node": ">=18" @@ -8420,9 +8443,9 @@ } }, "node_modules/dompurify": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", - "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz", + "integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -8509,9 +8532,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.224", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.224.tgz", - "integrity": "sha512-kWAoUu/bwzvnhpdZSIc6KUyvkI1rbRXMT0Eq8pKReyOyaPZcctMli+EgvcN1PAvwVc7Tdo4Fxi2PsLNDU05mdg==", + "version": "1.5.262", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz", + "integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -8555,9 +8578,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -8820,9 +8843,9 @@ } }, "node_modules/estree-util-value-to-estree": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.4.0.tgz", - "integrity": "sha512-Zlp+gxis+gCfK12d3Srl2PdX2ybsEA8ZYy6vQGVQTNNYLEGRQQ56XB64bjemN8kxIKXP1nC9ip4Z+ILy9LGzvQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.5.0.tgz", + "integrity": "sha512-aMV56R27Gv3QmfmF1MY12GWkGzzeAezAX+UplqHVASfjc9wNzI/X6hC0S9oxq61WT4aQesLGslWP9tKk6ghRZQ==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" @@ -9031,12 +9054,6 @@ "node": ">= 0.6" } }, - "node_modules/exsolve": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", - "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", - "license": "MIT" - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -9084,9 +9101,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "funding": [ { "type": "github", @@ -9371,15 +9388,15 @@ } }, "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", "license": "MIT", "engines": { "node": "*" }, "funding": { - "type": "patreon", + "type": "github", "url": "https://github.com/sponsors/rawify" } }, @@ -9393,9 +9410,9 @@ } }, "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -9512,9 +9529,9 @@ } }, "node_modules/glob-to-regex.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.0.1.tgz", - "integrity": "sha512-CG/iEvgQqfzoVsMUbxSJcwbG2JwyZ3naEqPkeltwl0BSS8Bp83k3xlGms+0QdWFUAwV+uvo80wNswKF6FWEkKg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", "license": "Apache-2.0", "engines": { "node": ">=10.0" @@ -9548,15 +9565,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/global-dirs/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -9657,9 +9665,9 @@ } }, "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -10064,9 +10072,9 @@ } }, "node_modules/html-webpack-plugin": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", - "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.5.tgz", + "integrity": "sha512-4xynFbKNNk+WlzXeQQ+6YYsH2g7mpfPszQZUi3ovKlj+pDmngQ7vRXjrrmGROabmKwyQkcgcX5hqfOwHbFmK5g==", "license": "MIT", "dependencies": { "@types/html-minifier-terser": "^6.0.0", @@ -10363,15 +10371,18 @@ "license": "ISC" }, "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "license": "ISC" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "license": "ISC", + "engines": { + "node": ">=10" + } }, "node_modules/inline-style-parser": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", - "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, "node_modules/internmap": { @@ -10393,9 +10404,9 @@ } }, "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", "license": "MIT", "engines": { "node": ">= 10" @@ -10606,9 +10617,9 @@ } }, "node_modules/is-npm": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", - "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.1.0.tgz", + "integrity": "sha512-O2z4/kNgyjhQwVR1Wpkbfc19JIhggF97NZNCpWTnjH7kVcZMUrnut9XSN7txI7VdyIYk5ZatOq3zvSuWpU8hoA==", "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -10813,9 +10824,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -10873,9 +10884,9 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -10885,9 +10896,9 @@ } }, "node_modules/katex": { - "version": "0.16.22", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", - "integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==", + "version": "0.16.25", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.25.tgz", + "integrity": "sha512-woHRUZ/iF23GBP1dkDQMh1QBad9dmr8/PAwNA54VrSOVYgI12MAcE14TqnDdQOdzyEonGzMepYnqBMYdsoAr8Q==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -10941,12 +10952,6 @@ "node": ">=6" } }, - "node_modules/kolorist": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", - "license": "MIT" - }, "node_modules/langium": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", @@ -10979,9 +10984,9 @@ } }, "node_modules/launch-editor": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.1.tgz", - "integrity": "sha512-SEET7oNfgSaB6Ym0jufAdCeo3meJVeCaaDyzRygy0xsp2BFKCprcfHljTq4QkzTLUxEKkFK6OK4811YM2oSrRg==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", + "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", "license": "MIT", "dependencies": { "picocolors": "^1.1.1", @@ -11022,12 +11027,16 @@ "license": "MIT" }, "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", "license": "MIT", "engines": { "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/loader-utils": { @@ -11044,23 +11053,6 @@ "node": ">=8.9.0" } }, - "node_modules/local-pkg": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz", - "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==", - "license": "MIT", - "dependencies": { - "mlly": "^1.7.4", - "pkg-types": "^2.0.1", - "quansync": "^0.2.8" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/locate-path": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", @@ -11181,15 +11173,15 @@ } }, "node_modules/marked": { - "version": "15.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", - "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", "license": "MIT", "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 18" + "node": ">= 20" } }, "node_modules/math-intrinsics": { @@ -11549,9 +11541,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -11619,9 +11611,9 @@ } }, "node_modules/memfs": { - "version": "4.46.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.46.1.tgz", - "integrity": "sha512-2wjHDg7IjP+ufAqqqSxjiNePFDrvWviA79ajUwG9lkHhk3HzZOLBzzoUG8cx9vCagj6VvBQD7oXuLuFz5LaAOQ==", + "version": "4.51.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.51.0.tgz", + "integrity": "sha512-4zngfkVM/GpIhC8YazOsM6E8hoB33NP0BCESPOA6z7qaL6umPJNqkO8CNYaLV2FB2MV6H1O3x2luHHOSqppv+A==", "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/json-pack": "^1.11.0", @@ -11661,27 +11653,27 @@ } }, "node_modules/mermaid": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.6.0.tgz", - "integrity": "sha512-PE8hGUy1LDlWIHWBP05SFdqUHGmRcCcK4IzpOKPE35eOw+G9zZgcnMpyunJVUEOgb//KBORPjysKndw8bFLuRg==", + "version": "11.12.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.1.tgz", + "integrity": "sha512-UlIZrRariB11TY1RtTgUWp65tphtBv4CSq7vyS2ZZ2TgoMjs2nloq+wFqxiwcxlhHUvs7DPGgMjs2aeQxz5h9g==", "license": "MIT", "dependencies": { - "@braintree/sanitize-url": "^7.0.4", - "@iconify/utils": "^2.1.33", - "@mermaid-js/parser": "^0.4.0", + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.1", + "@mermaid-js/parser": "^0.6.3", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.11", - "dayjs": "^1.11.13", - "dompurify": "^3.2.4", - "katex": "^0.16.9", + "dagre-d3-es": "7.0.13", + "dayjs": "^1.11.18", + "dompurify": "^3.2.5", + "katex": "^0.16.22", "khroma": "^2.1.0", "lodash-es": "^4.17.21", - "marked": "^15.0.7", + "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", @@ -13596,32 +13588,15 @@ } }, "node_modules/mlly": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", - "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", - "license": "MIT", - "dependencies": { - "acorn": "^8.14.0", - "pathe": "^2.0.1", - "pkg-types": "^1.3.0", - "ufo": "^1.5.4" - } - }, - "node_modules/mlly/node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "license": "MIT" - }, - "node_modules/mlly/node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", "license": "MIT", "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" } }, "node_modules/mrmime": { @@ -13711,18 +13686,18 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } }, "node_modules/node-releases": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", - "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "license": "MIT" }, "node_modules/normalize-path": { @@ -13744,9 +13719,9 @@ } }, "node_modules/normalize-url": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", + "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", "license": "MIT", "engines": { "node": ">=14.16" @@ -14099,9 +14074,9 @@ } }, "node_modules/package-manager-detector": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", - "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", "license": "MIT" }, "node_modules/param-case": { @@ -14325,14 +14300,14 @@ } }, "node_modules/pkg-types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", - "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", "license": "MIT", "dependencies": { - "confbox": "^0.2.1", - "exsolve": "^1.0.1", - "pathe": "^2.0.3" + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" } }, "node_modules/points-on-curve": { @@ -14405,9 +14380,9 @@ } }, "node_modules/postcss-attribute-case-insensitive/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -14649,9 +14624,9 @@ } }, "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -14687,9 +14662,9 @@ } }, "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -14815,9 +14790,9 @@ } }, "node_modules/postcss-focus-visible/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -14853,9 +14828,9 @@ } }, "node_modules/postcss-focus-within/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15142,9 +15117,9 @@ } }, "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15170,9 +15145,9 @@ } }, "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15269,9 +15244,9 @@ } }, "node_modules/postcss-nesting/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15628,9 +15603,9 @@ } }, "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15721,9 +15696,9 @@ } }, "node_modules/postcss-selector-not/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -15929,9 +15904,9 @@ } }, "node_modules/pupa": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", - "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.3.0.tgz", + "integrity": "sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA==", "license": "MIT", "dependencies": { "escape-goat": "^4.0.0" @@ -15958,22 +15933,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/quansync": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz", - "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/antfu" - }, - { - "type": "individual", - "url": "https://github.com/sponsors/sxzz" - } - ], - "license": "MIT" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -16075,6 +16034,12 @@ "rc": "cli.js" } }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -16085,28 +16050,24 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.2.0" } }, "node_modules/react-fast-compare": { @@ -16704,12 +16665,12 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -16882,19 +16843,16 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "license": "ISC" + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "license": "BlueOak-1.0.0" }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" }, "node_modules/schema-dts": { "version": "1.1.5", @@ -16903,9 +16861,9 @@ "license": "Apache-2.0" }, "node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -16961,9 +16919,9 @@ } }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -17529,9 +17487,9 @@ } }, "node_modules/std-env": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "license": "MIT" }, "node_modules/string_decoder": { @@ -17561,9 +17519,9 @@ } }, "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { "node": ">=12" @@ -17573,9 +17531,9 @@ } }, "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -17658,21 +17616,21 @@ } }, "node_modules/style-to-js": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", - "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", "license": "MIT", "dependencies": { - "style-to-object": "1.0.9" + "style-to-object": "1.0.14" } }, "node_modules/style-to-object": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", - "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", "license": "MIT", "dependencies": { - "inline-style-parser": "0.2.4" + "inline-style-parser": "0.2.7" } }, "node_modules/stylehacks": { @@ -17762,9 +17720,9 @@ } }, "node_modules/swr": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.6.tgz", - "integrity": "sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.7.tgz", + "integrity": "sha512-ZEquQ82QvalqTxhBVv/DlAg2mbmUjF4UgpPg9wwk4ufb9rQnZXh1iKyyKBqV6bQGu1Ie7L1QwSYO07qFIa1p+g==", "license": "MIT", "dependencies": { "dequal": "^2.0.3", @@ -17775,22 +17733,26 @@ } }, "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/terser": { - "version": "5.39.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.2.tgz", - "integrity": "sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg==", + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.14.0", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -17917,15 +17879,18 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", - "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", - "license": "MIT" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/tinypool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz", - "integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" @@ -18068,9 +18033,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -18088,9 +18053,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -18177,9 +18142,9 @@ } }, "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -18244,9 +18209,9 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -18276,9 +18241,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", "funding": [ { "type": "opencollective", @@ -18368,9 +18333,9 @@ } }, "node_modules/update-notifier/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -18486,9 +18451,9 @@ } }, "node_modules/use-sync-external-store": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -18676,35 +18641,36 @@ } }, "node_modules/webpack": { - "version": "5.99.9", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", - "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "version": "5.103.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.103.0.tgz", + "integrity": "sha512-HU1JOuV1OavsZ+mfigY0j8d1TgQgbZ6M+J75zDkpEAwYeXjWSqrGJtgnPblJjd/mAyTNQ7ygw0MiKOn6etz8yw==", "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", + "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.26.3", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", + "enhanced-resolve": "^5.17.3", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", - "tapable": "^2.1.1", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "watchpack": "^2.4.4", + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -18796,15 +18762,19 @@ } }, "node_modules/webpack-dev-middleware/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/webpack-dev-middleware/node_modules/range-parser": { @@ -18939,9 +18909,9 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.0.tgz", - "integrity": "sha512-77R0RDmJfj9dyv5p3bM5pOHa+X8/ZkO9c7kpDstigkC4nIDobadsfSGCwB4bKhMVxqAok8tajaoR8rirM7+VFQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "license": "MIT", "engines": { "node": ">=10.13.0" @@ -19117,9 +19087,9 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { "node": ">=12" @@ -19129,9 +19099,9 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", "engines": { "node": ">=12" @@ -19141,9 +19111,9 @@ } }, "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -19249,9 +19219,9 @@ "license": "ISC" }, "node_modules/yocto-queue": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", - "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", "license": "MIT", "engines": { "node": ">=12.20" @@ -19261,9 +19231,9 @@ } }, "node_modules/zod": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz", - "integrity": "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", + "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/artemis-docs/package.json b/artemis-docs/package.json index 38108723..7eaf4b7d 100644 --- a/artemis-docs/package.json +++ b/artemis-docs/package.json @@ -15,19 +15,19 @@ "typecheck": "tsc" }, "dependencies": { - "@docusaurus/core": "^3.9.1", - "@docusaurus/preset-classic": "^3.9.1", - "@docusaurus/theme-mermaid": "^3.9.1", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.0.0", - "prism-react-renderer": "^2.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "@docusaurus/core": "^3.9.2", + "@docusaurus/preset-classic": "^3.9.2", + "@docusaurus/theme-mermaid": "^3.9.2", + "@mdx-js/react": "^3.1.1", + "clsx": "^2.1.1", + "prism-react-renderer": "^2.4.1", + "react": "^19.2.0", + "react-dom": "^19.2.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.9.1", - "@tsconfig/docusaurus": "^2.0.2", - "typescript": "~5.2.2" + "@docusaurus/module-type-aliases": "^3.9.2", + "@tsconfig/docusaurus": "^2.0.7", + "typescript": "~5.9.3" }, "browserslist": { "production": [ @@ -44,4 +44,4 @@ "engines": { "node": ">=16.14" } -} +} \ No newline at end of file diff --git a/eslint.config.mts b/eslint.config.mts new file mode 100644 index 00000000..424c6786 --- /dev/null +++ b/eslint.config.mts @@ -0,0 +1,19 @@ +import js from "@eslint/js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import { defineConfig } from "eslint/config"; + +export default defineConfig([ + { files: [ "**/*.{js,mjs,cjs,ts,mts,cts}" ], plugins: { js }, extends: [ "js/recommended" ], languageOptions: { globals: globals.browser } }, + { files: [ "**/*.js" ], languageOptions: { sourceType: "script" } }, { + ignores: [ ".node_modules/*", "./artemis-docs/*", "./tests/*/*/main.js" ] + }, + tseslint.configs.strict, + { + languageOptions: { + parserOptions: { + projectService: true, + } + } + } +]); diff --git a/mod.ts b/mod.ts index 4eb375be..e36c0026 100644 --- a/mod.ts +++ b/mod.ts @@ -17,6 +17,8 @@ export { Epiphany } from "./src/linux/gnome/epiphany"; export { firmwareHistory } from "./src/linux/firmware"; export { kateRecentFiles } from "./src/linux/kde/kate"; export { Falkon } from "./src/linux/kde/falkon/falkon"; +export { queryLogons } from "./src/linux/sqlite/wtmpdb"; +export { readRawFileExt4, readRawDirExt4, readRawInodeExt4 } from "./src/linux/ext4"; /** * macOS exported functions @@ -56,6 +58,7 @@ export { gatekeeperEntries } from "./src/macos/sqlite/gatekeeper"; export { parseCookies } from "./src/macos/safari/cookies"; export { Safari } from "./src/macos/safari/safari"; export { authorizations } from "./src/macos/sqlite/authd"; + /** * Unix exported functions */ @@ -93,6 +96,8 @@ export { querySqlite } from "./src/applications/sqlite"; export { NextcloudClient } from "./src/applications/nextcloud/cloud"; export { LevelDb } from "./src/applications/leveldb/level"; export { AnyDesk } from "./src/applications/anydesk/rmm"; +export { OneDrive } from "./src/applications/onedrive/onedrive"; +export { Syncthing } from "./src/applications/syncthing"; /** * Windows exported functions @@ -137,9 +142,14 @@ export { parseWordWheel } from "./src/windows/registry/wordwheel"; export { UserAccessLogging } from "./src/windows/ese/ual"; export { Updates } from "./src/windows/ese/updates"; export { Outlook } from "./src/windows/outlook"; +export { ADCertificates } from "./src/windows/ese/certs"; export { assembleScriptblocks } from "./src/windows/eventlogs/scriptblocks"; export { firewallRules } from "./src/windows/registry/firewall_rules"; export { processTreeEventLogs } from "./src/windows/eventlogs/processtree"; +export { wifiNetworksWindows } from "./src/windows/registry/wifi"; +export { getRunKeys } from "./src/windows/registry/run"; +export { serviceInstalls } from "./src/windows/eventlogs/services"; +export { getEventlogProviders } from "./src/windows/registry/eventlog_providers"; /** * FreeBSD diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..6d5cd655 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1561 @@ +{ + "name": "artemis-api", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@eslint/js": "^9.39.1", + "@typescript-eslint/eslint-plugin": "^8.48.0", + "@typescript-eslint/parser": "^8.48.0", + "eslint": "^9.39.1", + "globals": "^16.5.0", + "jiti": "^2.6.1", + "typescript-eslint": "^8.48.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@types/estree": { + "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", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.0.tgz", + "integrity": "sha512-XxXP5tL1txl13YFtrECECQYeZjBZad4fyd3cFV4a19LkAY/bIp9fev3US4S5fDVV2JaYFiKAZ/GRTOLer+mbyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.48.0", + "@typescript-eslint/type-utils": "8.48.0", + "@typescript-eslint/utils": "8.48.0", + "@typescript-eslint/visitor-keys": "8.48.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.48.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.0.tgz", + "integrity": "sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.48.0", + "@typescript-eslint/types": "8.48.0", + "@typescript-eslint/typescript-estree": "8.48.0", + "@typescript-eslint/visitor-keys": "8.48.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.0.tgz", + "integrity": "sha512-Ne4CTZyRh1BecBf84siv42wv5vQvVmgtk8AuiEffKTUo3DrBaGYZueJSxxBZ8fjk/N3DrgChH4TOdIOwOwiqqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.48.0", + "@typescript-eslint/types": "^8.48.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.0.tgz", + "integrity": "sha512-uGSSsbrtJrLduti0Q1Q9+BF1/iFKaxGoQwjWOIVNJv0o6omrdyR8ct37m4xIl5Zzpkp69Kkmvom7QFTtue89YQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.0", + "@typescript-eslint/visitor-keys": "8.48.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.0.tgz", + "integrity": "sha512-WNebjBdFdyu10sR1M4OXTt2OkMd5KWIL+LLfeH9KhgP+jzfDV/LI3eXzwJ1s9+Yc0Kzo2fQCdY/OpdusCMmh6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.0.tgz", + "integrity": "sha512-zbeVaVqeXhhab6QNEKfK96Xyc7UQuoFWERhEnj3mLVnUWrQnv15cJNseUni7f3g557gm0e46LZ6IJ4NJVOgOpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.0", + "@typescript-eslint/typescript-estree": "8.48.0", + "@typescript-eslint/utils": "8.48.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.0.tgz", + "integrity": "sha512-cQMcGQQH7kwKoVswD1xdOytxQR60MWKM1di26xSUtxehaDs/32Zpqsu5WJlXTtTTqyAVK8R7hvsUnIXRS+bjvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.0.tgz", + "integrity": "sha512-ljHab1CSO4rGrQIAyizUS6UGHHCiAYhbfcIZ1zVJr5nMryxlXMVWS3duFPSKvSUbFPwkXMFk1k0EMIjub4sRRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.48.0", + "@typescript-eslint/tsconfig-utils": "8.48.0", + "@typescript-eslint/types": "8.48.0", + "@typescript-eslint/visitor-keys": "8.48.0", + "debug": "^4.3.4", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.0.tgz", + "integrity": "sha512-yTJO1XuGxCsSfIVt1+1UrLHtue8xz16V8apzPYI06W0HbEbEWHxHXgZaAgavIkoh+GeV6hKKd5jm0sS6OYxWXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.48.0", + "@typescript-eslint/types": "8.48.0", + "@typescript-eslint/typescript-estree": "8.48.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.0.tgz", + "integrity": "sha512-T0XJMaRPOH3+LBbAfzR2jalckP1MSG/L9eUtY0DEzUyVaXJ/t6zN0nR7co5kz0Jko/nkSYCBRkz1djvjajVTTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.0.tgz", + "integrity": "sha512-fcKOvQD9GUn3Xw63EgiDqhvWJ5jsyZUaekl3KVpGsDJnN46WJTe3jWxtQP9lMZm1LJNkFLlTaWAxK2vUQR+cqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.48.0", + "@typescript-eslint/parser": "8.48.0", + "@typescript-eslint/typescript-estree": "8.48.0", + "@typescript-eslint/utils": "8.48.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..99ad518b --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "scripts": { + "lint": "npx eslint --ext .ts ", + "test_linux": "cd tests/linux && python compile_tests.py", + "test_windows": "cd tests/windows && powershell compile_tests.ps1", + "test_macos": "cd tests/macos && python compile_tests.py", + "test_application": "cd tests/applications && python compile_tests.py" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@typescript-eslint/eslint-plugin": "^8.48.0", + "@typescript-eslint/parser": "^8.48.0", + "eslint": "^9.39.1", + "globals": "^16.5.0", + "jiti": "^2.6.1", + "typescript-eslint": "^8.48.0" + } +} \ No newline at end of file diff --git a/src/applications/anydesk/rmm.ts b/src/applications/anydesk/rmm.ts index 65db6f50..83e2169d 100644 --- a/src/applications/anydesk/rmm.ts +++ b/src/applications/anydesk/rmm.ts @@ -19,7 +19,7 @@ export class AnyDesk { * @param alt_path Optional alternative directory that contains all AnyDesk related files including configs * @returns `AnyDesk` instance class */ - constructor(platform: PlatformType, alt_path?: string) { + constructor (platform: PlatformType, alt_path?: string) { this.platform = platform; // Get AnyDesk data based on PlatformType @@ -47,7 +47,7 @@ export class AnyDesk { return; } - this.paths = [{ user_path: alt_path, version: client_version, account: client_account, id: client_id }]; + this.paths = [ { user_path: alt_path, version: client_version, account: client_account, id: client_id } ]; } /** @@ -66,8 +66,8 @@ export class AnyDesk { let hits: TraceEntry[] = []; // If alternative directory was provided then parse all trace files - if (is_alt && this.paths[0] !== undefined) { - const entries = glob(`${this.paths[0].user_path}${separator}*.trace`); + if (is_alt && this.paths[ 0 ] !== undefined) { + const entries = glob(`${this.paths[ 0 ].user_path}${separator}*.trace`); if (entries instanceof FileError) { console.error(entries); return hits; @@ -76,7 +76,7 @@ export class AnyDesk { if (!entry.is_file) { continue; } - const values = readTrace(entry.full_path, this.paths[0]); + const values = readTrace(entry.full_path, this.paths[ 0 ]); hits = hits.concat(values); } return hits; @@ -84,7 +84,7 @@ export class AnyDesk { // Try parsing trace files at default paths for (const entry of this.paths) { - let path = `${entry.user_path}${separator}*.trace`; + const path = `${entry.user_path}${separator}*.trace`; const entries = glob(path); if (entries instanceof FileError) { console.error(entries); @@ -99,7 +99,7 @@ export class AnyDesk { } } // Get system trace file(s) - if (this.paths[0] !== undefined) { + if (this.paths[ 0 ] !== undefined) { const entries = glob(system); if (entries instanceof FileError) { console.error(entries); @@ -109,7 +109,7 @@ export class AnyDesk { if (!entry.is_file) { continue; } - const values = readTrace(entry.full_path, this.paths[0]); + const values = readTrace(entry.full_path, this.paths[ 0 ]); hits = hits.concat(values); } } @@ -132,8 +132,8 @@ export class AnyDesk { } // If alternative directory was provided then parse all trace files - if (is_alt && this.paths[0] !== undefined) { - const entries = glob(`${this.paths[0].user_path}${separator}*.conf`); + if (is_alt && this.paths[ 0 ] !== undefined) { + const entries = glob(`${this.paths[ 0 ].user_path}${separator}*.conf`); if (entries instanceof FileError) { console.error(entries); return hits; @@ -142,7 +142,7 @@ export class AnyDesk { if (!entry.is_file) { continue; } - const values = readConfig(entry.full_path, this.paths[0]); + const values = readConfig(entry.full_path, this.paths[ 0 ]); if (values instanceof ApplicationError) { continue; } @@ -153,7 +153,7 @@ export class AnyDesk { // Try parsing conf files at default paths for (const entry of this.paths) { - let path = `${entry.user_path}${separator}*.conf`; + const path = `${entry.user_path}${separator}*.conf`; const entries = glob(path); if (entries instanceof FileError) { console.error(entries); @@ -171,8 +171,8 @@ export class AnyDesk { } } // Get system conf file(s) - if (this.paths[0] !== undefined && this.platform === PlatformType.Linux) { - let system = "/etc/anydesk/*.conf"; + if (this.paths[ 0 ] !== undefined && this.platform === PlatformType.Linux) { + const system = "/etc/anydesk/*.conf"; const entries = glob(system); if (entries instanceof FileError) { console.error(entries); @@ -183,7 +183,7 @@ export class AnyDesk { continue; } // Get user config - const values = readConfig(entry.full_path, this.paths[0]); + const values = readConfig(entry.full_path, this.paths[ 0 ]); if (values instanceof ApplicationError) { continue; } @@ -236,7 +236,7 @@ export class AnyDesk { break; } default: { - console.warn(`Unsupported platform: ${platform}`) + console.warn(`Unsupported platform: ${platform}`); return []; } } diff --git a/src/applications/chrome.ts b/src/applications/chrome.ts index 901d0202..3ecb386b 100644 --- a/src/applications/chrome.ts +++ b/src/applications/chrome.ts @@ -1,9 +1,11 @@ -import { BrowserType, ChromiumAutofill, ChromiumBookmarks, ChromiumCookies, ChromiumDips, ChromiumDownloads, ChromiumHistory, ChromiumLocalStorage, ChromiumLogins } from "../../types/applications/chromium"; +import { BrowserType, ChromiumAutofill, ChromiumBookmarks, ChromiumCookies, ChromiumDips, ChromiumDownloads, ChromiumFavicons, ChromiumHistory, ChromiumLocalStorage, ChromiumLogins, ChromiumSession, ChromiumShortcuts, Extension, Preferences } from "../../types/applications/chromium"; import { PlatformType } from "../system/systeminfo"; import { Chromium } from "./chromium/cr"; -import { chromiumBookmarks, chromiumExtensions, chromiumPreferences } from "./chromium/json"; +import { chromiumBookmarks, chromiumExtensions } from "./chromium/json"; import { chromiumLocalStorage } from "./chromium/level"; -import { chromiumAutofill, chromiumCookies, chromiumDips, chromiumDownloads, chromiumHistory, chromiumLogins } from "./chromium/sqlite"; +import { chromiumPreferences } from "./chromium/preferences"; +import { chromiumSessions } from "./chromium/sessions"; +import { chromiumAutofill, chromiumCookies, chromiumDips, chromiumDownloads, chromiumFavicons, chromiumHistory, chromiumLogins, chromiumShortcuts } from "./chromium/sqlite"; type ChromeHistory = ChromiumHistory; type ChromeDownloads = ChromiumDownloads; @@ -13,6 +15,9 @@ type ChromeBookmarks = ChromiumBookmarks; type ChromeLogins = ChromiumLogins; type ChromeDips = ChromiumDips; type ChromeLocalStorage = ChromiumLocalStorage; +type ChromeSession = ChromiumSession; +type ChromeFavicons = ChromiumFavicons; +type ChromeShortcuts = ChromiumShortcuts; /** * Class to extract Chrome browser information. Since Chrome is based on Chromium we can leverage the existing Chromium artifacts to parse Chrome info @@ -26,7 +31,7 @@ export class Chrome extends Chromium { * @param alt_path Optional alternative path to directory contain Chrome data * @returns `Chrome` instance class */ - constructor (platform: PlatformType, unfold = false, alt_path?: string) { + constructor(platform: PlatformType, unfold = false, alt_path?: string) { super(platform, unfold, BrowserType.CHROME, alt_path); } @@ -115,15 +120,15 @@ export class Chrome extends Chromium { * Get installed Chrome extensions * @returns Array of parsed extensions */ - public override extensions(): Record[] { + public override extensions(): Extension[] { return chromiumExtensions(this.paths, this.platform); } /** * Get Chrome Preferences - * @returns Array of Preferences for each user + * @returns Array of `Preferences` for each user */ - public override preferences(): Record[] { + public override preferences(): Preferences[] { return chromiumPreferences(this.paths, this.platform); } @@ -146,6 +151,28 @@ export class Chrome extends Chromium { return chromiumBookmarks(this.paths, this.platform); } + /** + * Function to parse Chrome Favicons information. + * @param [offset=0] Starting db offset. Default is zero + * @param [limit=100] How many records to return. Default is 100 + * @returns Array of `ChromeFavicons` + */ + public override favicons(offset?: number, limit?: number): ChromeFavicons[] { + const query = `SELECT url, last_updated FROM favicons JOIN favicon_bitmaps ON favicons.id = favicon_bitmaps.id LIMIT ${limit} OFFSET ${offset}`; + return chromiumFavicons(this.paths, this.platform, query); + } + + /** + * Function to parse Chrome Shortcut information. + * @param [offset=0] Starting db offset. Default is zero + * @param [limit=100] How many records to return. Default is 100 + * @returns Array of `ChromeShortcuts` + */ + public override shortcuts(offset = 0, limit = 100): ChromeShortcuts[] { + const query = `SELECT id, text, fill_into_edit, url, contents, description, type, keyword, last_access_time FROM omni_box_shortcuts LIMIT ${limit} OFFSET ${offset}`; + return chromiumShortcuts(this.paths, this.platform, query); + } + /** * Get Chrome Local Storage * @returns Array of `ChromeLocalStorage` for each user @@ -154,6 +181,14 @@ export class Chrome extends Chromium { return chromiumLocalStorage(this.paths, this.platform); } + /** + * Get Chrome Sessions + * @returns Array of `ChromeSession` for each user + */ + public override sessions(): ChromeSession[] { + return chromiumSessions(this.paths, this.platform); + } + /** * Function to parse Chrome Login information. * @param [offset=0] Starting db offset. Default is zero diff --git a/src/applications/chromium/cr.ts b/src/applications/chromium/cr.ts index 4dc67e47..b9a98384 100644 --- a/src/applications/chromium/cr.ts +++ b/src/applications/chromium/cr.ts @@ -1,12 +1,16 @@ -import { BrowserType, ChromiumAutofill, ChromiumBookmarks, ChromiumCookies, ChromiumDips, ChromiumDownloads, ChromiumHistory, ChromiumLocalStorage, ChromiumLogins, ChromiumProfiles } from "../../../types/applications/chromium"; +import { BrowserType, ChromiumAutofill, ChromiumBookmarks, ChromiumCookies, ChromiumDips, ChromiumDownloads, ChromiumFavicons, ChromiumHistory, ChromiumLocalStorage, ChromiumLogins, ChromiumProfiles, ChromiumSession, ChromiumShortcuts, Extension, Preferences } from "../../../types/applications/chromium"; import { getEnvValue } from "../../environment/env"; import { FileError } from "../../filesystem/errors"; import { glob, readTextFile } from "../../filesystem/files"; +import { SystemError } from "../../system/error"; +import { dumpData, Output } from "../../system/output"; import { PlatformType } from "../../system/systeminfo"; import { ApplicationError, ErrorName } from "../errors"; -import { chromiumBookmarks, chromiumExtensions, chromiumPreferences } from "./json"; +import { chromiumBookmarks, chromiumExtensions } from "./json"; import { chromiumLocalStorage } from "./level"; -import { chromiumAutofill, chromiumCookies, chromiumDips, chromiumDownloads, chromiumHistory, chromiumLogins } from "./sqlite"; +import { chromiumPreferences } from "./preferences"; +import { chromiumSessions } from "./sessions"; +import { chromiumAutofill, chromiumCookies, chromiumDips, chromiumDownloads, chromiumFavicons, chromiumHistory, chromiumLogins, chromiumShortcuts } from "./sqlite"; /** * Class to extract Chromium browser information. @@ -25,7 +29,7 @@ export class Chromium { * @param alt_path Optional alternative path to directory contain Chromium data * @returns `Chromium` instance class */ - constructor (platform: PlatformType, unfold = false, browser = BrowserType.CHROMIUM, alt_path?: string) { + constructor(platform: PlatformType, unfold = false, browser = BrowserType.CHROMIUM, alt_path?: string) { this.platform = platform; this.unfold = unfold; this.browser = browser; @@ -62,11 +66,11 @@ export class Chromium { return; } - this.paths = [ { + this.paths = [{ full_path: alt_path, version: browser_version, browser: this.browser, - } ]; + }]; } /** @@ -161,6 +165,28 @@ export class Chromium { return chromiumAutofill(this.paths, this.platform, query); } + /** + * Function to parse Chromium Favicons information. + * @param [offset=0] Starting db offset. Default is zero + * @param [limit=100] How many records to return. Default is 100 + * @returns Array of `ChromiumFavicons` + */ + public favicons(offset = 0, limit = 100): ChromiumFavicons[] { + const query = `SELECT url, last_updated FROM favicons JOIN favicon_bitmaps ON favicons.id = favicon_bitmaps.id LIMIT ${limit} OFFSET ${offset}`; + return chromiumFavicons(this.paths, this.platform, query); + } + + /** + * Function to parse Chromium Shortcut information. + * @param [offset=0] Starting db offset. Default is zero + * @param [limit=100] How many records to return. Default is 100 + * @returns Array of `ChromiumShortcuts` + */ + public shortcuts(offset = 0, limit = 100): ChromiumShortcuts[] { + const query = `SELECT id, text, fill_into_edit, url, contents, description, type, keyword, last_access_time FROM omni_box_shortcuts LIMIT ${limit} OFFSET ${offset}`; + return chromiumShortcuts(this.paths, this.platform, query); + } + /** * Function to parse Chromium Login information. * @param [offset=0] Starting db offset. Default is zero @@ -187,15 +213,15 @@ export class Chromium { * Get installed Chromium extensions * @returns Array of parsed extensions */ - public extensions(): Record[] { + public extensions(): Extension[] { return chromiumExtensions(this.paths, this.platform); } /** * Get Chromium Preferences - * @returns Array of Preferences for each user + * @returns Array of `Preferences` for each user */ - public preferences(): Record[] { + public preferences(): Preferences[] { return chromiumPreferences(this.paths, this.platform); } @@ -215,6 +241,158 @@ export class Chromium { return chromiumLocalStorage(this.paths, this.platform); } + /** + * Get Chromium Sessions + * @returns Array of `ChromiumSession` for each user + */ + public sessions(): ChromiumSession[] { + return chromiumSessions(this.paths, this.platform); + } + + /** + * Function to timeline all Chromium artifacts. Similar to [Hindsight](https://github.com/obsidianforensics/hindsight) + * @param output `Output` structure object. Format type should be either `JSON` or `JSONL`. `JSONL` is recommended + */ + public retrospect(output: Output): void { + let offset = 0; + const limit = 100; + while (true) { + const entries = this.history(offset, limit); + if (entries.length === 0) { + break; + } + if (!this.unfold) { + entries.forEach(x => delete x["unfold"]); + } + const status = dumpData(entries, `retrospect_${this.browser}_history`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} history: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.cookies(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_${this.browser}_cookies`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} cookies: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.downloads(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_${this.browser}_downloads`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} downloads: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.autofill(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_${this.browser}_autofill`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} autofill: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.logins(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_${this.browser}_logins`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} logins: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.dips(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_${this.browser}_dips`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} dips: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.favicons(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_${this.browser}_favicons`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} favicons: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.shortcuts(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_${this.browser}_shortcuts`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} shortcuts: ${status}`); + } + offset += limit; + } + + const ext = this.extensions(); + let status = dumpData(ext, `retrospect_${this.browser}_extensions`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} extensions: ${status}`); + } + + const prefs = this.preferences(); + status = dumpData(prefs, `retrospect_${this.browser}_preferences`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} preferences: ${status}`); + } + + const books = this.bookmarks(); + status = dumpData(books, `retrospect_${this.browser}_bookmarks`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} bookmarks: ${status}`); + } + + const level = this.localStorage(); + status = dumpData(level, `retrospect_${this.browser}_localstorage`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} localstorage: ${status}`); + } + + const sess = this.sessions(); + status = dumpData(sess, `retrospect_${this.browser}_sessions`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline ${this.browser} sessions: ${status}`); + } + } + /** * Get base path for all browser data * @param platform OS `PlatformType` diff --git a/src/applications/chromium/json.ts b/src/applications/chromium/json.ts index dc5408ec..1c1f7b2d 100644 --- a/src/applications/chromium/json.ts +++ b/src/applications/chromium/json.ts @@ -1,6 +1,6 @@ -import { ChromiumBookmarkChildren, ChromiumBookmarks, ChromiumProfiles } from "../../../types/applications/chromium"; +import { BookmarkType, BrowserType, ChromiumBookmarks, ChromiumProfiles, Extension, } from "../../../types/applications/chromium"; import { FileError } from "../../filesystem/errors"; -import { glob, readTextFile } from "../../filesystem/files"; +import { glob, readTextFile, stat } from "../../filesystem/files"; import { PlatformType } from "../../system/systeminfo"; import { unixEpochToISO, webkitToUnixEpoch } from "../../time/conversion"; @@ -10,13 +10,13 @@ import { unixEpochToISO, webkitToUnixEpoch } from "../../time/conversion"; * @param platform OS `PlatformType` * @returns Array of parsed extensions */ -export function chromiumExtensions(paths: ChromiumProfiles[], platform: PlatformType): Record[] { - const hits: Record[] = []; +export function chromiumExtensions(paths: ChromiumProfiles[], platform: PlatformType): Extension[] { + const hits: Extension[] = []; for (const path of paths) { - let full_path = `${path.full_path}/*/*/Extensions/*/*manifest.json`; + let full_path = `${path.full_path}/*/Extensions/*/*/manifest.json`; if (platform === PlatformType.Windows) { - full_path = `${path.full_path}\\*\\*\\Extensions\\*\\*\\manifest.json`; + full_path = `${path.full_path}\\*\\Extensions\\*\\*\\manifest.json`; } const ext_paths = glob(full_path); @@ -32,61 +32,49 @@ export function chromiumExtensions(paths: ChromiumProfiles[], platform: Platform } const data = JSON.parse(extension); - data[ "manifest_path" ] = ext_entry.full_path; - data[ "browser_version" ] = path.version; - - hits.push(data); - - } - } - return hits; -} - -/** - * Get Chromium Preferences - * @param paths Array of `ChromiumProfiles` - * @param platform OS `PlatformType` - * @returns Array of Preferences - */ -export function chromiumPreferences(paths: ChromiumProfiles[], platform: PlatformType): Record[] { - const hits: Record[] = []; - - for (const path of paths) { - let full_path = `${path.full_path}/*/Preferences`; - - if (platform === PlatformType.Windows) { - full_path = `${path.full_path}\\*\\Preferences`; - } - const pref_paths = glob(full_path); - if (pref_paths instanceof FileError) { - continue; - } + const ext_info: Extension = { + version: path.version, + message: `Extension: ${data["name"] ?? ""} | Version: ${data["version"] ?? ""}`, + datetime: "1970-01-01T00:00:00.000Z", + browser: path.browser, + timestamp_desc: "Extension Created", + artifact: "Browser Extension", + data_type: `applications:${path.browser.toLowerCase()}:extensions:entry`, + name: data["name"] ?? "", + author: "", + description: data["description"] ?? "", + manifest: ext_entry.full_path, + extension_version: data["version"] ?? "", + }; + const meta = stat(ext_entry.full_path); + if (!(meta instanceof FileError)) { + ext_info.datetime = meta.created; + } - for (const entry of pref_paths) { - const pref = readTextFile(entry.full_path); - if (pref instanceof FileError) { - console.warn(`could not read file ${entry.full_path}: ${pref}`); + if (data["author"] === undefined) { + hits.push(ext_info); continue; } - const data = JSON.parse(pref); - data[ "preference_path" ] = entry.full_path; - data[ "browser_version" ] = path.version; + if (data["author"]["email"] !== undefined) { + ext_info.author = data["author"]["email"] ?? ""; + } - hits.push(data); + hits.push(ext_info); } } return hits; } + /** - * Get Chromium Preferences + * Get Chromium Bookmarks * @param paths Array of `ChromiumProfiles` * @param platform OS `PlatformType` * @returns Array of `ChromiumBookmarks` */ export function chromiumBookmarks(paths: ChromiumProfiles[], platform: PlatformType): ChromiumBookmarks[] { - const hits: ChromiumBookmarks[] = []; + let hits: ChromiumBookmarks[] = []; for (const path of paths) { let full_path = `${path.full_path}/*/Bookmarks`; @@ -106,30 +94,21 @@ export function chromiumBookmarks(paths: ChromiumProfiles[], platform: PlatformT continue; } - const books: ChromiumBookmarks = { - bookmark_bar: [], - other: [], - synced: [], - path: entry.full_path, - version: path.version, - }; const book_json = JSON.parse(results); - const bar = book_json[ "roots" ][ "bookmark_bar" ][ "children" ] as + const bar = book_json["roots"]["bookmark_bar"]["children"] as | Record[] | undefined>[] | undefined; - books.bookmark_bar = getBookmarkChildren(bar); + hits = hits.concat(getBookmarkChildren(bar, entry.full_path, path.version, BookmarkType.Bar, path.browser)); - const other = book_json[ "roots" ][ "other" ][ "children" ] as + const other = book_json["roots"]["other"]["children"] as | Record[] | undefined>[] | undefined; - books.other = getBookmarkChildren(other); + hits = hits.concat(getBookmarkChildren(other, entry.full_path, path.version, BookmarkType.Other, path.browser)); - const synced = book_json[ "roots" ][ "other" ][ "synced" ] as + const synced = book_json["roots"]["other"]["synced"] as | Record[] | undefined>[] | undefined; - books.synced = getBookmarkChildren(synced); - - hits.push(books); + hits = hits.concat(getBookmarkChildren(synced, entry.full_path, path.version, BookmarkType.Sync, path.browser)); } } return hits; @@ -144,27 +123,41 @@ function getBookmarkChildren( book: | Record[] | undefined>[] | undefined, -): ChromiumBookmarkChildren[] { - let books: ChromiumBookmarkChildren[] = []; + path: string, + version: string, + bookmark_type: BookmarkType, + browser: BrowserType +): ChromiumBookmarks[] { + let books: ChromiumBookmarks[] = []; if (typeof book === "undefined") { return books; } const adjust_time = 1000000n; for (const entry of book) { - if (typeof entry[ "children" ] === "undefined") { - const book_entry: ChromiumBookmarkChildren = { + if (typeof entry["children"] === "undefined") { + const book_entry: ChromiumBookmarks = { date_added: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "date_added" ] as string) / adjust_time), + Number(BigInt(entry["date_added"] as string) / adjust_time) )), date_last_used: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "date_last_used" ] as string) / adjust_time), + Number(BigInt(entry["date_last_used"] as string) / adjust_time) + )), + guid: entry["guid"] as string, + id: Number(entry["id"] as string), + name: entry["name"] as string, + type: entry["type"] as string, + url: entry["url"] as string, + bookmark_type, + path, + version, + message: `Bookmark - ${entry["name"] as string}`, + datetime: unixEpochToISO(webkitToUnixEpoch( + Number(BigInt(entry["date_added"] as string) / adjust_time) )), - guid: entry[ "guid" ] as string, - id: Number(entry[ "id" ] as string), - name: entry[ "name" ] as string, - type: entry[ "type" ] as string, - url: entry[ "url" ] as string, - meta_info: entry[ "meta_info" ] as unknown as Record, + timestamp_desc: "Bookmark Added", + artifact: "Browser Bookmark", + data_type: `applications:${browser.toLowerCase()}:bookmark:entry`, + browser, }; books.push(book_entry); continue; @@ -172,12 +165,59 @@ function getBookmarkChildren( books = books.concat( getBookmarkChildren( - entry[ "children" ] as + entry["children"] as | Record[] | undefined>[] | undefined, + path, + version, + bookmark_type, + browser ), ); } return books; } + +/** + * Function to test the Chromium JSON file parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the Chromium JSON parsing + */ +export function testChromiumJsonFiles(): void { + const path: ChromiumProfiles = { + full_path: "../../test_data/edge", + version: "141", + browser: BrowserType.EDGE + }; + const ext = chromiumExtensions([path], PlatformType.Darwin); + if (ext.length !== 3) { + throw `Got length ${ext.length} expected 3.......chromiumExtensions āŒ`; + } + if (ext[0]?.name != "__MSG_extName__") { + throw `Got name ${ext[0]?.name} expected "__MSG_extName__".......chromiumExtensions āŒ`; + } + console.info(` Function chromiumExtensions āœ…`); + + const book = chromiumBookmarks([path], PlatformType.Darwin); + if (book.length !== 1) { + throw `Got length ${book.length} expected 1.......chromiumBookmarks āŒ`; + } + + if (book[0]?.message != "Bookmark - Download the DuckDuckGo Browser for Mac") { + throw `Got message ${book[0]?.message} expected "Bookmark - Download the DuckDuckGo Browser for Mac".......chromiumBookmarks āŒ`; + } + + if (book[0]?.date_added != "2025-11-02T22:47:41.000Z") { + throw `Got date ${book[0]?.date_added} expected "2025-11-02T22:47:41.000Z".......chromiumBookmarks āŒ`; + } + + console.info(` Function chromiumBookmarks āœ…`); + + const child = getBookmarkChildren(undefined, "", "", BookmarkType.Bar, BrowserType.EDGE); + if (child.length !== 0) { + throw `Got length ${child.length} expected 0.......getBookmarkChildren āŒ`; + } + + console.info(` Function getBookmarkChildren āœ…`); +} \ No newline at end of file diff --git a/src/applications/chromium/level.ts b/src/applications/chromium/level.ts index 382c7e53..daac8c52 100644 --- a/src/applications/chromium/level.ts +++ b/src/applications/chromium/level.ts @@ -1,4 +1,4 @@ -import { ChromiumLocalStorage, ChromiumProfiles } from "../../../types/applications/chromium"; +import { BrowserType, ChromiumLocalStorage, ChromiumProfiles } from "../../../types/applications/chromium"; import { ValueType } from "../../../types/applications/level"; import { ProtoTag } from "../../../types/encoding/protobuf"; import { FileError } from "../../filesystem/errors"; @@ -41,12 +41,11 @@ export function chromiumLocalStorage(paths: ChromiumProfiles[], platform: Platfo for (const entry of entries as ChromiumLocalStorage[]) { entry["version"] = path.version; - let key = entry.key === "" ? entry.origin : entry.key; if (entry.state !== "Deletion") { - entry["message"] = `${key}: ${JSON.stringify(entry.value)}` + entry["message"] = `Origin: ${entry.origin} | Key: ${entry.key}: ${JSON.stringify(entry.value)}`; } else { - entry["message"] = key; + entry["message"] = `Origin: ${entry.origin} | Key: ${entry.key}`; } if (entry.value_type === ValueType.Protobuf) { entry.value = JSON.stringify(entry.value); @@ -73,35 +72,44 @@ export function chromiumLocalStorage(paths: ChromiumProfiles[], platform: Platfo let default_time = "1970-01-01T00:00:00.000Z"; const adjust_time = 1000000n; for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + if (entry === undefined) { + continue; + } // First we must find a META key entry with Protobuf data - if (entries[i].origin.startsWith("META:") && entries[i].value_type === ValueType.Protobuf) { + if (entry.origin.startsWith("META:") && entry.value_type === ValueType.Protobuf) { // The first protobuf entry should be our timestamp - const time_value = (entries[i].value as Record)["1"]; + const time_value = (entry.value as Record)["1"]; + if (time_value === undefined) { + continue; + } if (typeof time_value.value === 'number') { default_time = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(time_value.value) / adjust_time))); } } // Turn all Protobuf data into a string. Otherwise Timesketch complains - if (entries[i].value_type === ValueType.Protobuf) { - entries[i].value = JSON.stringify(entries[i].value); + if (entry.value_type === ValueType.Protobuf) { + entry.value = JSON.stringify(entry.value); } // Update our entry - (entries as ChromiumLocalStorage[])[i]["datetime"] = default_time; + const ldb_entries = (entries as ChromiumLocalStorage[])[i]; + if (ldb_entries === undefined) { + continue; + } + ldb_entries["datetime"] = default_time; } for (const entry of entries as ChromiumLocalStorage[]) { entry["version"] = path.version; - let key = entry.key === "" ? entry.origin : entry.key; if (entry.state !== "Deletion") { if (entry.value_type === ValueType.Protobuf || entry.value_type === ValueType.Array) { - entry["message"] = `${key}: ${JSON.stringify(entry.value)}`; + entry["message"] = `Origin: ${entry.origin} | Key: ${entry.key}: ${JSON.stringify(entry.value)}`; } else { - entry["message"] = `${key}: ${entry.value}`; + entry["message"] = `Origin: ${entry.origin} | Key: ${entry.key}: ${entry.value}`; } - } else { - entry["message"] = key; + entry["message"] = `Origin: ${entry.origin} | Key: ${entry.key}`; } entry["browser"] = path.browser; entry["data_type"] = "applications:leveldb:entry"; @@ -109,9 +117,36 @@ export function chromiumLocalStorage(paths: ChromiumProfiles[], platform: Platfo entry["timestamp_desc"] = "Local Storage Entry Write"; hits.push(entry); } - } } return hits; +} + +/** + * Function to test the Chromium Local Storage parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the Chromium Local Storage parsing + */ +export function testChromiumLocalStorage(): void { + const path: ChromiumProfiles = { + full_path: "../../test_data/edge", + version: "141", + browser: BrowserType.EDGE + }; + + const level = chromiumLocalStorage([path], PlatformType.Darwin); + if (level.length !== 587) { + throw `Got length ${level.length} expected 587.......chromiumLocalStorage āŒ`; + } + + if (level[345]?.message !== "Origin: _https://microsoftedge.microsoft.com | Key: logs.esw_13: {\"logTime\":\"2025-11-02T22:33:21.650Z\",\"logLevel\":\"debug\",\"eventName\":\"GetCuratedList\",\"sessionId\":\"d2fcef2f-7b0c-41d3-9c74-2fb980239265\",\"message\":\"[\\\"Started fetching curated list for: Edge_Extensions_Productivity_V2 and page no:1\\\"]\"}") { + throw `Got message ${level[345]?.message} expected "Origin: _https://microsoftedge.microsoft.com | Key: logs.esw_13: {"logTime":"2025-11-02T22:33:21.650Z","logLevel":"debug","eventName":"GetCuratedList","sessionId":"d2fcef2f-7b0c-41d3-9c74-2fb980239265","message":"[\\"Started fetching curated list for: Edge_Extensions_Productivity_V2 and page no:1\\"]"}".......chromiumLocalStorage āŒ`; + } + + if (level[257]?.origin !== "_https://www.cnn.com") { + throw `Got origin ${level[257]?.origin} expected "_https://www.cnn.com".......chromiumLocalStorage āŒ`; + } + + console.info(` Function chromiumLocalStorage āœ…`); } \ No newline at end of file diff --git a/src/applications/chromium/preferences.ts b/src/applications/chromium/preferences.ts new file mode 100644 index 00000000..abe05e81 --- /dev/null +++ b/src/applications/chromium/preferences.ts @@ -0,0 +1,273 @@ +import { glob, PlatformType, readTextFile } from "../../../mod"; +import { BrowserType, ChromiumProfiles, ExceptionCategory, Preferences } from "../../../types/applications/chromium"; +import { FileError } from "../../filesystem/errors"; +import { unixEpochToISO, webkitToUnixEpoch } from "../../time/conversion"; + +/** + * Get Chromium Preferences + * @param paths Array of `ChromiumProfiles` + * @param platform OS `PlatformType` + * @returns Array of Preferences + */ +export function chromiumPreferences(paths: ChromiumProfiles[], platform: PlatformType): Preferences[] { + let hits: Preferences[] = []; + + for (const path of paths) { + let full_path = `${path.full_path}/*/Preferences`; + + if (platform === PlatformType.Windows) { + full_path = `${path.full_path}\\*\\Preferences`; + } + const pref_paths = glob(full_path); + if (pref_paths instanceof FileError) { + continue; + } + + for (const entry of pref_paths) { + const pref = readTextFile(entry.full_path); + if (pref instanceof FileError) { + console.warn(`could not read file ${entry.full_path}: ${pref}`); + continue; + } + + const data = JSON.parse(pref); + const user_pref: Preferences = { + version: path.version, + message: "", + datetime: "", + browser: path.browser, + timestamp_desc: "Last Modified", + artifact: "User Preferences", + data_type: `applications:${path.browser.toLowerCase()}:preferences:entry`, + path: entry.full_path, + exception_category: ExceptionCategory.Zoom, + created_version: "", + profile_id: "", + preferences_created: "", + name: "", + url: "", + last_modified: "" + }; + + // Sites with zoomed preferences first + const zoom_values = zoomPrefs(data, user_pref); + const profile = data["profile"] as undefined | Profile; + if (profile === undefined) { + continue; + } + + const profile_info = profileInfo(profile, user_pref); + const sample = profile_info.at(0); + if (sample !== undefined) { + for (let i = 0; i < zoom_values.length; i++) { + const value = zoom_values[i]; + if (value === undefined) { + continue; + } + value.created_version = sample.created_version; + value.preferences_created = sample.preferences_created; + value.profile_id = sample.profile_id; + value.name = sample.name; + } + } + + hits = hits.concat(zoom_values); + hits = hits.concat(profile_info); + } + } + return hits; +} + +function zoomPrefs(data: Record>>>>, prefs: Preferences): Preferences[] { + const values: Preferences[] = []; + + const partitions = data["partition"]; + if (partitions === undefined) { + return values; + } + const levels = partitions["per_host_zoom_levels"]; + if (levels === undefined) { + return values; + } + + const urls = levels["x"]; + if (urls === undefined) { + return values; + } + + for (const key in urls) { + prefs.url = key; + const data = urls[key]; + if (data === undefined) { + continue; + } + prefs.last_modified = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(data["last_modified"] ?? 0n) / 1000000n))); + prefs.datetime = prefs.last_modified; + prefs.message = key; + values.push(Object.assign({}, prefs)); + } + + return values; +} + +interface Profile { + "created_by_version": string; + "creation_time": string; + "edge_profile_id": string | undefined; + "enterprise_profile_guid": string | undefined; + name: string; + "content_settings": { + exceptions: { + "app_banner": Record, + "client_hints": Record, + "cookie_controls_metadata": Record, + "https_enforced": Record, + "media_engagement": Record, + "site_engagement": Record, + "ssl_cert_decisions": Record, + }; + } | undefined; +} + +function profileInfo(data: Profile, pref: Preferences): Preferences[] { + pref.created_version = data.created_by_version; + pref.name = data.name; + pref.preferences_created = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(data.creation_time) / 1000000n))); + pref.profile_id = data.edge_profile_id ?? data.enterprise_profile_guid ?? ""; + + const values: Preferences[] = []; + if (data.content_settings === undefined) { + return [Object.assign({}, pref)]; + } + const banner = data.content_settings.exceptions.app_banner; + for (const key in banner) { + pref.url = key; + pref.message = key; + pref.exception_category = ExceptionCategory.AppBanner; + pref.last_modified = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(banner[key]?.last_modified ?? 0) / 1000000n))); + pref.datetime = pref.last_modified; + values.push(Object.assign({}, pref)); + } + + const hints = data.content_settings.exceptions.client_hints; + for (const key in hints) { + pref.url = key; + pref.message = key; + pref.exception_category = ExceptionCategory.ClientHints; + pref.last_modified = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(hints[key]?.last_modified ?? 0) / 1000000n))); + pref.datetime = pref.last_modified; + values.push(Object.assign({}, pref)); + } + + const cookie = data.content_settings.exceptions.cookie_controls_metadata; + for (const key in cookie) { + pref.url = key; + pref.message = key; + pref.exception_category = ExceptionCategory.CookieControls; + pref.last_modified = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(cookie[key]?.last_modified ?? 0) / 1000000n))); + pref.datetime = pref.last_modified; + values.push(Object.assign({}, pref)); + } + + const https = data.content_settings.exceptions.https_enforced; + for (const key in https) { + pref.url = key; + pref.message = key; + pref.exception_category = ExceptionCategory.HttpsEnforced; + pref.last_modified = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(https[key]?.last_modified ?? 0) / 1000000n))); + pref.datetime = pref.last_modified; + values.push(Object.assign({}, pref)); + } + + const media = data.content_settings.exceptions.media_engagement; + for (const key in media) { + pref.url = key; + pref.message = key; + pref.exception_category = ExceptionCategory.MediaEngagement; + pref.last_modified = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(media[key]?.last_modified ?? 0) / 1000000n))); + pref.datetime = pref.last_modified; + values.push(Object.assign({}, pref)); + } + + const site = data.content_settings.exceptions.site_engagement; + for (const key in site) { + pref.url = key; + pref.message = key; + pref.exception_category = ExceptionCategory.SiteEngagement; + pref.last_modified = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(site[key]?.last_modified ?? 0) / 1000000n))); + pref.datetime = pref.last_modified; + values.push(Object.assign({}, pref)); + } + + const ssl = data.content_settings.exceptions.ssl_cert_decisions; + for (const key in ssl) { + pref.url = key; + pref.message = key; + pref.exception_category = ExceptionCategory.SslCert; + pref.last_modified = unixEpochToISO(webkitToUnixEpoch(Number(BigInt(ssl[key]?.last_modified ?? 0) / 1000000n))); + pref.datetime = pref.last_modified; + values.push(Object.assign({}, pref)); + } + + return values; +} + +/** + * Function to test the Chromium Preferences file parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the Chromium Preferences parsing + */ +export function testChromiumPreferences(): void { + const path: ChromiumProfiles = { + full_path: "../../test_data/edge", + version: "141", + browser: BrowserType.EDGE + }; + + const pref = chromiumPreferences([path], PlatformType.Darwin); + if (pref.length !== 36 || pref[0] === undefined) { + throw `Got length ${pref.length} expected 36.......chromiumPreferences āŒ`; + } + + if (pref[1]?.message !== "https://github.com:443,*") { + throw `Got message ${pref[1]?.message} expected "https://github.com:443,*".......chromiumPreferences āŒ`; + } + + console.info(` Function chromiumPreferences āœ…`); + + const zoom = zoomPrefs({}, pref[0]); + if (zoom.length !== 0) { + throw `Got length ${zoom.length} expected 0.......zoomPrefs āŒ`; + } + + console.info(` Function zoomPrefs āœ…`); + + const info = profileInfo({ + created_by_version: "", + creation_time: "", + edge_profile_id: undefined, + enterprise_profile_guid: undefined, + name: "", + content_settings: undefined + }, pref[0]); + + if (info.length !== 1) { + throw `Got length ${info.length} expected 1.......profileInfo āŒ`; + } + + console.info(` Function profileInfo āœ…`); +} \ No newline at end of file diff --git a/src/applications/chromium/sessions.ts b/src/applications/chromium/sessions.ts new file mode 100644 index 00000000..00d9b363 --- /dev/null +++ b/src/applications/chromium/sessions.ts @@ -0,0 +1,1398 @@ +import { BrowserType, ChromiumProfiles, ChromiumSession, SessionCommand, SessionTabCommand, SessionType } from "../../../types/applications/chromium"; +import { extractUtf16String, extractUtf8String } from "../../encoding/strings"; +import { FileError } from "../../filesystem/errors"; +import { glob, readFile } from "../../filesystem/files"; +import { NomError } from "../../nom/error"; +import { Endian, nomUnsignedEightBytes, nomUnsignedFourBytes, nomUnsignedOneBytes, nomUnsignedTwoBytes } from "../../nom/helpers"; +import { take } from "../../nom/parsers"; +import { PlatformType } from "../../system/systeminfo"; +import { unixEpochToISO, webkitToUnixEpoch } from "../../time/conversion"; +import { ApplicationError } from "../errors"; + +/** + * Get Chromium sessions for all users + * @param paths Array of `ChromiumProfiles` + * @param platform OS `PlatformType` + * @returns Array of `ChromiumSession` + */ +export function chromiumSessions(paths: ChromiumProfiles[], platform: PlatformType): ChromiumSession[] { + let values: ChromiumSession[] = []; + for (const path of paths) { + let full_path = `${path.full_path}/*/Sessions/*`; + if (platform === PlatformType.Windows) { + full_path = `${path.full_path}\\*\\Sessions\\*`; + } + + const sessions = glob(full_path); + if (sessions instanceof FileError) { + continue; + } + for (const entry of sessions) { + if (!entry.is_file) { + continue; + } + + let session_type = SessionType.Session; + if (entry.full_path.includes("Tabs_")) { + session_type = SessionType.Tab; + } + const status = parseSession(entry.full_path, session_type, path); + if (status instanceof ApplicationError) { + console.warn(`Failed to parse session for ${entry.full_path}: ${status}`); + continue; + } + values = values.concat(status); + } + } + return values; +} + +/** + * Function to parse a session file + * @param path Path to a session file + * @param session_type `SessionType` Can be `Session` or `Tab` + * @param profile `ChromiumProfiles` object + * @returns Array of `ChromiumSession` or `ApplicationError` + */ +function parseSession(path: string, session_type: SessionType, profile: ChromiumProfiles): ChromiumSession[] | ApplicationError { + const bytes = readFile(path); + if (bytes instanceof FileError) { + return new ApplicationError(`CHROMIUM`, `Failed to read session file ${path}: ${bytes}`); + } + + const header = getHeader(bytes); + if (header instanceof ApplicationError) { + return header; + } + + const min_size = 10; + const values: ChromiumSession[] = []; + const session_command_values: Record = {}; + const tab_command_values: Record = {}; + while (header.remaining.byteLength > min_size) { + const size = nomUnsignedTwoBytes(header.remaining, Endian.Le); + if (size instanceof NomError) { + break; + } + const payload = take(size.remaining, size.value); + if (payload instanceof NomError) { + break; + } + + header.remaining = payload.remaining as Uint8Array; + + const id = nomUnsignedOneBytes(payload.nommed as Uint8Array); + if (id instanceof NomError) { + break; + } + + if (session_type === SessionType.Session) { + const command = getSessionCommand(id.value); + parseSessionCommand(command, id.remaining, session_command_values); + } else { + const command = getTabCommand(id.value); + parseTabCommand(command, id.remaining, tab_command_values); + } + } + + for (const session_id in session_command_values) { + const ses: ChromiumSession = { + version: profile.version, + message: "", + datetime: session_command_values[session_id]?.last_active ?? "1970-01-01T00:00:00Z", + browser: profile.browser, + timestamp_desc: "Last Active", + artifact: "Browser Session", + data_type: `applications:${profile.browser.toLowerCase()}:session:entry`, + session_id, + last_active: session_command_values[session_id]?.last_active ?? "1970-01-01T00:00:00Z", + url: "", + title: "", + session_type: SessionType.Session, + path, + }; + for (const entry of session_command_values[session_id]?.commands ?? []) { + if (entry[SessionCommand.UpdateTabNavigation] === undefined) { + continue; + } + ses.url = (entry[SessionCommand.UpdateTabNavigation] as Record)["url"] ?? ":"; + ses.title = (entry[SessionCommand.UpdateTabNavigation] as Record)["title"] ?? ""; + ses.message = `Session: ${ses.url} | Page Title: ${ses.title}`; + values.push(Object.assign({}, ses)); + } + } + + for (const session_id in tab_command_values) { + const ses: ChromiumSession = { + version: profile.version, + message: "", + datetime: tab_command_values[session_id]?.last_active ?? "1970-01-01T00:00:00Z", + browser: profile.browser, + timestamp_desc: "Last Active", + artifact: "Browser Session", + data_type: `applications:${profile.browser.toLowerCase()}:tab:entry`, + session_id, + last_active: tab_command_values[session_id]?.last_active ?? "1970-01-01T00:00:00Z", + url: "", + title: "", + session_type: SessionType.Tab, + path, + }; + for (const entry of tab_command_values[session_id]?.commands ?? []) { + if (entry[SessionTabCommand.UpdateTabNavigation] === undefined) { + continue; + } + ses.url = (entry[SessionTabCommand.UpdateTabNavigation] as Record)["url"] ?? ":"; + ses.title = (entry[SessionTabCommand.UpdateTabNavigation] as Record)["title"] ?? ""; + ses.message = `Tab: ${ses.url} | Page Title: ${ses.title}`; + values.push(Object.assign({}, ses)); + } + } + + return values; +} + +interface Header { + signature: number; + version: number; + remaining: Uint8Array; +} + +/** + * Get initial structure of the Session file. Header is used to determine the version number + * @param bytes Session file bytes + * @returns `Header` information about the session file + */ +function getHeader(bytes: Uint8Array): Header | ApplicationError { + const sig = nomUnsignedFourBytes(bytes, Endian.Le); + if (sig instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get session sig: ${sig}`); + } + const version = nomUnsignedFourBytes(sig.remaining, Endian.Le); + if (version instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get session version: ${version}`); + } + + const head: Header = { + signature: sig.value, + version: version.value, + remaining: version.remaining, + }; + return head; +} + +/** + * Determine the command associated with Session. Each command stores different kinds of data. Some store URLs, timestamps, User agents, etc + * @param id Session ID number + * @returns Session Command value + */ +function getSessionCommand(id: number): SessionCommand { + switch (id) { + case 0: return SessionCommand.TabWindow; + case 1: return SessionCommand.WindowBounds; + case 2: return SessionCommand.TabIndexInWindow; + case 5: return SessionCommand.TabNavigationPathPrunedFromBack; + case 6: return SessionCommand.UpdateTabNavigation; + case 7: return SessionCommand.SelectedNavigationIndex; + case 8: return SessionCommand.SelectedTabInIndex; + case 9: return SessionCommand.WindowType; + case 10: return SessionCommand.WindowBounds2; + case 11: return SessionCommand.TabNavigationPathPrunedFromFront; + case 12: return SessionCommand.PinnedState; + case 13: return SessionCommand.ExtensionAppID; + case 14: return SessionCommand.WindowBounds3; + case 15: return SessionCommand.WindowAppName; + case 16: return SessionCommand.TabClosed; + case 17: return SessionCommand.WindowClosed; + case 18: return SessionCommand.TabUserAgentOverride; + case 19: return SessionCommand.SessionStorageAssociated; + case 20: return SessionCommand.ActiveWindow; + case 21: return SessionCommand.LastActiveTime; + case 22: return SessionCommand.WindowWorkspace; + case 23: return SessionCommand.WindowWorkspace2; + case 24: return SessionCommand.TabNavigationPathPruned; + case 25: return SessionCommand.TabGroup; + case 26: return SessionCommand.TabGroupMetadata; + case 27: return SessionCommand.TabGroupMetadata2; + case 28: return SessionCommand.TabGuid; + case 29: return SessionCommand.TabUserAgentOverride2; + case 30: return SessionCommand.TabData; + case 31: return SessionCommand.WindowUserTitle; + case 32: return SessionCommand.WindowVisibleOnAllWorkspaces; + case 33: return SessionCommand.AddTabExtraData; + case 34: return SessionCommand.AddWindowExtraData; + case 35: return SessionCommand.PlatformSessionId; + case 36: return SessionCommand.SplitTab; + case 37: return SessionCommand.SplitTabData; + // Chromium browsers can make there own custom commands + // https://github.com/cclgroupltd/ccl_chromium_reader/blob/552516720761397c4d482908b6b8b08130b313a1/ccl_chromium_reader/ccl_chromium_snss2.py#L95 + case 131: return SessionCommand.EdgeCommand; + case 132: return SessionCommand.EdgeCommand2; + case 44: return SessionCommand.EdgeCommand3; + case 50: return SessionCommand.EdgeCommand4; + case 255: return SessionCommand.CommandStorageBackend; + default: { + console.info(`Unknown session command ${id}`); + return SessionCommand.Unknown; + } + } +} + +/** + * Determine the command associated with Tab. Each command stores different kinds of data. Some store URLs, timestamps, User agents, etc + * @param id Tab ID number + * @returns Tab Command value + */ +function getTabCommand(id: number): SessionTabCommand { + switch (id) { + case 1: return SessionTabCommand.UpdateTabNavigation; + case 2: return SessionTabCommand.RestoredEntry; + case 3: return SessionTabCommand.WindowDeprecated; + case 4: return SessionTabCommand.SelectedNavigtionInTab; + case 5: return SessionTabCommand.PinnedState; + case 6: return SessionTabCommand.ExtensionAppID; + case 7: return SessionTabCommand.WindowAppName; + case 8: return SessionTabCommand.TabUserAgentOverride; + case 9: return SessionTabCommand.Window; + case 10: return SessionTabCommand.TabGroupData; + case 11: return SessionTabCommand.TabUserAgentOverride2; + case 12: return SessionTabCommand.WindowUserTitle; + case 13: return SessionTabCommand.CreateGroup; + case 14: return SessionTabCommand.AddTabExtraData; + case 255: return SessionTabCommand.CommandStorageBackend; + default: { + console.info(`Unknown tab command ${id}`); + return SessionTabCommand.Unknown; + } + } +} + +interface CommandValues { + commands: Record[]; + last_active: string; +} + +/** + * Function to parse the data associated with each SessionCommand. Many commands have similar strucutres + * @param command `SessionCommand` identifier + * @param bytes Bytes associated with the command + * @param command_values Values associated with the SessionCommand + */ +function parseSessionCommand(command: SessionCommand, bytes: Uint8Array, command_values: Record) { + switch (command) { + case SessionCommand.WindowType: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.WindowAppName: { + const window = parseWindowAppName(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.WindowUserTitle: { + const window = parseWindowAppName(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.WindowWorkspace2: { + const window = parseWindowAppName(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.WindowVisibleOnAllWorkspaces: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.PinnedState: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.TabIndexInWindow: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.TabGroup: { + const window = parseTabGroup(bytes); + if (!(window instanceof ApplicationError) && window.length !== 0 && window[0] !== undefined) { + if (command_values[window[0].session_id] === undefined) { + command_values[window[0].session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + + } else { + command_values[window[0].session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.TabWindow: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.SessionStorageAssociated: { + const window = parseSessionStorageAssociated(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.SelectedTabInIndex: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.LastActiveTime: { + const window = parseLastActive(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: window.last_active + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + const last = command_values[window.session_id]; + if (last !== undefined) { + last.last_active = window.last_active; + } + } + } + break; + } + case SessionCommand.SelectedNavigationIndex: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.UpdateTabNavigation: { + const window = parseUpdateTabNavigation(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.ActiveWindow: { + const window = parseSessionId(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window] === undefined) { + command_values[window] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.WindowBounds3: { + const window = parseWindowsBounds(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.CommandStorageBackend: { + // Contains nothing + break; + } case SessionCommand.AddWindowExtraData: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.TabUserAgentOverride2: { + const window = parseWindowAppName(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.TabClosed: { + const window = parseLastActive(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.EdgeCommand: { + const window = parseLastActive(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.EdgeCommand2: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.EdgeCommand3: { + const window = parseWindowAppName(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.EdgeCommand4: { + const window = parseWindowAppName(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + + break; + } + case SessionCommand.TabNavigationPathPruned: { + const window = parseWindowType(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionCommand.ExtensionAppID: { + const window = parseSessionStorageAssociated(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + default: { + console.info(`Unsupported session command: ${command}`); + } + } +} + +/** + * Function to parse the data associated with each TabCommand. Many commands have similar strucutres + * @param command `SessionTabCommand` identifier + * @param bytes Bytes associated with the command + * @param command_values Values associated with the SessionCommand + */ +function parseTabCommand(command: SessionTabCommand, bytes: Uint8Array, command_values: Record) { + switch (command) { + case SessionTabCommand.SelectedNavigtionInTab: { + const window = parseLastActive(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: window.last_active + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + const last = command_values[window.session_id]; + if (last !== undefined) { + last.last_active = window.last_active; + } + } + } + break; + } + case SessionTabCommand.UpdateTabNavigation: { + const window = parseUpdateTabNavigation(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionTabCommand.CommandStorageBackend: { + // Contains nothing + break; + } + case SessionTabCommand.Window: { + const window = parseWindow(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + case SessionTabCommand.TabUserAgentOverride2: { + // Contains array of user agents + break; + } + case SessionTabCommand.ExtensionAppID: { + const window = parseSessionStorageAssociated(bytes); + if (!(window instanceof ApplicationError)) { + if (command_values[window.session_id] === undefined) { + command_values[window.session_id] = { + commands: [({ + [command]: window, + })], + last_active: "" + }; + } else { + command_values[window.session_id]?.commands.push({ + [command]: window, + }); + } + } + break; + } + default: { + console.info(`Unsupported tab command: ${command}`); + } + } +} + +interface WindowType { + session_id: number; + index: number; +} + +/** + * Parse the WindowType info + * @param bytes Bytes associated with the WindowType. Should always be 8 bytes + * @returns `WindowType` object or `ApplicationError` + */ +function parseWindowType(bytes: Uint8Array): WindowType | ApplicationError { + const session = nomUnsignedFourBytes(bytes, Endian.Le); + if (session instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to window type session id: ${session}`); + } + + const index = nomUnsignedFourBytes(session.remaining, Endian.Le); + if (index instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to window type index: ${index}`); + } + + const window: WindowType = { + session_id: session.value, + index: index.value, + }; + + return window; +} + +/** + * Parse the WindowAppName info + * @param bytes Bytes associated with the WindowType. Should always be 12 bytes + * @returns `WindowType` object or `ApplicationError` + */ +function parseWindowAppName(bytes: Uint8Array): WindowType | ApplicationError { + const size = nomUnsignedFourBytes(bytes, Endian.Le); + if (size instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to window app name size: ${size}`); + } + // Size is 8 bytes? + // Same values as WindowType? + + return parseWindowType(size.remaining); +} + +/** + * Parse the TabGroup info + * @param bytes Bytes associated with the TabGroup + * @returns Array of `WindowType` or `Application Error` + */ +function parseTabGroup(bytes: Uint8Array): WindowType[] | ApplicationError { + const limit = 4; + let count = 0; + const group: WindowType[] = []; + let remaining = bytes; + while (count < limit) { + const session = nomUnsignedFourBytes(remaining, Endian.Le); + if (session instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to window type session id: ${session}`); + } + + const index = nomUnsignedFourBytes(session.remaining, Endian.Le); + if (index instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to window type index: ${index}`); + } + remaining = index.remaining; + + const window: WindowType = { + session_id: session.value, + index: index.value, + }; + group.push(window); + count += 1; + } + + return group; +} + +interface SessionStorageAssociated { + session_id: number; + value: string; +} + +/** + * Parse the session storage associated info. Usually contains a string + * @param bytes Bytes assocaited with SessionStorageAssociated + * @returns `SessionStorageAssociated` object or `ApplicationError` object + */ +function parseSessionStorageAssociated(bytes: Uint8Array): SessionStorageAssociated | ApplicationError { + let size = nomUnsignedFourBytes(bytes, Endian.Le); + if (size instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get session storage associated size: ${size}`); + } + const session_id = nomUnsignedFourBytes(size.remaining, Endian.Le); + if (session_id instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get session storage associated id: ${session_id}`); + } + + size = nomUnsignedFourBytes(session_id.remaining, Endian.Le); + if (size instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get session storage associated string size: ${size}`); + } + + const string_data = take(size.remaining, size.value); + if (string_data instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get session storage associated string: ${string_data}`); + } + + const value = extractUtf8String(string_data.nommed as Uint8Array); + const info: SessionStorageAssociated = { + session_id: session_id.value, + value, + }; + return info; +} + +interface LastActive { + session_id: number; + index: number; + last_active: string; +} + +/** + * Parse the last active timestamp + * @param bytes Bytes assocaited with LastActive + * @returns `LastActive` object or `ApplicationError` object + */ +function parseLastActive(bytes: Uint8Array): LastActive | ApplicationError { + const session = nomUnsignedFourBytes(bytes, Endian.Le); + if (session instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to last active session id: ${session}`); + } + + const index = nomUnsignedFourBytes(session.remaining, Endian.Le); + if (index instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get last active index: ${index}`); + } + + const timestamp = nomUnsignedEightBytes(index.remaining, Endian.Le); + if (timestamp instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get last active timestamp: ${timestamp}`); + } + + const last: LastActive = { + session_id: session.value, + index: index.value, + last_active: unixEpochToISO(webkitToUnixEpoch(Number(timestamp.value / 1000000n))), + }; + + return last; +} + +/** + * Get the session ID value + * @param bytes Bytes associated with the session ID + * @returns Session ID or `ApplicationError + */ +function parseSessionId(bytes: Uint8Array): number | ApplicationError { + const session = nomUnsignedFourBytes(bytes, Endian.Le); + if (session instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to last active session id: ${session}`); + } + + return session.value; +} + +interface TabNavigation { + session_id: number; + unknown: number; + unknown2: number; + unknown3: number; + unknown4: number; + unknown5: number; +} + +/** + * Parse the windows bound info. + * @param bytes Bytes associted with TabNavigation + * @returns `TabNavigation` object or `ApplicationError` + */ +function parseWindowsBounds(bytes: Uint8Array): TabNavigation | ApplicationError { + const session = nomUnsignedFourBytes(bytes, Endian.Le); + if (session instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get windows bound session id: ${session}`); + } + + const unknown = nomUnsignedFourBytes(session.remaining, Endian.Le); + if (unknown instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get windows bound unknown: ${unknown}`); + } + + const unknown2 = nomUnsignedFourBytes(unknown.remaining, Endian.Le); + if (unknown2 instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get windows bound unknown2: ${unknown2}`); + } + + const unknown3 = nomUnsignedFourBytes(unknown2.remaining, Endian.Le); + if (unknown3 instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get windows bound unknown3: ${unknown3}`); + } + + const unknown4 = nomUnsignedFourBytes(unknown3.remaining, Endian.Le); + if (unknown4 instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get windows bound unknown4: ${unknown4}`); + } + + const unknown5 = nomUnsignedFourBytes(unknown4.remaining, Endian.Le); + if (unknown5 instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get windows bound unknown5: ${unknown5}`); + } + + const tab: TabNavigation = { + session_id: session.value, + unknown: unknown.value, + unknown2: unknown2.value, + unknown3: unknown3.value, + unknown4: unknown4.value, + unknown5: unknown5.value + }; + + return tab; +} + +interface TabInfo { + session_id: number; + index: number; + url: string; + title: string; +} + +/** + * Parse the Tab Navigation info. Usually contains page info like URL and page title and alot more + * @param bytes Bytes associated with TabInfo + * @returns `TabInfo` object or `ApplicationError` + */ +function parseUpdateTabNavigation(bytes: Uint8Array): TabInfo | ApplicationError { + const size = nomUnsignedFourBytes(bytes, Endian.Le); + if (size instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation size: ${size}`); + } + + const session_id = nomUnsignedFourBytes(size.remaining, Endian.Le); + if (session_id instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation session id: ${session_id}`); + } + const index = nomUnsignedFourBytes(session_id.remaining, Endian.Le); + if (index instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation index: ${index}`); + } + + // Size does NOT include end of string character + const url_size = nomUnsignedFourBytes(index.remaining, Endian.Le); + if (url_size instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation url size: ${url_size}`); + } + + // Should align to 4 bytes? + let adjust = url_size.value % 4; + if (adjust !== 0) { + adjust = 4 - adjust; + } + + const url_data = take(url_size.remaining, url_size.value + adjust); + if (url_data instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation url: ${url_data}`); + } + + const url = extractUtf8String(url_data.nommed as Uint8Array); + + const title_size = nomUnsignedFourBytes(url_data.remaining as Uint8Array, Endian.Le); + if (title_size instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation url title size: ${title_size}`); + } + + const adjust_size = 2; + // Align 4 bytes + adjust = (title_size.value * adjust_size) % 4; + if (adjust !== 0) { + adjust = 4 - adjust; + } + + let title = ""; + let remaining = title_size.remaining; + if (title_size.value !== 0) { + // Title data is UTF16 o.O and does NOT include end of string character + const title_data = take(title_size.remaining, (title_size.value + adjust)); + if (title_data instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation url title: ${title_data}`); + } + remaining = title_data.remaining as Uint8Array; + + const title_string = extractUtf16String(title_data.nommed as Uint8Array); + title = title_string; + } + + // A lot more left to parse! + // https://digitalinvestigation.wordpress.com/2012/09/03/chrome-session-and-tabs-files-and-the-puzzle-of-the-pickle/ + + const state_size = nomUnsignedFourBytes(remaining, Endian.Le); + if (state_size instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation url state size: ${state_size}`); + } + // A very complex format. Currently not parsing. *Might* contain info like URL referrer, User agent, additional timestamps + // const state_data = take(state_size.remaining, state_size.value); + // if (state_data instanceof NomError) { + // return new ApplicationError(`CHROMIUM`, `Failed to get update tab navigation url state data: ${state_data}`); + // } + + const info: TabInfo = { + session_id: session_id.value, + index: index.value, + url, + title, + }; + + return info; +} + +interface Window { + session_id: number; + index: number; + unknown: number; + window_timestamp: string; +} + +/** + * Parse the Window session command + * @param bytes Bytes associated with the Window command + * @returns `Window` object or `ApplicationError` + */ +function parseWindow(bytes: Uint8Array): Window | ApplicationError { + const session = nomUnsignedFourBytes(bytes, Endian.Le); + if (session instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get window session id: ${session}`); + } + + const index = nomUnsignedFourBytes(session.remaining, Endian.Le); + if (index instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get window index: ${index}`); + } + + const unknown = nomUnsignedFourBytes(index.remaining, Endian.Le); + if (unknown instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get window unknown: ${unknown}`); + } + + const timestamp = nomUnsignedEightBytes(unknown.remaining, Endian.Le); + if (timestamp instanceof NomError) { + return new ApplicationError(`CHROMIUM`, `Failed to get window timestamp: ${timestamp}`); + } + + // A lot more left to parse! + // https://digitalinvestigation.wordpress.com/2012/09/03/chrome-session-and-tabs-files-and-the-puzzle-of-the-pickle/ + + + const win: Window = { + session_id: session.value, + index: index.value, + unknown: unknown.value, + window_timestamp: unixEpochToISO(webkitToUnixEpoch(Number(timestamp.value / 1000000n))), + }; + + return win; +} + +/** + * Function to test the Chromium Sessions parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the Chromium Sessions parsing + */ +export function testChromiumSessions(): void { + const path: ChromiumProfiles = { + full_path: "../../test_data/edge", + version: "141", + browser: BrowserType.EDGE + }; + + const sess = chromiumSessions([path], PlatformType.Darwin); + if (sess.length !== 115) { + throw `Got length ${sess.length} expected 115.......chromiumSessions āŒ`; + } + + if (sess[12]?.message !== "Session: https://www.washingtonpost.com/politics/2025/11/02/nuclear-testing-trump-energy-secretary/ | Page Title: Trump energy secretary says no nuclear b") { + throw `Got message "${sess[12]?.message}" expected "Session: https://www.washingtonpost.com/politics/2025/11/02/nuclear-testing-trump-energy-secretary/ | Page Title: Trump energy secretary says no nuclear b".......chromiumSessions āŒ`; + } + + + if (sess[0]?.message != "Session: edge://newtab/ | Page Title: New T") { + throw `Got message ${sess[0]?.message} expected "Session: edge://newtab/ | Page Title: New T".......chromiumSessions āŒ`; + } + + console.info(` Function chromiumSessions āœ…`); + + const sess_file = "../../test_data/edge/v141/Sessions/Session_13406596486318013"; + const results = parseSession(sess_file, SessionType.Session, path); + if (results instanceof ApplicationError) { + throw results.message; + } + + if (results.length !== 58) { + throw `Got length ${results.length} expected 58.......parseSession āŒ`; + } + + if (results[7]?.message != "Session: https://www.washingtonpost.com/ | Page Title: The Washington Post - Breaking news and latest headlines") { + throw `Got message ${results[7]?.message} expected "Session: https://www.washingtonpost.com/ | Page Title: The Washington Post - Breaking news and latest headlines".......parseSession āŒ`; + } + + console.info(` Function parseSession āœ…`); + + const header = getHeader(new Uint8Array([0, 0, 0, 0, 1, 0, 0, 0])); + if (header instanceof ApplicationError) { + throw header.message; + } + + if (header.version !== 1) { + throw `Got length ${header.version} expected 1.......getHeader āŒ`; + } + + console.info(` Function getHeader āœ…`); + + const test = [0, 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 131, 132, 44, 50, 255]; + for (const entry of test) { + const value = getSessionCommand(entry); + if (value === SessionCommand.Unknown) { + throw `Got Session command Unknown for ${entry}.......getSessionCommand āŒ` + } + } + + console.info(` Function getSessionCommand āœ…`); + + for (const entry of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 255]) { + const value = getTabCommand(entry); + if (value === SessionTabCommand.Unknown) { + throw `Got Tab command Unknown for ${entry}.......getTabCommand āŒ` + } + } + + console.info(` Function getTabCommand āœ…`); + + const comm: Record = {}; + parseSessionCommand(SessionCommand.TabWindow, new Uint8Array([1, 0, 0, 0, 2, 0, 0, 0]), comm); + if (!JSON.stringify(comm).includes("TabWindow")) { + throw `Got Session command ${JSON.stringify(comm)} wanted "TabWindow".......parseSessionCommand āŒ` + } + + console.info(` Function parseSessionCommand āœ…`); + + const tab: Record = {}; + parseTabCommand(SessionTabCommand.SelectedNavigtionInTab, new Uint8Array([1, 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0]), tab); + if (!JSON.stringify(tab).includes("SelectedNavigationInTab")) { + throw `Got Session command ${JSON.stringify(tab)} wanted "SelectedNavigationInTab".......parseTabCommand āŒ` + } + + console.info(` Function parseTabCommand āœ…`); + + let info = parseWindowType(new Uint8Array([1, 0, 0, 0, 2, 0, 0, 0])); + if (info instanceof ApplicationError) { + throw info.message; + } + + if (info.index !== 2) { + throw `Got index ${info.index} expected 2.......parseWindowType āŒ`; + } + + console.info(` Function parseWindowType āœ…`); + + info = parseWindowAppName(new Uint8Array([8, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0])); + if (info instanceof ApplicationError) { + throw info.message; + } + + if (info.index !== 2) { + throw `Got index ${info.index} expected 2.......parseWindowAppName āŒ`; + } + + console.info(` Function parseWindowAppName āœ…`); + + const tab_group = parseTabGroup(new Uint8Array([8, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0])); + if (tab_group instanceof ApplicationError) { + throw tab_group.message; + } + + if (tab_group.length !== 4) { + throw `Got index ${tab_group.length} expected 4.......parseTabGroup āŒ`; + } + + console.info(` Function parseTabGroup āœ…`); + + const url_bytes = parseSessionStorageAssociated(new Uint8Array([44, 0, 0, 0, 208, 120, 213, 109, 36, 0, 0, 0, 97, 102, 100, 99, 50, 50, 54, 100, 95, 99, 55, 57, 51, 95, 52, 97, 51, 52, 95, 97, 49, 51, 50, 95, 50, 100, 102, 100, 99, 99, 50, 53, 56, 97, 57, 50])); + if (url_bytes instanceof ApplicationError) { + throw url_bytes.message; + } + + if (url_bytes.value !== "afdc226d_c793_4a34_a132_2dfdcc258a92") { + throw `Got value ${url_bytes.value} expected "afdc226d_c793_4a34_a132_2dfdcc258a92".......parseSessionStorageAssociated āŒ`; + } + console.info(` Function parseSessionStorageAssociated āœ…`); + + const last_active = parseLastActive(new Uint8Array([81, 121, 213, 109, 0, 0, 0, 0, 59, 250, 123, 137, 58, 161, 47, 0])); + if (last_active instanceof ApplicationError) { + throw last_active.message; + } + + if (last_active.last_active !== "2025-11-02T22:38:12.000Z") { + throw `Got time ${last_active.last_active} expected "2025-11-02T22:38:12.000Z".......parseLastActive āŒ`; + } + console.info(` Function parseLastActive āœ…`); + + const session_id = parseSessionId(new Uint8Array([1, 0, 0, 0])); + if (session_id instanceof ApplicationError) { + throw session_id.message; + } + + if (session_id !== 1) { + throw `Got ID ${session_id} expected "1".......parseSessionId āŒ`; + } + console.info(` Function parseSessionId āœ…`); + + const navigate = parseWindowsBounds(new Uint8Array([11, 121, 213, 109, 22, 0, 0, 0, 22, 0, 0, 0, 0, 15, 0, 0, 56, 4, 0, 0, 1, 0, 0, 0])); + if (navigate instanceof ApplicationError) { + throw navigate.message; + } + + if (navigate.session_id !== 1842706699) { + throw `Got ID ${navigate.session_id} expected "1842706699".......parseWindowsBounds āŒ`; + } + console.info(` Function parseWindowsBounds āœ…`); + + const bytes = readFile("../../test_data/edge/v141/raw/tab_url.raw"); + if (bytes instanceof FileError) { + throw bytes.message; + } + + const tab_url = parseUpdateTabNavigation(bytes); + if (tab_url instanceof ApplicationError) { + throw tab_url.message; + } + + if (tab_url.url != "edge://newtab/") { + throw `Got URL ${tab_url.url} expected "edge://newtab/".......parseUpdateTabNavigation āŒ`; + } + console.info(` Function parseUpdateTabNavigation āœ…`); + + const win = parseWindow(new Uint8Array([11, 121, 213, 109, 22, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])); + if (win instanceof ApplicationError) { + throw win.message; + } + + if (win.session_id !== 1842706699) { + throw `Got ID ${win.session_id} expected "1842706699".......parseWindow āŒ`; + } + console.info(` Function parseWindow āœ…`); +} \ No newline at end of file diff --git a/src/applications/chromium/sqlite.ts b/src/applications/chromium/sqlite.ts index 0d0202f5..5e6f7888 100644 --- a/src/applications/chromium/sqlite.ts +++ b/src/applications/chromium/sqlite.ts @@ -1,4 +1,4 @@ -import { ChromiumProfiles, ChromiumHistory, ChromiumDownloads, ChromiumCookies, ChromiumAutofill, ChromiumLogins, ChromiumDips, ChromiumCookieType } from "../../../types/applications/chromium"; +import { ChromiumProfiles, ChromiumHistory, ChromiumDownloads, ChromiumCookies, ChromiumAutofill, ChromiumLogins, ChromiumDips, ChromiumCookieType, BrowserType, ChromiumFavicons, ChromiumShortcuts, ShortcutType } from "../../../types/applications/chromium"; import { FileError } from "../../filesystem/errors"; import { glob } from "../../filesystem/files"; import { PlatformType } from "../../system/systeminfo"; @@ -46,25 +46,31 @@ export function chromiumHistory(paths: ChromiumProfiles[], platform: PlatformTyp for (const entry of results) { const adjust = 1000000; const webkit = webkitToUnixEpoch( - (entry[ "last_visit_time" ] as number ?? 0) / adjust, + (entry["last_visit_time"] as number ?? 0) / adjust, ); const history_row: ChromiumHistory = { - id: entry[ "id" ] as number ?? 0, - url: entry[ "url" ] as string ?? "", - title: entry[ "title" ] as string ?? "", - visit_count: entry[ "visit_count" ] as number ?? 0, - typed_count: entry[ "typed_count" ] as number ?? 0, + id: entry["id"] as number ?? 0, + url: entry["url"] as string ?? "", + title: entry["title"] as string ?? "", + visit_count: entry["visit_count"] as number ?? 0, + typed_count: entry["typed_count"] as number ?? 0, last_visit_time: unixEpochToISO(webkit), - hidden: entry[ "hidden" ] as number ?? 0, - visits_id: entry[ "visits_id" ] as number ?? 0, - from_visit: entry[ "from_visit" ] as number ?? 0, - transition: entry[ "transition" ] as number ?? 0, - segment_id: entry[ "segment_id" ] as number ?? 0, - visit_duration: entry[ "visit_duration" ] as number ?? 0, - opener_visit: entry[ "opener_visit" ] as number ?? 0, + hidden: entry["hidden"] as number ?? 0, + visits_id: entry["visits_id"] as number ?? 0, + from_visit: entry["from_visit"] as number ?? 0, + transition: entry["transition"] as number ?? 0, + segment_id: entry["segment_id"] as number ?? 0, + visit_duration: entry["visit_duration"] as number ?? 0, + opener_visit: entry["opener_visit"] as number ?? 0, unfold: undefined, db_path: entry_path.full_path, version: path.version, + message: entry["url"] as string ?? "", + datetime: unixEpochToISO(webkit), + timestamp_desc: "URL Visited", + artifact: "URL History", + data_type: `applications:${path.browser.toLowerCase()}:history:entry`, + browser: path.browser, }; if (unfold && typeof client !== 'undefined') { @@ -89,6 +95,7 @@ export function chromiumHistory(paths: ChromiumProfiles[], platform: PlatformTyp * @param paths Array of `ChromiumProfiles` * @param platform OS `PlatformType` * @param query SQL query to run + * @param browser Chromium based browser type * @returns Array of `ChromiumDownloads` */ export function chromiumDownloads(paths: ChromiumProfiles[], platform: PlatformType, query: string): ChromiumDownloads[] { @@ -115,52 +122,56 @@ export function chromiumDownloads(paths: ChromiumProfiles[], platform: PlatformT for (const entry of results) { const adjust = 1000000; const start = webkitToUnixEpoch( - (entry[ "start_time" ] as number ?? 0) / adjust, + (entry["start_time"] as number ?? 0) / adjust, ); const end = webkitToUnixEpoch( - (entry[ "end_time" ] as number ?? 0) / adjust, + (entry["end_time"] as number ?? 0) / adjust, ); const access = webkitToUnixEpoch( - (entry[ "last_access_time" ] as number ?? 0) / adjust, + (entry["last_access_time"] as number ?? 0) / adjust, ); const download_row: ChromiumDownloads = { - id: entry[ "id" ] as number ?? 0, - guid: entry[ "guid" ] as string ?? "", - current_path: entry[ "current_path" ] as string ?? "", - target_path: entry[ "target_path" ] as string ?? "", + id: entry["id"] as number ?? 0, + guid: entry["guid"] as string ?? "", + current_path: entry["current_path"] as string ?? "", + target_path: entry["target_path"] as string ?? "", start_time: unixEpochToISO(start), - received_bytes: entry[ "received_bytes" ] as number ?? 0, - total_bytes: entry[ "total_bytes" ] as number ?? 0, - state: entry[ "state" ] as number ?? 0, - danger_type: entry[ "danger_type" ] as number ?? 0, - interrupt_reason: entry[ "interrupt_reason" ] as number ?? 0, - hash: entry[ "hash" ] as number[] ?? [], + received_bytes: entry["received_bytes"] as number ?? 0, + total_bytes: entry["total_bytes"] as number ?? 0, + state: entry["state"] as number ?? 0, + danger_type: entry["danger_type"] as number ?? 0, + interrupt_reason: entry["interrupt_reason"] as number ?? 0, + hash: entry["hash"] as number[] ?? [], end_time: unixEpochToISO(end), - opened: entry[ "opened" ] as number ?? 0, + opened: entry["opened"] as number ?? 0, last_access_time: unixEpochToISO(access), - transient: entry[ "transient" ] as number ?? 0, - referrer: entry[ "referrer" ] as string ?? "", - site_url: entry[ "site_url" ] as string ?? "", - tab_url: entry[ "tab_url" ] as string ?? "", - tab_referrer_url: entry[ "tab_referrer_url" ] as string ?? "", - http_method: entry[ "http_method" ] as string ?? "", - by_ext_id: entry[ "by_ext_id" ] as string ?? "", - by_ext_name: entry[ "by_ext_name" ] as string ?? "", - etag: entry[ "etag" ] as string ?? "", - last_modified: entry[ "last_modified" ] as string ?? "", - mime_type: entry[ "mime_type" ] as string ?? "", - original_mime_type: entry[ "original_mime_type" ] as string ?? "", - downloads_url_chain_id: entry[ "downloads_url_chain_id" ] as number ?? 0, - chain_index: entry[ "chain_index" ] as number ?? 0, - url: entry[ "url" ] as string ?? "", + transient: entry["transient"] as number ?? 0, + referrer: entry["referrer"] as string ?? "", + site_url: entry["site_url"] as string ?? "", + tab_url: entry["tab_url"] as string ?? "", + tab_referrer_url: entry["tab_referrer_url"] as string ?? "", + http_method: entry["http_method"] as string ?? "", + by_ext_id: entry["by_ext_id"] as string ?? "", + by_ext_name: entry["by_ext_name"] as string ?? "", + etag: entry["etag"] as string ?? "", + last_modified: entry["last_modified"] as string ?? "", + mime_type: entry["mime_type"] as string ?? "", + original_mime_type: entry["original_mime_type"] as string ?? "", + downloads_url_chain_id: entry["downloads_url_chain_id"] as number ?? 0, + chain_index: entry["chain_index"] as number ?? 0, + url: entry["url"] as string ?? "", db_path: entry_path.full_path, version: path.version, + message: `${entry["url"] as string ?? ""} | ${entry["target_path"] as string ?? ""}`, + datetime: unixEpochToISO(start), + timestamp_desc: "File Download Start", + artifact: "File Download", + data_type: `applications:${path.browser.toLowerCase()}:downloads:entry`, + browser: path.browser, }; hits.push(download_row); } } - - } return hits; @@ -176,10 +187,10 @@ export function chromiumDownloads(paths: ChromiumProfiles[], platform: PlatformT export function chromiumCookies(paths: ChromiumProfiles[], platform: PlatformType, query: string): ChromiumCookies[] { const hits: ChromiumCookies[] = []; for (const path of paths) { - let full_paths = [ `${path.full_path}/*/Cookies`, `${path.full_path}/*/Network/Cookies` ]; + let full_paths = [`${path.full_path}/*/Cookies`, `${path.full_path}/*/Network/Cookies`]; if (platform === PlatformType.Windows) { - full_paths = [ `${path.full_path}\\*\\Network\\Cookies`, `${path.full_path}\\*\\Cookies` ]; + full_paths = [`${path.full_path}\\*\\Network\\Cookies`, `${path.full_path}\\*\\Cookies`]; } @@ -200,34 +211,42 @@ export function chromiumCookies(paths: ChromiumProfiles[], platform: PlatformTyp for (const entry of results) { const cookie_entry: ChromiumCookies = { creation: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "creation_utc" ] as bigint) / adjust_time), + Number(BigInt(entry["creation_utc"] as bigint) / adjust_time) )), - host_key: entry[ "host_key" ] as string, - top_frame_site_key: entry[ "top_frame_site_key" ] as string, - name: entry[ "name" ] as string, - value: entry[ "value" ] as string, - encrypted_value: entry[ "encrypted_value" ] as string, - path: entry[ "path" ] as string, + host_key: entry["host_key"] as string, + top_frame_site_key: entry["top_frame_site_key"] as string | undefined ?? "", + name: entry["name"] as string | undefined ?? "", + value: entry["value"] as string | undefined ?? "", + encrypted_value: entry["encrypted_value"] as string, + path: entry["path"] as string | undefined ?? "", expires: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "expires_utc" ] as bigint) / adjust_time), + Number(BigInt(entry["expires_utc"] as bigint) / adjust_time) )), - is_secure: !!(entry[ "is_secure" ] as number), - is_httponly: !!(entry[ "is_httponly" ] as number), + is_secure: !!(entry["is_secure"] as number), + is_httponly: !!(entry["is_httponly"] as number), last_access: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "last_access_utc" ] as bigint) / adjust_time), + Number(BigInt(entry["last_access_utc"] as bigint) / adjust_time) )), - has_expires: !!(entry[ "has_expires" ] as number), - is_persistent: !!(entry[ "is_persistent" ] as number), - priority: entry[ "priority" ] as number, - samesite: entry[ "samesite" ] as number, - source_scheme: entry[ "source_scheme" ] as number, - source_port: entry[ "source_port" ] as number, - is_same_party: entry[ "is_same_party" ] as number, + has_expires: !!(entry["has_expires"] as number), + is_persistent: !!(entry["is_persistent"] as number), + priority: entry["priority"] as number, + samesite: entry["samesite"] as number, + source_scheme: entry["source_scheme"] as number, + source_port: entry["source_port"] as number, + is_same_party: entry["is_same_party"] as number | undefined ?? 0, last_update: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "last_update_utc" ] as bigint) / adjust_time), + Number(BigInt(entry["last_update_utc"] as bigint) / adjust_time) )), db_path: entry_path.full_path, version: path.version, + message: `Cookie name: ${entry["name"] as string} | value: ${entry["value"] as string | undefined ?? ""}`, + datetime: unixEpochToISO(webkitToUnixEpoch( + Number(BigInt(entry["expires_utc"] as bigint) / adjust_time) + )), + timestamp_desc: "Cookie Expires", + artifact: "Website Cookie", + data_type: `applications:${path.browser.toLowerCase()}:cookies:entry`, + browser: path.browser, }; hits.push(cookie_entry); } @@ -238,6 +257,182 @@ export function chromiumCookies(paths: ChromiumProfiles[], platform: PlatformTyp return hits; } +/** + * Get Favicons for websites + * @param paths Array of `ChromiumProfiles` + * @param platform OS `PlatformType` + * @param query SQL query to run + * @returns Array of `ChromiumFavicons` + */ +export function chromiumFavicons(paths: ChromiumProfiles[], platform: PlatformType, query: string): ChromiumFavicons[] { + const hits: ChromiumFavicons[] = []; + for (const path of paths) { + let full_path = `${path.full_path}/*/Favicons`; + + + if (platform === PlatformType.Windows) { + full_path = `${path.full_path}\\*\\Favicons`; + } + const glob_paths = glob(full_path); + if (glob_paths instanceof FileError) { + console.warn(`Failed to glob ${full_path}: ${glob_paths}`); + continue; + } + for (const entry_path of glob_paths) { + const results = querySqlite(entry_path.full_path, query); + if (results instanceof ApplicationError) { + console.warn(`Failed to query ${entry_path.full_path}: ${results}`); + continue; + } + // Loop through favicon rows + for (const entry of results) { + const adjust = 1000000; + const last_update = webkitToUnixEpoch( + (entry["last_updated"] as number ?? 0) / adjust, + ); + let url = "Favicon URL Null"; + if (typeof entry["url"] === 'string') { + url = entry["url"]; + } + + const download_row: ChromiumFavicons = { + db_path: entry_path.full_path, + version: path.version, + message: `Favicon for ${url}`, + datetime: unixEpochToISO(last_update), + data_type: `applications:${path.browser.toLowerCase()}:favicons:entry`, + browser: path.browser, + last_update: unixEpochToISO(last_update), + url, + timestamp_desc: "Favicon Updated", + artifact: "Website Favicon" + }; + hits.push(download_row); + } + } + } + + return hits; +} + +/** + * Get Shortcuts for websites + * @param paths Array of `ChromiumProfiles` + * @param platform OS `PlatformType` + * @param query SQL query to run + * @returns Array of `ChromiumShortcuts` + */ +export function chromiumShortcuts(paths: ChromiumProfiles[], platform: PlatformType, query: string): ChromiumShortcuts[] { + const hits: ChromiumShortcuts[] = []; + for (const path of paths) { + let full_path = `${path.full_path}/*/Shortcuts`; + + + if (platform === PlatformType.Windows) { + full_path = `${path.full_path}\\*\\Shortcuts`; + } + const glob_paths = glob(full_path); + if (glob_paths instanceof FileError) { + console.warn(`Failed to glob ${full_path}: ${glob_paths}`); + continue; + } + for (const entry_path of glob_paths) { + const results = querySqlite(entry_path.full_path, query); + if (results instanceof ApplicationError) { + console.warn(`Failed to query ${entry_path.full_path}: ${results}`); + continue; + } + // Loop through favicon rows + for (const entry of results) { + const adjust = 1000000; + const last_update = webkitToUnixEpoch( + (entry["last_access_time"] as number ?? 0) / adjust, + ); + let short_type = -1; + if (typeof entry["type"] === 'number') { + short_type = entry["type"]; + } + let url = "Shortcut URL Null"; + if (typeof entry["url"] === 'string') { + url = entry["url"]; + } + const download_row: ChromiumShortcuts = { + db_path: entry_path.full_path, + version: path.version, + message: `Shortcut for ${url}`, + datetime: unixEpochToISO(last_update), + data_type: `applications:${path.browser.toLowerCase()}:shortcuts:entry`, + browser: path.browser, + last_update: unixEpochToISO(last_update), + url, + text: entry["text"] as string | undefined ?? "", + contents: entry["contents"] as string | undefined ?? "", + fill_into_edit: entry["fill_into_edit"] as string | undefined ?? "", + shortcut_id: entry["id"] as string | undefined ?? "", + keyword: entry["keyword"] as string | undefined ?? "", + shortcut_type: getShortcut(short_type), + description: entry["description"] as string | undefined ?? "", + timestamp_desc: "Shortcut Last Access", + artifact: "Website Shortcut" + }; + hits.push(download_row); + } + } + } + + return hits; +} + +/** + * Get ShortcutType for websites + * @param value enum value of the shortcut + */ +function getShortcut(value: number): ShortcutType { + switch (value) { + case 0: return ShortcutType.Typed; + case 1: return ShortcutType.History; + case 2: return ShortcutType.HistoryTitle; + case 3: return ShortcutType.HistoryBody; + case 4: return ShortcutType.HistoryKeyword; + case 5: return ShortcutType.Suggest; + case 6: return ShortcutType.SearchUrl; + case 7: return ShortcutType.SearchHistory; + case 8: return ShortcutType.SearchSuggest; + case 9: return ShortcutType.SearchSuggestEntity + case 10: return ShortcutType.SearchTail; + case 11: return ShortcutType.SearchPersonalized; + case 12: return ShortcutType.SearchProfile; + case 13: return ShortcutType.SearchEngine; + case 14: return ShortcutType.ExtensionApp; + case 15: return ShortcutType.UserContact; + case 16: return ShortcutType.Bookmark; + case 17: return ShortcutType.SuggestPersonalized; + case 18: return ShortcutType.Calculator; + case 19: return ShortcutType.Clipboard; + case 20: return ShortcutType.Voice; + case 21: return ShortcutType.Physical; + case 22: return ShortcutType.PhysicalOverflow; + case 23: return ShortcutType.Tab; + case 24: return ShortcutType.Document; + case 25: return ShortcutType.Pedal; + case 26: return ShortcutType.ClipboardText; + case 27: return ShortcutType.ClipboardImage; + case 28: return ShortcutType.TitleSuggest; + case 29: return ShortcutType.TitleNavSuggest; + case 30: return ShortcutType.OpenTab; + case 31: return ShortcutType.HistoryCluster; + case 32: return ShortcutType.Null; + case 33: return ShortcutType.Starter; + case 34: return ShortcutType.MostVisited; + case 35: return ShortcutType.Repeatable; + case 36: return ShortcutType.HistoryEmbed; + case 37: return ShortcutType.Enterprise; + case 38: return ShortcutType.HistoryEmbedAnswers; + case 39: return ShortcutType.TabGroup; + default: return ShortcutType.Unkonwn; + } +} + /** * Determine Cookie Type. From `https://chromium.googlesource.com/chromium/src/net/+/refs/heads/main/cookies/cookie_constants.h#378` * @param source Cookie source_type column @@ -286,13 +481,19 @@ export function chromiumAutofill(paths: ChromiumProfiles[], platform: PlatformTy for (const entry of results) { const fill_entry: ChromiumAutofill = { db_path: entry_path.full_path, - date_created: unixEpochToISO(entry[ "date_created" ] as number), - date_last_used: unixEpochToISO(entry[ "date_last_used" ] as number), - count: entry[ "count" ] as number, - name: entry[ "name" ] as string | undefined, - value: entry[ "value" ] as string | undefined, - value_lower: entry[ "value_lower" ] as string | undefined, + date_created: unixEpochToISO(entry["date_created"] as number), + date_last_used: unixEpochToISO(entry["date_last_used"] as number), + count: entry["count"] as number, + name: entry["name"] as string ?? "", + value: entry["value"] as string ?? "", + value_lower: entry["value_lower"] as string ?? "", version: path.version, + message: `Autofill name: ${entry["name"] as string ?? ""} | value: ${entry["value"] as string ?? ""}`, + datetime: unixEpochToISO(entry["date_created"] as number), + timestamp_desc: "Autofill Created", + artifact: "Website Autofill", + data_type: `applications:${path.browser.toLowerCase()}:autofill:entry`, + browser: path.browser, }; hits.push(fill_entry); } @@ -333,56 +534,59 @@ export function chromiumLogins(paths: ChromiumProfiles[], platform: PlatformType // Loop through logins rows for (const entry of data) { const login_entry: ChromiumLogins = { - origin_url: entry[ "origin_url" ] as string, - signon_realm: entry[ "signon_realm" ] as string, + origin_url: entry["origin_url"] as string, + signon_realm: entry["signon_realm"] as string, date_created: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "date_created" ] as bigint) / adjust_time), + Number(BigInt(entry["date_created"] as bigint) / adjust_time) )), - blacklisted_by_user: entry[ "blacklisted_by_user" ] as number, - scheme: entry[ "scheme" ] as number, - id: entry[ "id" ] as number, + blacklisted_by_user: entry["blacklisted_by_user"] as number, + scheme: entry["scheme"] as number, + id: entry["id"] as number, date_last_used: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "date_last_used" ] as bigint) / adjust_time), + Number(BigInt(entry["date_last_used"] as bigint) / adjust_time) )), date_password_modified: unixEpochToISO(webkitToUnixEpoch( - Number(BigInt(entry[ "date_password_modified" ] as bigint) / adjust_time), + Number(BigInt(entry["date_password_modified"] as bigint) / adjust_time) )), - sharing_notification_display: entry[ - "sharing_notification_display" - ] as number, + sharing_notification_display: entry["sharing_notification_display"] as number, db_path: entry_path.full_path, - action_url: entry[ "action_url" ] as string | undefined, - username_element: entry[ "username_element" ] as string | undefined, - username_value: entry[ "username_value" ] as string | undefined, - times_used: entry[ "times_used" ] as number | undefined, - icon_url: entry[ "icon_url" ] as string | undefined, - possible_username_pairs: entry[ "possible_username_pairs" ] as - | string - | undefined, - federation_url: entry[ "federation_url" ] as string | undefined, - generation_upload_status: entry[ "generation_upload_status" ] as - | number - | undefined, - sender_profile_image_url: entry[ "sender_profile_image_url" ] as - | string - | undefined, - password_element: entry[ "password_element" ] as string | undefined, - password_type: entry[ "password_type" ] as number | undefined, - password_value: entry[ "password_value" ] as string | undefined, + action_url: entry["action_url"] as string | undefined, + username_element: entry["username_element"] as string | undefined, + username_value: entry["username_value"] as string | undefined, + times_used: entry["times_used"] as number | undefined, + icon_url: entry["icon_url"] as string | undefined, + possible_username_pairs: entry["possible_username_pairs"] as string | + undefined, + federation_url: entry["federation_url"] as string | undefined, + generation_upload_status: entry["generation_upload_status"] as number | + undefined, + sender_profile_image_url: entry["sender_profile_image_url"] as string | + undefined, + password_element: entry["password_element"] as string | undefined, + password_type: entry["password_type"] as number | undefined, + password_value: entry["password_value"] as string | undefined, date_received: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "date_received" ] === "undefined" + typeof entry["date_received"] === "undefined" ? 0 - : Number(BigInt(entry[ "date_received" ] as bigint) / adjust_time), + : Number(BigInt(entry["date_received"] as bigint) / adjust_time) )), - sender_email: entry[ "sender_email" ] as string | undefined, - sender_name: entry[ "sender_name" ] as string | undefined, - skip_zero_click: entry[ "skip_zero_click" ] as number | undefined, - submit_element: entry[ "submit_element" ] as string | undefined, - display_name: entry[ "display_name" ] as string | undefined, - form_data: entry[ "form_data" ] as string | undefined, - moving_blocked_for: entry[ "moving_blocked_for" ] as string | undefined, - keychain_identifier: entry[ "keychain_identifier" ] as string | undefined, + sender_email: entry["sender_email"] as string | undefined, + sender_name: entry["sender_name"] as string | undefined, + skip_zero_click: entry["skip_zero_click"] as number | undefined, + submit_element: entry["submit_element"] as string | undefined, + display_name: entry["display_name"] as string | undefined, + form_data: entry["form_data"] as string | undefined, + moving_blocked_for: entry["moving_blocked_for"] as string | undefined, + keychain_identifier: entry["keychain_identifier"] as string | undefined, version: path.version, + message: entry["origin_url"] as string, + datetime: unixEpochToISO(webkitToUnixEpoch( + Number(BigInt(entry["date_last_used"] as bigint) / adjust_time) + )), + timestamp_desc: "Last Login", + artifact: "Website Login", + data_type: `applications:${path.browser.toLowerCase()}:login:entry`, + browser: path.browser, }; hits.push(login_entry); } @@ -424,86 +628,243 @@ export function chromiumDips(paths: ChromiumProfiles[], platform: PlatformType, // Loop through logins rows for (const entry of data) { const dips_entry: ChromiumDips = { - site: entry[ "site" ] as string, + site: entry["site"] as string, path: entry_path.full_path, first_bounce: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "first_bounce_time" ] === "undefined" || - entry[ "first_bounce_time" ] === null + typeof entry["first_bounce_time"] === "undefined" || + entry["first_bounce_time"] === null ? 0 - : Number(BigInt(entry[ "first_bounce_time" ] as bigint) / adjust_time), + : Number(BigInt(entry["first_bounce_time"] as bigint) / adjust_time) )), last_bounce: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "last_bounce_time" ] === "undefined" || - entry[ "last_bounce_time" ] === null + typeof entry["last_bounce_time"] === "undefined" || + entry["last_bounce_time"] === null ? 0 - : Number(BigInt(entry[ "last_bounce_time" ] as bigint) / adjust_time), + : Number(BigInt(entry["last_bounce_time"] as bigint) / adjust_time) )), first_site_storage: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "first_site_storage_time" ] === "undefined" || - entry[ "first_site_storage_time" ] === null + typeof entry["first_site_storage_time"] === "undefined" || + entry["first_site_storage_time"] === null ? 0 : Number( - BigInt(entry[ "first_site_storage_time" ] as bigint) / adjust_time, - ), + BigInt(entry["first_site_storage_time"] as bigint) / adjust_time + ) )), first_stateful_bounce: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "first_stateful_bounce_time" ] === "undefined" || - entry[ "first_stateful_bounce_time" ] === null + typeof entry["first_stateful_bounce_time"] === "undefined" || + entry["first_stateful_bounce_time"] === null ? 0 : Number( - BigInt(entry[ "first_stateful_bounce_time" ] as bigint) / adjust_time, - ), + BigInt(entry["first_stateful_bounce_time"] as bigint) / adjust_time + ) )), first_user_interaction: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "first_user_interaction_time" ] === "undefined" || - entry[ "first_user_interaction_time" ] === null + typeof entry["first_user_interaction_time"] === "undefined" || + entry["first_user_interaction_time"] === null ? 0 : Number( - BigInt(entry[ "first_user_interaction_time" ] as bigint) / - adjust_time, - ), + BigInt(entry["first_user_interaction_time"] as bigint) / + adjust_time + ) )), first_web_authn_assertion: unixEpochToISO(webkitToUnixEpoch( - entry[ "first_web_authn_assertion_time" ] === null ? 0 : Number( - BigInt(entry[ "first_web_authn_assertion_time" ] as bigint) / - adjust_time, - ), + entry["first_web_authn_assertion_time"] === null ? 0 : Number( + BigInt(entry["first_web_authn_assertion_time"] as bigint) / + adjust_time + ) )), last_site_storage: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "last_site_storage_time" ] === "undefined" || - entry[ "last_site_storage_time" ] === null + typeof entry["last_site_storage_time"] === "undefined" || + entry["last_site_storage_time"] === null ? 0 : Number( - BigInt(entry[ "last_site_storage_time" ] as bigint) / adjust_time, - ), + BigInt(entry["last_site_storage_time"] as bigint) / adjust_time + ) )), last_stateful_bounce: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "last_stateful_bounce_time" ] === "undefined" || - entry[ "last_stateful_bounce_time" ] === null + typeof entry["last_stateful_bounce_time"] === "undefined" || + entry["last_stateful_bounce_time"] === null ? 0 : Number( - BigInt(entry[ "last_stateful_bounce_time" ] as bigint) / adjust_time, - ), + BigInt(entry["last_stateful_bounce_time"] as bigint) / adjust_time + ) )), last_user_interaction: unixEpochToISO(webkitToUnixEpoch( - typeof entry[ "last_user_interaction_time" ] === "undefined" || - entry[ "last_user_interaction_time" ] === null + typeof entry["last_user_interaction_time"] === "undefined" || + entry["last_user_interaction_time"] === null ? 0 : Number( - BigInt(entry[ "last_user_interaction_time" ] as bigint) / adjust_time, - ), + BigInt(entry["last_user_interaction_time"] as bigint) / adjust_time + ) )), last_web_authn_assertion: unixEpochToISO(webkitToUnixEpoch( - entry[ "last_web_authn_assertion_time" ] === null ? 0 : Number( - BigInt(entry[ "last_web_authn_assertion_time" ] as bigint) / - adjust_time, - ), + entry["last_web_authn_assertion_time"] === null ? 0 : Number( + BigInt(entry["last_web_authn_assertion_time"] as bigint) / + adjust_time + ) )), version: path.version, + message: entry["site"] as string, + datetime: unixEpochToISO(webkitToUnixEpoch( + typeof entry["first_site_storage_time"] === "undefined" || + entry["first_site_storage_time"] === null + ? 0 + : Number( + BigInt(entry["first_site_storage_time"] as bigint) / + adjust_time + ) + )), + timestamp_desc: "First Interaction", + artifact: "Browser DIPS", + data_type: `applications:${path.browser.toLowerCase()}:dips:entry`, + browser: path.browser, }; hits.push(dips_entry); } } } return hits; +} + +/** + * Function to test the Chromium sqlite file parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the Chromium sqlite parsing + */ +export function testChromiumSqlite(): void { + const path: ChromiumProfiles = { + full_path: "../../test_data/edge", + version: "141", + browser: BrowserType.EDGE + }; + let query = `SELECT + urls.id AS id, + urls.url AS url, + title, + visit_count, + typed_count, + last_visit_time, + hidden, + visits.id AS visits_id, + from_visit, + transition, + segment_id, + visit_duration, + opener_visit + FROM + urls + JOIN visits ON urls.id = visits.url LIMIT 60 OFFSET 0`; + + const hist = chromiumHistory([path], PlatformType.Darwin, true, query); + if (hist.length !== 56) { + throw `Got length ${hist.length} expected 56.......chromiumHistory āŒ`; + } + + if (hist[23]?.url !== "https://www.washingtonpost.com/latest-headlines/") { + throw `Got url ${hist[23]?.url} expected "https://www.washingtonpost.com/latest-headlines/".......chromiumHistory āŒ`; + } + + console.info(` Function chromiumHistory āœ…`); + + query = `SELECT + downloads.id AS downloads_id, + guid, + current_path, + target_path, + start_time, + received_bytes, + total_bytes, + state, + danger_type, + interrupt_reason, + hash, + end_time, + opened, + last_access_time, + transient, + referrer, + site_url, + tab_url, + tab_referrer_url, + http_method, + by_ext_id, + by_ext_name, + etag, + last_modified, + mime_type, + original_mime_type, + downloads_url_chains.id AS downloads_url_chain_id, + chain_index, + url + FROM + downloads + JOIN downloads_url_chains ON downloads_url_chains.id = downloads.id LIMIT 20 OFFSET 0`; + const downs = chromiumDownloads([path], PlatformType.Darwin, query); + if (downs.length !== 6) { + throw `Got length ${downs.length} expected 6.......chromiumDownloads āŒ`; + } + + if (downs[4]?.url !== "https://github.com/Velocidex/velociraptor/releases/download/v0.75/velociraptor-v0.75.1-windows-amd64.exe") { + throw `Got url ${downs[4]?.url} expected "https://github.com/Velocidex/velociraptor/releases/download/v0.75/velociraptor-v0.75.1-windows-amd64.exe".......chromiumDownloads āŒ`; + } + + console.info(` Function chromiumDownloads āœ…`); + + query = `SELECT * FROM cookies`; + const cook = chromiumCookies([path], PlatformType.Darwin, query); + if (cook.length !== 251) { + throw `Got length ${cook.length} expected 251.......chromiumCookies āŒ`; + } + + if (cook[4]?.message !== "Cookie name: __rubyUX | value: ") { + throw `Got url ${cook[4]?.message} expected "Cookie name: __rubyUX | value: ".......chromiumCookies āŒ`; + } + + console.info(` Function chromiumCookies āœ…`); + + query = `SSELECT name, value, date_created, date_last_used, count, value_lower from autofill`; + const fill = chromiumAutofill([path], PlatformType.Darwin, query); + if (fill.length !== 0) { + throw `Got length ${fill.length} expected 0.......chromiumAutofill āŒ`; + } + + console.info(` Function chromiumAutofill āœ…`); + + query = `SELECT * FROM logins`; + const log = chromiumLogins([path], PlatformType.Darwin, query); + if (log.length !== 0) { + throw `Got length ${log.length} expected 0.......chromiumLogins āŒ`; + } + + console.info(` Function chromiumLogins āœ…`); + + query = `SELECT * FROM bounces`; + const dip = chromiumDips([path], PlatformType.Darwin, query); + if (dip.length !== 33) { + throw `Got length ${dip.length} expected 33.......chromiumDips āŒ`; + } + + console.info(` Function chromiumDips āœ…`); + + query = `SELECT url, last_updated FROM favicons JOIN favicon_bitmaps ON favicons.id = favicon_bitmaps.id`; + const favi = chromiumFavicons([path], PlatformType.Darwin, query); + if (favi.length !== 60) { + throw `Got length ${favi.length} expected 60.......chromiumFavicons āŒ`; + } + if (favi[0]?.message !== "Favicon for chrome-extension://lmijmgnfconjockjeepmlmkkibfgjmla/pages/shared/resources/images/icons/extension/favicon.ico") { + throw `Got url ${favi[0]?.message} expected wanted "Favicon for chrome-extension://lmijmgnfconjockjeepmlmkkibfgjmla/pages/shared/resources/images/icons/extension/favicon.ico".......chromiumFavicons āŒ`; + } + + console.info(` Function chromiumFavicons āœ…`); + + query = `SELECT id,text,fill_into_edit,url,contents,description,type,keyword,last_access_time FROM omni_box_shortcuts`; + const short = chromiumShortcuts([path], PlatformType.Darwin, query); + if (short.length !== 98) { + throw `Got length ${short.length} expected 60.......chromiumShortcuts āŒ`; + } + if (short[17]?.message !== "Shortcut for https://www.bing.com/search?q=sharphound+github&FORM=ANAB01&PC=U531") { + throw `Got url ${short[17]?.message} expected wanted "Shortcut for https://www.bing.com/search?q=sharphound+github&FORM=ANAB01&PC=U531".......chromiumShortcuts āŒ`; + } + + console.info(` Function chromiumShortcuts āœ…`); } \ No newline at end of file diff --git a/src/applications/defender/definitions.ts b/src/applications/defender/definitions.ts index 006a7bbc..04491df3 100644 --- a/src/applications/defender/definitions.ts +++ b/src/applications/defender/definitions.ts @@ -49,7 +49,7 @@ export function extractDefenderRules( ): Definition[] | ApplicationError { let paths: string[] = []; if (alt_file !== undefined) { - paths = [ alt_file ]; + paths = [alt_file]; } else if (platform === PlatformType.Windows) { let drive = getEnvValue("SystemDrive"); if (drive === "") { @@ -135,6 +135,7 @@ export function extractDefenderRules( * @returns Decompressed VDM rules data */ function readVdm(path: string): Uint8Array | ApplicationError { + console.log(path); const bytes = readFile(path); if (bytes instanceof FileError) { return new ApplicationError( @@ -144,7 +145,7 @@ function readVdm(path: string): Uint8Array | ApplicationError { } // search for RMDX signature - const sig = new Uint8Array([ 82, 77, 68, 88 ]); + const sig = new Uint8Array([82, 77, 68, 88]); const sig_start = takeUntil(bytes, sig); if (sig_start instanceof NomError) { return new ApplicationError( @@ -158,38 +159,62 @@ function readVdm(path: string): Uint8Array | ApplicationError { return new ApplicationError(`DEFENDER`, `defender data too small`); } - const byte_size = 4; const size_start = 24; const decom_size_start = 28; - const zlib_data = (sig_start.remaining as Uint8Array).buffer.slice( - size_start, - size_start + byte_size + 1, - ); - const zlib_offset = new DataView(zlib_data).getUint32(0, true); - const decom_size_data = (sig_start.remaining as Uint8Array).buffer.slice( - decom_size_start, - decom_size_start + byte_size + 1, - ); - const decom_size = new DataView(decom_size_data).getUint32(0, true); + const zlib_data = take(sig_start.remaining as Uint8Array, size_start); + if (zlib_data instanceof NomError) { + return new ApplicationError( + `DEFENDER`, + `could not get to zlib data for ${path}: ${zlib_data}`, + ); + } + + const zlib_offset = nomUnsignedFourBytes(zlib_data.remaining as Uint8Array, Endian.Le); + if (zlib_offset instanceof NomError) { + return new ApplicationError( + `DEFENDER`, + `could not get to zlib offset for ${path}: ${zlib_offset}`, + ); + } + const decom_bytes = take(sig_start.remaining as Uint8Array, decom_size_start); + if (decom_bytes instanceof NomError) { + return new ApplicationError( + `DEFENDER`, + `could not get to zlib decompressed size bytes for ${path}: ${decom_bytes}`, + ); + } + const decom_size = nomUnsignedFourBytes(decom_bytes.remaining as Uint8Array, Endian.Le); + if (decom_size instanceof NomError) { + return new ApplicationError( + `DEFENDER`, + `could not get to zlib decompressed size for ${path}: ${decom_size}`, + ); + } + console.info(decom_size.value); + + const compressed_data = take(sig_start.remaining as Uint8Array, zlib_offset.value + 8); + if (compressed_data instanceof NomError) { + return new ApplicationError( + `DEFENDER`, + `could not get to compressed data for ${path}: ${compressed_data}`, + ); + } - const compressed_data = (sig_start.remaining as Uint8Array).buffer.slice( - zlib_offset + 8, - ); const wbits = 15; const decom_data = decompress_zlib( - new Uint8Array(compressed_data), + compressed_data.remaining as Uint8Array, wbits, - decom_size, + decom_size.value, ); if (decom_data instanceof CompressionError) { return new ApplicationError( `DEFENDER`, - `could decompress ${path}: ${decom_data}`, + `could not decompress ${path}: ${decom_data}`, ); } - if (decom_data.byteLength !== decom_size) { + if (decom_data.byteLength !== decom_size.value) { return new ApplicationError( `DEFENDER`, `incorrect decompressed size, expected ${decom_size} got: ${decom_data.byteLength}`, @@ -418,7 +443,7 @@ function getSigMeta(data: Uint8Array): SigMeta | ApplicationError { const bytes = new Uint8Array(data.buffer.slice(4, size + 1)); const sig: SigMeta = { - sig: signatureType(data[ 0 ]), + sig: signatureType(data[0]), size, bytes, }; @@ -591,7 +616,7 @@ function signatureType(sig: number): RuleType { 235: RuleType.SIGNATURE_TYPE_DATABASE_CATALOG, }; - const value = sigs[ sig ]; + const value = sigs[sig]; if (value === undefined) { return RuleType.SIGNATURE_TYPE_UNKNOWN; } diff --git a/src/applications/edge.ts b/src/applications/edge.ts index 2363fe21..2d657ea7 100644 --- a/src/applications/edge.ts +++ b/src/applications/edge.ts @@ -1,9 +1,11 @@ -import { BrowserType, ChromiumAutofill, ChromiumBookmarks, ChromiumCookies, ChromiumDips, ChromiumDownloads, ChromiumHistory, ChromiumLocalStorage, ChromiumLogins } from "../../types/applications/chromium"; +import { BrowserType, ChromiumAutofill, ChromiumBookmarks, ChromiumCookies, ChromiumDips, ChromiumDownloads, ChromiumFavicons, ChromiumHistory, ChromiumLocalStorage, ChromiumLogins, ChromiumSession, ChromiumShortcuts, Extension, Preferences } from "../../types/applications/chromium"; import { PlatformType } from "../system/systeminfo"; import { Chromium } from "./chromium/cr"; -import { chromiumBookmarks, chromiumExtensions, chromiumPreferences } from "./chromium/json"; +import { chromiumBookmarks, chromiumExtensions } from "./chromium/json"; import { chromiumLocalStorage } from "./chromium/level"; -import { chromiumAutofill, chromiumCookies, chromiumDips, chromiumDownloads, chromiumHistory, chromiumLogins } from "./chromium/sqlite"; +import { chromiumPreferences } from "./chromium/preferences"; +import { chromiumSessions } from "./chromium/sessions"; +import { chromiumAutofill, chromiumCookies, chromiumDips, chromiumDownloads, chromiumFavicons, chromiumHistory, chromiumLogins, chromiumShortcuts } from "./chromium/sqlite"; type EdgeHistory = ChromiumHistory; type EdgeDownloads = ChromiumDownloads; @@ -13,6 +15,9 @@ type EdgeBookmarks = ChromiumBookmarks; type EdgeLogins = ChromiumLogins; type EdgeDips = ChromiumDips; type EdgeLocalStorage = ChromiumLocalStorage; +type EdgeSession = ChromiumSession; +type EdgeFavicons = ChromiumFavicons; +type EdgeShortcuts = ChromiumShortcuts; /** * Class to extract Edge browser information. Since Edge is based on Chromium we can leverage the existing Chromium artifacts to parse Edge info @@ -26,7 +31,7 @@ export class Edge extends Chromium { * @param alt_path Optional alternative path to directory contain Edge data * @returns `Edge` instance class */ - constructor (platform: PlatformType, unfold = false, alt_path?: string) { + constructor(platform: PlatformType, unfold = false, alt_path?: string) { super(platform, unfold, BrowserType.EDGE, alt_path); } @@ -115,15 +120,15 @@ export class Edge extends Chromium { * Get installed Edge extensions * @returns Array of parsed extensions */ - public override extensions(): Record[] { + public override extensions(): Extension[] { return chromiumExtensions(this.paths, this.platform); } /** * Get Edge Preferences - * @returns Array of Preferences for each user + * @returns Array of `Preferences` for each user */ - public override preferences(): Record[] { + public override preferences(): Preferences[] { return chromiumPreferences(this.paths, this.platform); } @@ -138,6 +143,28 @@ export class Edge extends Chromium { return chromiumAutofill(this.paths, this.platform, query); } + /** + * Function to parse Edge Favicons information. + * @param [offset=0] Starting db offset. Default is zero + * @param [limit=100] How many records to return. Default is 100 + * @returns Array of `EdgeFavicons` + */ + public override favicons(offset?: number, limit?: number): EdgeFavicons[] { + const query = `SELECT url, last_updated FROM favicons JOIN favicon_bitmaps ON favicons.id = favicon_bitmaps.id LIMIT ${limit} OFFSET ${offset}`; + return chromiumFavicons(this.paths, this.platform, query); + } + + /** + * Function to parse Edge Shortcut information. + * @param [offset=0] Starting db offset. Default is zero + * @param [limit=100] How many records to return. Default is 100 + * @returns Array of `EdgeShortcuts` + */ + public override shortcuts(offset = 0, limit = 100): EdgeShortcuts[] { + const query = `SELECT id, text, fill_into_edit, url, contents, description, type, keyword, last_access_time FROM omni_box_shortcuts LIMIT ${limit} OFFSET ${offset}`; + return chromiumShortcuts(this.paths, this.platform, query); + } + /** * Get Edge Bookmarks * @returns Array of `EdgeBookmarks` for each user @@ -154,6 +181,14 @@ export class Edge extends Chromium { return chromiumLocalStorage(this.paths, this.platform); } + /** + * Get Edge Sessions + * @returns Array of `EdgeSession` for each user + */ + public override sessions(): EdgeSession[] { + return chromiumSessions(this.paths, this.platform); + } + /** * Function to parse Edge Login information. * @param [offset=0] Starting db offset. Default is zero diff --git a/src/applications/errors.ts b/src/applications/errors.ts index 0957489f..e4f9810d 100644 --- a/src/applications/errors.ts +++ b/src/applications/errors.ts @@ -14,6 +14,7 @@ export type ErrorName = | "EDGE" | "CHROMIUM" | "LEVELDB" - | "ANYDESK"; + | "ANYDESK" + | "SYNCTHING"; export class ApplicationError extends ErrorBase { } diff --git a/src/applications/firefox/addons.ts b/src/applications/firefox/addons.ts index 656ba790..ab581c2d 100644 --- a/src/applications/firefox/addons.ts +++ b/src/applications/firefox/addons.ts @@ -1,21 +1,21 @@ -import { FirefoxProfiles } from "../../../types/applications/firefox"; +import { FirefoxAddons, FirefoxProfiles } from "../../../types/applications/firefox"; import { FileError } from "../../filesystem/errors"; import { readTextFile } from "../../filesystem/files"; import { PlatformType } from "../../system/systeminfo"; -import { ApplicationError } from "../errors"; +import { unixEpochToISO } from "../../time/conversion"; /** * Get installed Firefox addons * @param paths Array of `FirefoxProfiles` * @param platform Platform to parse Firefox addons - * @returns Array of `Record` or `ApplicationError` + * @returns Array of `FirefoxAddons` or `ApplicationError` */ export function firefoxAddons( paths: FirefoxProfiles[], platform: PlatformType, -): Record[] | ApplicationError { +): FirefoxAddons[] { - let extensions: Record[] = []; + const extensions: FirefoxAddons[] = []; for (const path of paths) { let full_path = `${path.full_path}/extensions.json`; if (platform === PlatformType.Windows) { @@ -28,10 +28,28 @@ export function firefoxAddons( continue; } - const data = JSON.parse(extension)[ "addons" ]; - data[ "addons_path" ] = full_path; - - extensions = extensions.concat(data); + const data = JSON.parse(extension)["addons"]; + for (const entry of data) { + const value: FirefoxAddons = { + installed: unixEpochToISO(entry["installDate"] ?? 0), + updated: unixEpochToISO(entry["updateDate"] ?? 0), + active: entry["active"] ?? false, + visible: entry["visible"] ?? false, + author: entry["id"] ?? "", + version: entry["version"] ?? "", + path: entry["path"] ?? "", + db_path: full_path, + message: `Addon ${entry["defaultLocale"]["name"] ?? ""} installed`, + datetime: unixEpochToISO(entry["installDate"] ?? 0), + name: entry["defaultLocale"]["name"] ?? "", + description: entry["defaultLocale"]["description"] ?? "", + creator: entry["defaultLocale"]["creator"] ?? "", + timestamp_desc: "Extension Installed", + artifact: "Browser Extension", + data_type: "application:firefox:extension:entry" + }; + extensions.push(value); + } } return extensions; diff --git a/src/applications/firefox/fox.ts b/src/applications/firefox/fox.ts index 1c5201ca..3d5cf576 100644 --- a/src/applications/firefox/fox.ts +++ b/src/applications/firefox/fox.ts @@ -1,8 +1,10 @@ -import { FirefoxCookies, FirefoxDownloads, FirefoxFavicons, FirefoxHistory, FirefoxProfiles, FirefoxStorage } from "../../../types/applications/firefox"; +import { FirefoxAddons, FirefoxCookies, FirefoxDownloads, FirefoxFavicons, FirefoxHistory, FirefoxProfiles, FirefoxStorage } from "../../../types/applications/firefox"; import { GlobInfo } from "../../../types/filesystem/globs"; import { getEnvValue } from "../../environment/env"; import { FileError } from "../../filesystem/errors"; import { glob, readTextFile } from "../../filesystem/files"; +import { SystemError } from "../../system/error"; +import { dumpData, Output } from "../../system/output"; import { PlatformType } from "../../system/systeminfo"; import { ApplicationError } from "../errors"; import { firefoxAddons } from "./addons"; @@ -23,7 +25,7 @@ export class FireFox { * @param alt_path Optional alternative path to directory contain FireFox data * @returns `FireFox` instance class */ - constructor (platform: PlatformType, unfold = false, alt_path?: string) { + constructor(platform: PlatformType, unfold = false, alt_path?: string) { this.platform = platform; this.unfold = unfold; if (alt_path === undefined) { @@ -39,19 +41,19 @@ export class FireFox { return; } - this.paths = [ { + this.paths = [{ full_path: alt_path, version: fox_version - } ]; + }]; } /** * Extract FireFox history * @param [offset=0] Starting db offset. Default is zero * @param [limit=100] How many records to return. Default is 100 - * @returns Array of `FirefoxHistory` or `ApplicationError` + * @returns Array of `FirefoxHistory` */ - public history(offset = 0, limit = 100): FirefoxHistory[] | ApplicationError { + public history(offset = 0, limit = 100): FirefoxHistory[] { return firefoxHistory(this.paths, this.platform, this.unfold, offset, limit); } @@ -59,9 +61,9 @@ export class FireFox { * Extract FireFox cookies * @param [offset=0] Starting db offset. Default is zero * @param [limit=100] How many records to return. Default is 100 - * @returns Array of `FirefoxCookies` or `ApplicationError` + * @returns Array of `FirefoxCookies` */ - public cookies(offset = 0, limit = 100): FirefoxCookies[] | ApplicationError { + public cookies(offset = 0, limit = 100): FirefoxCookies[] { return firefoxCookies(this.paths, this.platform, offset, limit); } @@ -69,17 +71,17 @@ export class FireFox { * Extract FireFox downloads * @param [offset=0] Starting db offset. Default is zero * @param [limit=100] How many records to return. Default is 100 - * @returns Array of `FirefoxDownloads` or `ApplicationError` + * @returns Array of `FirefoxDownloads` */ - public downloads(offset = 0, limit = 100): FirefoxDownloads[] | ApplicationError { + public downloads(offset = 0, limit = 100): FirefoxDownloads[] { return firefoxDownloads(this.paths, this.platform, offset, limit); } /** * Extract FireFox addons - * @returns Array of `JSON` objects or `ApplicationError` + * @returns Array of `JSON` objects */ - public addons(): Record[] | ApplicationError { + public addons(): FirefoxAddons[] { return firefoxAddons(this.paths, this.platform); } @@ -87,9 +89,9 @@ export class FireFox { * Function to extract entries from `storage.sqlite` * @param [offset=0] Starting db offset. Default is zero * @param [limit=100] How many records to return. Default is 100 - * @returns Array of `FirefoxStorage` or `ApplicationError` + * @returns Array of `FirefoxStorage` */ - public storage(offset = 0, limit = 100): FirefoxStorage[] | ApplicationError { + public storage(offset = 0, limit = 100): FirefoxStorage[] { return firefoxStorage(this.paths, this.platform, offset, limit); } @@ -97,12 +99,82 @@ export class FireFox { * Function to extract favicon entries * @param [offset=0] Starting db offset. Default is zero * @param [limit=100] How many records to return. Default is 100 - * @returns Array of `FirefoxFavicons` or `ApplicationError` + * @returns Array of `FirefoxFavicons` */ - public favicons(offset = 0, limit = 100): FirefoxFavicons[] | ApplicationError { + public favicons(offset = 0, limit = 100): FirefoxFavicons[] { return firefoxFavicons(this.paths, this.platform, offset, limit); } + /** + * Function to timeline all Firefox artifacts. Similar to [Hindsight](https://github.com/obsidianforensics/hindsight) + * @param output `Output` structure object. Format type should be either `JSON` or `JSONL`. `JSONL` is recommended + */ + public retrospect(output: Output): void { + let offset = 0; + const limit = 100; + + while (true) { + const entries = this.history(offset, limit); + if (entries.length === 0) { + break; + } + if (!this.unfold) { + entries.forEach(x => delete x["unfold"]); + } + const status = dumpData(entries, `retrospect_firefox_history`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline firefox history: ${status}`); + } + offset += limit; + } + + offset = 0; + + while (true) { + const entries = this.cookies(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_firefox_cookies`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline firefox cookies: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.favicons(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_firefox_favicons`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline firefox favicons: ${status}`); + } + offset += limit; + } + + offset = 0; + while (true) { + const entries = this.storage(offset, limit); + if (entries.length === 0) { + break; + } + const status = dumpData(entries, `retrospect_firefox_storage`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline firefox storage: ${status}`); + } + offset += limit; + } + + const ext = this.addons(); + const status = dumpData(ext, `retrospect_firefox_extensions`, output); + if (status instanceof SystemError) { + console.error(`Failed timeline firefox extensions: ${status}`); + } + } + /** * Get base path for all FireFox data * @param platform OS `PlatformType` diff --git a/src/applications/firefox/sqlite.ts b/src/applications/firefox/sqlite.ts index 80c5f215..255ffb25 100644 --- a/src/applications/firefox/sqlite.ts +++ b/src/applications/firefox/sqlite.ts @@ -42,7 +42,7 @@ export function firefoxHistory(paths: FirefoxProfiles[], platform: PlatformType, if (unfold) { client = new Unfold(); } - + for (const path of paths) { let full_path = `${path.full_path}/places.sqlite`; @@ -68,7 +68,7 @@ export function firefoxHistory(paths: FirefoxProfiles[], platform: PlatformType, typed: entry["typed"] as number ?? 0, frequency: entry["frequency"] as number ?? 0, last_visit_date: unixEpochToISO( - entry["last_visit_date"] as bigint ?? 0, + entry["last_visit_date"] as bigint ?? 0 ), guid: entry["guid"] as string ?? "", foreign_count: entry["foreign_count"] as number ?? 0, @@ -79,6 +79,13 @@ export function firefoxHistory(paths: FirefoxProfiles[], platform: PlatformType, host: entry["host"] as string ?? "", unfold: undefined, db_path: full_path, + message: entry["url"] as string ?? "", + datetime: unixEpochToISO( + entry["last_visit_date"] as bigint ?? 0 + ), + timestamp_desc: "URL Visited", + artifact: "URL History", + data_type: "application:firefox:history:entry" }; if (unfold && typeof client !== 'undefined') { @@ -102,7 +109,7 @@ export function firefoxHistory(paths: FirefoxProfiles[], platform: PlatformType, * @param limit Number of records to return * @returns Array of `FirefoxDownloads` or `ApplicationError` */ -export function firefoxDownloads(paths: FirefoxProfiles[], platform: PlatformType, offset: number, limit: number): FirefoxDownloads[] | ApplicationError { +export function firefoxDownloads(paths: FirefoxProfiles[], platform: PlatformType, offset: number, limit: number): FirefoxDownloads[] { const query = `SELECT moz_annos.id AS downloads_id, place_id, @@ -155,14 +162,38 @@ export function firefoxDownloads(paths: FirefoxProfiles[], platform: PlatformTyp expiration: entry["expiration"] as number ?? 0, download_type: entry["download_type"] as number ?? 0, date_added: unixEpochToISO( - entry["date_added"] as bigint ?? 0, + entry["date_added"] as bigint ?? 0 ), last_modified: unixEpochToISO( - entry["last_modified"] as bigint ?? 0, + entry["last_modified"] as bigint ?? 0 ), name: entry["name"] as string ?? "", db_path: full_path, + message: "", + datetime: unixEpochToISO( + entry["date_added"] as bigint ?? 0 + ), + timestamp_desc: "File Download Start", + artifact: "File Download", + data_type: "application:firefox:downloads:entry", + moz_places_id: entry["moz_places_id"] as number ?? 0, + url: entry["url"] as string ?? "", + title: entry["title"] as string ?? "", + rev_host: entry["rev_host"] as string ?? "", + visit_count: entry["visit_count"] as number ?? 0, + hidden: entry["hidden"] as number ?? 0, + typed: entry["typed"] as number ?? 0, + frequency: entry["frequency"] as number ?? 0, + last_visit_date: unixEpochToISO( + entry["last_visit_date"] as bigint ?? 0 + ), + guid: entry["guid"] as string ?? "", + foreign_count: entry["foreign_count"] as number ?? 0, + url_hash: entry["url_hash"] as number ?? 0, + description: entry["description"] as string ?? "", + preview_image_url: entry["preview_image_url"] as string ?? "", }; + download_row.message = `File download from: ${download_row.url} | File: ${download_row.name}` hits.push(download_row); } @@ -179,23 +210,22 @@ export function firefoxDownloads(paths: FirefoxProfiles[], platform: PlatformTyp * @param limit Number of records to return * @returns Array of `FirefoxCookies` or `ApplicationError` */ -export function firefoxCookies(paths: FirefoxProfiles[], platform: PlatformType, offset: number, limit: number): FirefoxCookies[] | ApplicationError { +export function firefoxCookies(paths: FirefoxProfiles[], platform: PlatformType, offset: number, limit: number): FirefoxCookies[] { const cookies: FirefoxCookies[] = []; const query = `select * from moz_cookies LIMIT ${limit} OFFSET ${offset}`; for (const path of paths) { - let full_path = `${path.full_path}/places.sqlite`; + let full_path = `${path.full_path}/cookies.sqlite`; if (platform === PlatformType.Windows) { - full_path = `${path.full_path}\\places.sqlite`; + full_path = `${path.full_path}\\cookies.sqlite`; } const results = querySqlite(full_path, query); if (results instanceof ApplicationError) { - console.warn(`Failed to query ${full_path}: ${results}`); + console.warn(`Failed to query ${full_path}: ${results.message}`); continue; } - const adjust_time: bigint = 1000000n; for (const entry of results) { const cookie_entry: FirefoxCookies = { @@ -203,30 +233,33 @@ export function firefoxCookies(paths: FirefoxProfiles[], platform: PlatformType, origin_attributes: entry["originAttributes"] as string, in_browser_element: !!(entry["inBrowserElement"] as number), same_site: !!(entry["sameSite"] as number), - raw_same_site: !!(entry["rawSameSite"] as number), - scheme_map: entry["rawSameSite"] as number, - name: entry["name"] as string | undefined, - value: entry["value"] as string | undefined, - path: entry["path"] as string | undefined, - expiry: entry["expiry"] as number | undefined, - is_secure: !!(entry["isSecure"] as number | undefined), - is_http_only: !!(entry["isSecure"] as number | undefined), - host: entry["host"] as string | undefined, + scheme_map: entry["schemeMap"] as number, + name: entry["name"] as string ?? "", + value: entry["value"] as string ?? "", + path: entry["path"] as string ?? "", + expiry: unixEpochToISO( + (entry["expiry"] as bigint ?? 0) + ), + is_secure: !!(entry["isSecure"] as number ?? 0), + is_http_only: !!(entry["isHttpOnly"] as number ?? 0), + host: entry["host"] as string ?? "", db_path: full_path, + message: "", + datetime: unixEpochToISO( + entry["expiry"] as bigint ?? 0 + ), + timestamp_desc: "Cookie Expires", + artifact: "Website Cookie", + data_type: "application:firefox:cookies:entry", + last_accessed: unixEpochToISO( + (entry["lastAccessed"] as bigint ?? 0) + ), + creation_time: unixEpochToISO( + (entry["creationTime"] as bigint ?? 0) + ) }; - if (entry["lastAccessed"] !== undefined) { - cookie_entry.last_accessed = unixEpochToISO(Number( - BigInt(entry["lastAccessed"] as bigint) / adjust_time, - )); - } - - if (entry["creationTime"] !== undefined) { - cookie_entry.creation_time = unixEpochToISO(Number( - BigInt(entry["creationTime"] as bigint) / adjust_time, - )); - } - + cookie_entry.message = `Cookie from ${cookie_entry.host} | Value: ${cookie_entry.value}` cookies.push(cookie_entry); } @@ -243,15 +276,15 @@ export function firefoxCookies(paths: FirefoxProfiles[], platform: PlatformType, * @param limit Number of records to return * @returns Array of `FirefoxFavicons` or `ApplicationError` */ -export function firefoxFavicons(paths: FirefoxProfiles[], platform: PlatformType, offset: number, limit: number): FirefoxFavicons[] | ApplicationError { +export function firefoxFavicons(paths: FirefoxProfiles[], platform: PlatformType, offset: number, limit: number): FirefoxFavicons[] { const favicons: FirefoxFavicons[] = []; - const query = `SELECT icon_url, expire_ms FROM moz_cookies LIMIT ${limit} OFFSET ${offset}`; + const query = `SELECT icon_url, expire_ms FROM moz_icons LIMIT ${limit} OFFSET ${offset}`; for (const path of paths) { - let full_path = `${path.full_path}/places.sqlite`; + let full_path = `${path.full_path}/favicons.sqlite`; if (platform === PlatformType.Windows) { - full_path = `${path.full_path}\\places.sqlite`; + full_path = `${path.full_path}\\favicons.sqlite`; } const results = querySqlite(full_path, query); @@ -265,6 +298,11 @@ export function firefoxFavicons(paths: FirefoxProfiles[], platform: PlatformType icon_url: entry["icon_url"] as string, expires: unixEpochToISO(entry["expire_ms"] as number), db_path: full_path, + datetime: unixEpochToISO(entry["expire_ms"] as number), + timestamp_desc: "Favicon Expires", + artifact: "URL Favicon", + data_type: "application:firefox:favicons:entry", + message: `Favicon: ${entry["icon_url"]}` }; favicons.push(fav_entry); @@ -282,8 +320,8 @@ export function firefoxFavicons(paths: FirefoxProfiles[], platform: PlatformType * @param limit Number of records to return * @returns Array of `FirefoxFavicons` or `ApplicationError` */ -export function firefoxStorage(paths: FirefoxProfiles[], platform: PlatformType, offset: number, limit: number): FirefoxStorage[] | ApplicationError { - const query = `SELECT respository_id, suffix, group_, origin, client_usages, usage, last_access_time, accessed, persisted FROM origin LIMIT ${limit} OFFSET ${offset}`; +export function firefoxStorage(paths: FirefoxProfiles[], platform: PlatformType, offset: number, limit: number): FirefoxStorage[] { + const query = `SELECT repository_id, suffix, group_, origin, client_usages, usage, last_access_time, accessed, persisted FROM origin LIMIT ${limit} OFFSET ${offset}`; const storage: FirefoxStorage[] = []; for (const path of paths) { @@ -302,14 +340,19 @@ export function firefoxStorage(paths: FirefoxProfiles[], platform: PlatformType, for (const entry of results) { const fav_entry: FirefoxStorage = { db_path: full_path, - repository: getRepo(entry["respository_id"] as number), + repository: getRepo(entry["repository_id"] as number), group: entry["group_"] as string, origin: entry["origin"] as string, client_usages: entry["client_usages"] as string, last_access: unixEpochToISO(entry["last_access_time"] as number), accessed: entry["accessed"] as number, persisted: entry["persisted"] as number, - suffix: entry["suffix"] as string ?? undefined + suffix: entry["suffix"] as string ?? undefined, + datetime: unixEpochToISO(entry["last_access_time"] as number), + timestamp_desc: "Website Storage Last Accessed", + artifact: "Website Storage", + data_type: "application:firefox:storage:entry", + message: `Storage for ${entry["origin"]}` }; storage.push(fav_entry); diff --git a/src/applications/leveldb/table.ts b/src/applications/leveldb/table.ts index 2cda6ce0..b27543c9 100644 --- a/src/applications/leveldb/table.ts +++ b/src/applications/leveldb/table.ts @@ -101,7 +101,7 @@ function parseFooter(data: Uint8Array): Footer | ApplicationError { // Typically this is 8 bytes in length. However, technically it could be longer // There is often 0 padding between varint data and the footer signature. So we can nom until we encounter that - const var_data = takeUntil(foot_start.remaining, new Uint8Array([0])); + const var_data = takeUntil(foot_start.remaining, new Uint8Array([ 0 ])); if (var_data instanceof NomError) { return new ApplicationError(`LEVELDB`, `could not parse var data: ${var_data}`); } @@ -213,7 +213,7 @@ interface KeyValueData { */ function parseKey(shared_key: string, data: Uint8Array): KeyValueData | ApplicationError { let remaining = data; - let share_key = parseVarInt(remaining); + const share_key = parseVarInt(remaining); if (share_key instanceof ApplicationError) { return share_key; } @@ -230,7 +230,7 @@ function parseKey(shared_key: string, data: Uint8Array): KeyValueData | Applicat remaining = share_key.remaining; } - let key = parseVarInt(remaining); + const key = parseVarInt(remaining); if (key instanceof ApplicationError) { return key; } @@ -258,16 +258,18 @@ function parseKey(shared_key: string, data: Uint8Array): KeyValueData | Applicat // Sometimes key is composed of 2 strings const prefix = 95; // If key starts has prefix '_' then it has two parts - if ((key_data.nommed as Uint8Array)[0] === prefix) { + if ((key_data.nommed as Uint8Array)[ 0 ] === prefix) { // Sometimes first part of the key has end of string character - const first_part = takeUntil(key_data.nommed, new Uint8Array([0])); + const first_part = takeUntil(key_data.nommed, new Uint8Array([ 0 ])); if (first_part instanceof NomError) { // If end of string character not found. Try entire string key_string = extractUtf8String(key_data.nommed as Uint8Array); } else { const first_data = (first_part.remaining as Uint8Array).buffer.slice(2); + const string_flag = new Uint8Array((first_part.remaining as Uint8Array).buffer.slice(1, 2)); + const is_utf16 = new Uint8Array([ 0 ]); // If 0 the encoding is UTF16-LE. Otherwise its ASCII - if (new Uint8Array((first_part.remaining as Uint8Array).buffer.slice(1, 2)) === new Uint8Array([0])) { + if (string_flag === is_utf16) { key_string = `${extractUtf8String(first_part.nommed as Uint8Array)} ${extractUtf16String(new Uint8Array(first_data))}`; } else { key_string = `${extractUtf8String(first_part.nommed as Uint8Array)} ${extractUtf8String(new Uint8Array(first_data))}`; @@ -442,7 +444,7 @@ interface BlockValue { */ function parseBlockData(shared_key: string, data: Uint8Array): BlockValue | ApplicationError { let remaining = data; - let share_key = parseVarInt(remaining); + const share_key = parseVarInt(remaining); if (share_key instanceof ApplicationError) { return share_key; } @@ -459,8 +461,7 @@ function parseBlockData(shared_key: string, data: Uint8Array): BlockValue | Appl remaining = share_key.remaining; } - - let non_shared_key = parseVarInt(remaining); + const non_shared_key = parseVarInt(remaining); if (non_shared_key instanceof ApplicationError) { return non_shared_key; } @@ -497,13 +498,15 @@ function parseBlockData(shared_key: string, data: Uint8Array): BlockValue | Appl let key_string = ""; let entry_key = ""; // First key string has end of string character? - const first_part = takeUntil(key_data, new Uint8Array([0])); + const first_part = takeUntil(key_data, new Uint8Array([ 0 ])); if (first_part instanceof NomError) { key_string = extractUtf8String(key_data); } else { const first_data = (first_part.remaining as Uint8Array).buffer.slice(2); + const string_flag = new Uint8Array((first_part.remaining as Uint8Array).buffer.slice(1, 2)); + const is_utf16 = new Uint8Array([ 0 ]); // If 0 the encoding is UTF16-LE. Otherwise its ASCII - if (new Uint8Array((first_part.remaining as Uint8Array).buffer.slice(1, 2)) === new Uint8Array([0])) { + if (string_flag === is_utf16) { key_string = `${extractUtf8String(first_part.nommed as Uint8Array)} ${extractUtf16String(new Uint8Array(first_data))}`; entry_key = `${extractUtf8String(first_part.nommed as Uint8Array)} ${extractUtf16String(new Uint8Array(first_data))}`; } else { @@ -576,8 +579,12 @@ export function testLevelLdb(): void { throw `Got length ${block_result.length} expected 61.......parseBlock āŒ`; } - if (!JSON.stringify(block_result[0].value).includes("13401944653177090")) { - throw `Got value ${JSON.stringify(block_result[0].value)} expected to contain 13401944653177090.......parseBlock āŒ`; + if (block_result[ 0 ] === undefined) { + throw 'Got undefined.......parseBlock āŒ'; + } + + if (!JSON.stringify(block_result[ 0 ].value).includes("13401944653177090")) { + throw `Got value ${JSON.stringify(block_result[ 0 ].value)} expected to contain 13401944653177090.......parseBlock āŒ`; } console.info(` Function parseBlock āœ…`); @@ -606,7 +613,7 @@ export function testLevelLdb(): void { console.info(` Function parseBlockData āœ…`); - const parse_key_block_test = [0, 201, 23]; + const parse_key_block_test = [ 0, 201, 23 ]; const parse_key_block_result = parseKeyBlock(new Uint8Array(parse_key_block_test)); if (parse_key_block_result instanceof ApplicationError) { throw parse_key_block_result; @@ -623,7 +630,7 @@ export function testLevelLdb(): void { console.info(` Function parseKeyBlock āœ…`); - const parse_key_test = [0, 34, 3, 95, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 0, 1, 96, 1, 255, 255, 255, 255, 255, 255, 255, 0, 201, 23, 0, 57, 5, 95, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 0, 1, 115, 98, 95, 119, 105, 122, 46, 122, 112, 99, 46, 103, 119, 115, 45, 119, 105, 122, 45, 115, 101, 114, 112, 46, 1, 84, 0, 0, 0, 0, 0, 0, 206, 23, 214, 240, 3, 0, 57, 6, 95, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 0, 1, 115, 98, 95, 119, 105, 122, 46, 122, 112, 99, 46, 103, 119, 115, 45, 119, 105, 122, 45, 115, 101, 114, 112, 46, 1, 62, 0, 0, 0, 0, 0, 0, 169, 136, 4, 234, 252, 1, 0, 9, 5, 96, 1, 255, 255, 255, 255, 255, 255, 255, 152, 133, 6, 212, 15, 0, 0, 0, 0, 40, 0, 0, 0, 105, 0, 0, 0, 171, 0, 0, 0, 4, 0, 0, 0]; + const parse_key_test = [ 0, 34, 3, 95, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 0, 1, 96, 1, 255, 255, 255, 255, 255, 255, 255, 0, 201, 23, 0, 57, 5, 95, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 0, 1, 115, 98, 95, 119, 105, 122, 46, 122, 112, 99, 46, 103, 119, 115, 45, 119, 105, 122, 45, 115, 101, 114, 112, 46, 1, 84, 0, 0, 0, 0, 0, 0, 206, 23, 214, 240, 3, 0, 57, 6, 95, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 0, 1, 115, 98, 95, 119, 105, 122, 46, 122, 112, 99, 46, 103, 119, 115, 45, 119, 105, 122, 45, 115, 101, 114, 112, 46, 1, 62, 0, 0, 0, 0, 0, 0, 169, 136, 4, 234, 252, 1, 0, 9, 5, 96, 1, 255, 255, 255, 255, 255, 255, 255, 152, 133, 6, 212, 15, 0, 0, 0, 0, 40, 0, 0, 0, 105, 0, 0, 0, 171, 0, 0, 0, 4, 0, 0, 0 ]; const parse_key_result = parseKey("", new Uint8Array(parse_key_test)); if (parse_key_result instanceof ApplicationError) { throw parse_key_result; @@ -633,14 +640,14 @@ export function testLevelLdb(): void { throw `Got key ${parse_key_result.key} expected '_https://www.google.com \`'.......parseKey āŒ`; } - if (JSON.stringify(Array.from(parse_key_result.value)) !== JSON.stringify([0, 201, 23])) { + if (JSON.stringify(Array.from(parse_key_result.value)) !== JSON.stringify([ 0, 201, 23 ])) { throw `Got value [${parse_key_result.value}] expected [0,201,23].......parseKey āŒ`; } console.info(` Function parseKey āœ…`); - const parse_index_test = [208, 1, 120, 0, 34, 3, 95, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 0, 1, 96, 1, 255, 9, 1, 20, 0, 201, 23, 0, 57, 5, 98, 40, 0, 104, 115, 98, 95, 119, 105, 122, 46, 122, 112, 99, 46, 103, 119, 115, 45, 119, 105, 122, 45, 115, 101, 114, 112, 46, 1, 84, 0, 5, 1, 28, 206, 23, 214, 240, 3, 0, 57, 6, 198, 65, 0, 0, 62, 5, 64, 44, 0, 169, 136, 4, 234, 252, 1, 0, 9, 5, 96, 1, 9, 145, 20, 255, 152, 133, 6, 212, 15, 1, 29, 60, 40, 0, 0, 0, 105, 0, 0, 0, 171, 0, 0, 0, 4, 0, 0, 0, 1, 95, 36, 244, 214, 241, 148, 6, 8, 254, 148, 6, 133, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 251, 128, 139, 36, 117, 71, 219]; + const parse_index_test = [ 208, 1, 120, 0, 34, 3, 95, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 0, 1, 96, 1, 255, 9, 1, 20, 0, 201, 23, 0, 57, 5, 98, 40, 0, 104, 115, 98, 95, 119, 105, 122, 46, 122, 112, 99, 46, 103, 119, 115, 45, 119, 105, 122, 45, 115, 101, 114, 112, 46, 1, 84, 0, 5, 1, 28, 206, 23, 214, 240, 3, 0, 57, 6, 198, 65, 0, 0, 62, 5, 64, 44, 0, 169, 136, 4, 234, 252, 1, 0, 9, 5, 96, 1, 9, 145, 20, 255, 152, 133, 6, 212, 15, 1, 29, 60, 40, 0, 0, 0, 105, 0, 0, 0, 171, 0, 0, 0, 4, 0, 0, 0, 1, 95, 36, 244, 214, 241, 148, 6, 8, 254, 148, 6, 133, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 251, 128, 139, 36, 117, 71, 219 ]; const parse_index_result = parseIndex(new Uint8Array(parse_index_test), 133, 0); if (parse_index_result instanceof ApplicationError) { throw parse_index_result; @@ -657,7 +664,7 @@ export function testLevelLdb(): void { console.info(` Function parseIndex āœ…`); - const parse_foot_test = [241, 148, 6, 8, 254, 148, 6, 133, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 251, 128, 139, 36, 117, 71, 219]; + const parse_foot_test = [ 241, 148, 6, 8, 254, 148, 6, 133, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 251, 128, 139, 36, 117, 71, 219 ]; const parse_footer_result = parseFooter(new Uint8Array(parse_foot_test)); if (parse_footer_result instanceof ApplicationError) { throw parse_footer_result; @@ -683,8 +690,12 @@ export function testLevelLdb(): void { throw `Got ldb entries length ${parse_ldb_result.length} expected 109.......parseLdb āŒ`; } - if (!JSON.stringify(parse_ldb_result[8].value).includes("13401944468429548")) { - throw `Got ldb entry value ${JSON.stringify(parse_ldb_result[8].value)} expected to include 13401944468429548.......parseLdb āŒ`; + if (parse_ldb_result[ 8 ] === undefined) { + throw 'Got undefined.......parseLdb āŒ'; + } + + if (!JSON.stringify(parse_ldb_result[ 8 ].value).includes("13401944468429548")) { + throw `Got ldb entry value ${JSON.stringify(parse_ldb_result[ 8 ].value)} expected to include 13401944468429548.......parseLdb āŒ`; } console.info(` Function parseLdb āœ…`); diff --git a/src/applications/leveldb/wal.ts b/src/applications/leveldb/wal.ts index 45061087..a4c9ffa0 100644 --- a/src/applications/leveldb/wal.ts +++ b/src/applications/leveldb/wal.ts @@ -1,4 +1,4 @@ -import { CompactPoint, DeletedFile, LevelDbEntry, LevelManifest, LogType, ManifestTag, NewFileValue, RecordType, ValueType, WalData, WalValue } from "../../../types/applications/level"; +import { CompactPoint, DeletedFile, LevelDbEntry, LevelManifest, LogType, ManifestTag, NewFileValue, RecordType, ValueType, } from "../../../types/applications/level"; import { ProtoTag } from "../../../types/encoding/protobuf"; import { encode } from "../../encoding/base64"; import { EncodingError } from "../../encoding/errors"; @@ -66,7 +66,7 @@ export function parseWalManifest(path: string): LevelManifest[] | ApplicationErr if (value instanceof ApplicationError) { return value; } - entry.records.push({ [tag]: value.value }); + entry.records.push({ [ tag ]: value.value }); tag_remaining = value.remaining; } remaining = record.remaining as Uint8Array; @@ -110,7 +110,7 @@ export function parseWal(path: string): LevelDbEntry[] | ApplicationError { } const record_type = getRecordType(input.value); - let record = take(input.remaining, size); + const record = take(input.remaining, size); if (record instanceof NomError) { return new ApplicationError(`LEVELDB`, `could not get entry for ${path}: ${record}`); } @@ -152,12 +152,12 @@ export function parseWal(path: string): LevelDbEntry[] | ApplicationError { * @returns Array of `WalValue` or `ApplicationError` */ function parseWalValues(data: Uint8Array, path: string): LevelDbEntry[] | ApplicationError { - let sequence = nomUnsignedEightBytes(data, Endian.Le); + const sequence = nomUnsignedEightBytes(data, Endian.Le); if (sequence instanceof NomError) { return new ApplicationError(`LEVELDB`, `could not get wal sequence: ${sequence}`); } - let input = nomUnsignedFourBytes(sequence.remaining, Endian.Le); + const input = nomUnsignedFourBytes(sequence.remaining, Endian.Le); if (input instanceof NomError) { return new ApplicationError(`LEVELDB`, `could not get wal count: ${input}`); } @@ -411,7 +411,7 @@ function getTagValue(tag: ManifestTag, data: Uint8Array): TagValue | Application export function parseVarInt(data: Uint8Array): TagValue | ApplicationError { // If the varint length is one then 0 index is our value if (data.buffer.byteLength === 1) { - return { value: data[0], remaining: new Uint8Array() }; + return { value: data[ 0 ] ?? 0, remaining: new Uint8Array() }; } let var_value = 0; @@ -422,7 +422,7 @@ export function parseVarInt(data: Uint8Array): TagValue | ApplicationError { const wire = 7; const done = 0x80; while (proto_data.buffer.byteLength !== 0) { - let value = nomUnsignedOneBytes(proto_data); + const value = nomUnsignedOneBytes(proto_data); if (value instanceof NomError) { return new ApplicationError(`LEVELDB`, `could not parse varint ${value}`); } @@ -448,14 +448,16 @@ function parseKey(data: Uint8Array): string { // If key starts has prefix '_' then it has two parts if (data.at(0) === prefix) { // First has end of string character? - const first_part = takeUntil(data, new Uint8Array([0])); + const first_part = takeUntil(data, new Uint8Array([ 0 ])); if (first_part instanceof NomError) { return "Unknown Key"; } const first_data = (first_part.remaining as Uint8Array).buffer.slice(2); + const string_flag = new Uint8Array((first_part.remaining as Uint8Array).buffer.slice(1, 2)); + const is_utf16 = new Uint8Array([ 0 ]); // If 0 the encoding is UTF16-LE. Otherwise its ASCII - if (new Uint8Array((first_part.remaining as Uint8Array).buffer.slice(1, 2)) === new Uint8Array([0])) { + if (string_flag === is_utf16) { return `${extractUtf8String(first_part.nommed as Uint8Array)} ${extractUtf16String(new Uint8Array(first_data))}`; } else { return `${extractUtf8String(first_part.nommed as Uint8Array)} ${extractUtf8String(new Uint8Array(first_data))}`; @@ -546,27 +548,27 @@ export function parseValue(data: Uint8Array, value_type: ValueType): string | nu * Or want to validate the leveldb parsing */ export function testLevelWal(): void { - const parse_value_test = [8, 130, 194, 232, 178, 246, 159, 231, 23, 16, 85]; + const parse_value_test = [ 8, 130, 194, 232, 178, 246, 159, 231, 23, 16, 85 ]; const parse_value_result = parseValue(new Uint8Array(parse_value_test), ValueType.Protobuf); if (parse_value_result instanceof ApplicationError) { throw parse_value_result; } - if (parse_value_result["1"].value != "13401944653177090") { - throw `Got value ${parse_value_result["1"].value} expected 13401944653177090.......parseValue āŒ`; + if (parse_value_result[ "1" ].value != "13401944653177090") { + throw `Got value ${parse_value_result[ "1" ].value} expected 13401944653177090.......parseValue āŒ`; } console.info(` Function parseValue āœ…`); - const value_type_test = [0, 1, 2, 3, 4, 6, 8, 15]; + const value_type_test = [ 0, 1, 2, 3, 4, 6, 8, 15 ]; for (const entry of value_type_test) { - const result = getValueType(new Uint8Array([entry, 0, 0, 0])); + const result = getValueType(new Uint8Array([ entry, 0, 0, 0 ])); if (result === ValueType.Unknown) { - `Got unknown value type for ${entry}.......getValueType āŒ`; + throw `Got unknown value type for ${entry}.......getValueType āŒ`; } } console.info(` Function getValueType āœ…`); - const parse_key_test = [77, 69, 84, 65, 58, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109]; + const parse_key_test = [ 77, 69, 84, 65, 58, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109 ]; const parse_key_result = parseKey(new Uint8Array(parse_key_test)); if (parse_key_result !== "META:https://www.google.com") { @@ -574,7 +576,7 @@ export function testLevelWal(): void { } console.info(` Function parseKey āœ…`); - const parse_var_int_test = [77, 69, 84, 65, 58, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109]; + const parse_var_int_test = [ 77, 69, 84, 65, 58, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109 ]; const parse_var_int_result = parseVarInt(new Uint8Array(parse_var_int_test)); if (parse_var_int_result instanceof ApplicationError) { throw parse_var_int_result; @@ -584,7 +586,7 @@ export function testLevelWal(): void { } console.info(` Function parseVarInt āœ…`); - const get_tag_value_test = [26, 108, 101, 118, 101, 108, 100, 98, 46, 66, 121, 116, 101, 119, 105, 115, 101, 67, 111, 109, 112, 97, 114, 97, 116, 111, 114, 2, 0, 3, 2, 4, 0]; + const get_tag_value_test = [ 26, 108, 101, 118, 101, 108, 100, 98, 46, 66, 121, 116, 101, 119, 105, 115, 101, 67, 111, 109, 112, 97, 114, 97, 116, 111, 114, 2, 0, 3, 2, 4, 0 ]; const get_tag_value_result = getTagValue(ManifestTag.Comparator, new Uint8Array(get_tag_value_test)); if (get_tag_value_result instanceof ApplicationError) { throw get_tag_value_result; @@ -594,25 +596,25 @@ export function testLevelWal(): void { } console.info(` Function getTagValue āœ…`); - const get_tag_test = [1, 2, 3, 4, 5, 6, 7, 9]; + const get_tag_test = [ 1, 2, 3, 4, 5, 6, 7, 9 ]; for (const entry of get_tag_test) { const result = getTag(entry); if (result === ManifestTag.Unknown) { - `Got unknown manifest tag for ${entry}.......getTag āŒ`; + throw `Got unknown manifest tag for ${entry}.......getTag āŒ`; } } console.info(` Function getTag āœ…`); - const get_record_type_test = [1, 2, 3, 4]; + const get_record_type_test = [ 1, 2, 3, 4 ]; for (const entry of get_record_type_test) { const result = getRecordType(entry); if (result === RecordType.Unknown) { - `Got unknown record type for ${entry}.......getRecordType āŒ`; + throw `Got unknown record type for ${entry}.......getRecordType āŒ`; } } console.info(` Function getRecordType āœ…`); - const parse_wal_values_test = [226, 45, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 12, 77, 69, 84, 65, 58, 102, 105, 108, 101, 58, 47, 47, 11, 8, 208, 186, 223, 177, 158, 197, 230, 23, 16, 36, 1, 31, 95, 102, 105, 108, 101, 58, 47, 47, 0, 1, 108, 97, 115, 116, 82, 101, 99, 101, 105, 118, 101, 100, 65, 116, 67, 111, 117, 110, 116, 101, 114, 14, 1, 49, 55, 53, 51, 57, 50, 51, 55, 48, 48, 51, 48, 55 + const parse_wal_values_test = [ 226, 45, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 12, 77, 69, 84, 65, 58, 102, 105, 108, 101, 58, 47, 47, 11, 8, 208, 186, 223, 177, 158, 197, 230, 23, 16, 36, 1, 31, 95, 102, 105, 108, 101, 58, 47, 47, 0, 1, 108, 97, 115, 116, 82, 101, 99, 101, 105, 118, 101, 100, 65, 116, 67, 111, 117, 110, 116, 101, 114, 14, 1, 49, 55, 53, 51, 57, 50, 51, 55, 48, 48, 51, 48, 55 ]; const parse_wal_values_result = parseWalValues(new Uint8Array(parse_wal_values_test), ""); if (parse_wal_values_result instanceof ApplicationError) { @@ -622,8 +624,8 @@ export function testLevelWal(): void { if (parse_wal_values_result.length != 2) { throw `Got length ${parse_wal_values_result.length} expected 2.......parseWalValues āŒ`; } - if (parse_wal_values_result[1].value != 1753923700307) { - throw `Got value ${parse_wal_values_result[1].value} expected 1753923700307.......parseWalValues āŒ`; + if (parse_wal_values_result[ 1 ].value != 1753923700307) { + throw `Got value ${parse_wal_values_result[ 1 ].value} expected 1753923700307.......parseWalValues āŒ`; } console.info(` Function parseWalValues āœ…`); @@ -635,8 +637,8 @@ export function testLevelWal(): void { if (parse_wal_result.length != 7) { throw `Got length ${parse_wal_result.length} expected 7.......parseWal āŒ`; } - if (parse_wal_result[1].value !== "0aAFtxy5hqMZ-m5_84cwxsP9wDeMSWgnZIZV8HYeffZdqJJZVdLX0yDE4UmHJ-F18zr6wVg952cpmadDgN3LcJ7Bbac7IopaVc8pplhgtVdTuVXI4aig") { - throw `Got ${parse_wal_result[1].value} expected 0aAFtxy5hqMZ-m5_84cwxsP9wDeMSWgnZIZV8HYeffZdqJJZVdLX0yDE4UmHJ-F18zr6wVg952cpmadDgN3LcJ7Bbac7IopaVc8pplhgtVdTuVXI4aig.......parseWal āŒ`; + if (parse_wal_result[ 1 ].value !== "0aAFtxy5hqMZ-m5_84cwxsP9wDeMSWgnZIZV8HYeffZdqJJZVdLX0yDE4UmHJ-F18zr6wVg952cpmadDgN3LcJ7Bbac7IopaVc8pplhgtVdTuVXI4aig") { + throw `Got ${parse_wal_result[ 1 ].value} expected 0aAFtxy5hqMZ-m5_84cwxsP9wDeMSWgnZIZV8HYeffZdqJJZVdLX0yDE4UmHJ-F18zr6wVg952cpmadDgN3LcJ7Bbac7IopaVc8pplhgtVdTuVXI4aig.......parseWal āŒ`; } console.info(` Function parseWal āœ…`); @@ -648,8 +650,8 @@ export function testLevelWal(): void { if (parse_manifest_result.length != 1) { throw `Got manifest length ${parse_manifest_result.length} expected 1.......parseWalManifest āŒ`; } - if (!JSON.stringify(parse_manifest_result[0].records[0]).includes("Comparator")) { - throw `Got ${JSON.stringify(parse_manifest_result[0].records[0])} and does not include Comparator.......parseWalManifest āŒ`; + if (!JSON.stringify(parse_manifest_result[ 0 ].records[ 0 ]).includes("Comparator")) { + throw `Got ${JSON.stringify(parse_manifest_result[ 0 ].records[ 0 ])} and does not include Comparator.......parseWalManifest āŒ`; } console.info(` Function parseWalManifest āœ…`); } \ No newline at end of file diff --git a/src/applications/libreoffice.ts b/src/applications/libreoffice.ts index d2eafae7..cf9776f1 100644 --- a/src/applications/libreoffice.ts +++ b/src/applications/libreoffice.ts @@ -116,6 +116,11 @@ export function recentFiles( readonly: false, thumbnail: "", source: path.full_path, + message: path_data[ "oor:name" ], + timestamp_desc: "N/A", + artifact: "LibreOffice Recent Files", + data_type: "application:libreoffice:recentfiles:entry", + datetime: "1970-01-01T00:00:00Z" }; // Finally at section containing data of interest @@ -163,13 +168,16 @@ export function testRecentFiles(): void { throw result; } - if (result[ 0 ] === undefined) { + if (result[ 0 ]?.title === undefined) { throw `Got title undefined expected Hindsight Report (2025-09-18T00-18-20).......recentFiles āŒ`; } if (result[ 0 ].title != "Hindsight Report (2025-09-18T00-18-20)") { throw `Got title ${result[ 0 ].title} expected Hindsight Report (2025-09-18T00-18-20).......recentFiles āŒ`; } + if (result[ 0 ].message != "file:///home/test/Downloads/Hindsight%20Report%20(2025-09-18T00-18-20).xlsx") { + throw `Got message ${result[ 0 ].message} expected "file:///home/test/Downloads/Hindsight%20Report%20(2025-09-18T00-18-20).xlsx").......recentFiles āŒ`; + } console.info(` Function recentFiles āœ…`); } \ No newline at end of file diff --git a/src/applications/nextcloud/cloud.ts b/src/applications/nextcloud/cloud.ts index 4ef07a5e..7fa30b63 100644 --- a/src/applications/nextcloud/cloud.ts +++ b/src/applications/nextcloud/cloud.ts @@ -11,7 +11,7 @@ import { nextcloudActivityLogs } from "./logs/activity"; import { nextcloudSyncLogs } from "./logs/sync"; /** - * Class to extract Nextcloud client information + * Class to extract NextCloud client information */ export class NextcloudClient { private paths: NextcloudClientUsers[] = []; @@ -27,7 +27,7 @@ export class NextcloudClient { this.platform = platform; if (alt_path === undefined) { - const results = this.profiles(platform); + const results = this.profiles(); if (results instanceof ApplicationError) { return; } @@ -46,12 +46,11 @@ export class NextcloudClient { /** * Get base path for all Nextcloud clients data - * @param platform OS `PlatformType` * @returns Array of `NextcloudClientUsers` or `ApplicationError` */ - private profiles(platform: PlatformType): NextcloudClientUsers[] | ApplicationError { + private profiles(): NextcloudClientUsers[] | ApplicationError { let paths: GlobInfo[] = []; - switch (platform) { + switch (this.platform) { case PlatformType.Linux: { const linux_paths = glob("/home/*/.config/Nextcloud"); if (linux_paths instanceof FileError) { diff --git a/src/applications/nextcloud/logs/activity.ts b/src/applications/nextcloud/logs/activity.ts index 93d83b0f..ceb9818f 100644 --- a/src/applications/nextcloud/logs/activity.ts +++ b/src/applications/nextcloud/logs/activity.ts @@ -42,13 +42,13 @@ export function nextcloudActivityLogs(text: string, log_source: string): Nextclo log.category = (values.at(0) ?? "").trim(); log.function = (values.at(1) ?? "").trim(); - let source = (values.at(2) ?? ""); + const source = (values.at(2) ?? ""); if (source === "") { continue; } log.source_file = source.split(":").at(0) ?? ""; - log.source_file_line = Number(source.split(":").at(1)) ?? 0; + log.source_file_line = Number(source.split(":").at(1)); log.message = values.slice(3).join(" ").replace("]:", "").trim(); logs.push(log); diff --git a/src/applications/onedrive/config.ts b/src/applications/onedrive/config.ts new file mode 100644 index 00000000..7dd68fe9 --- /dev/null +++ b/src/applications/onedrive/config.ts @@ -0,0 +1,111 @@ +import { getPlist, getRegistry } from "../../../mod"; +import { OneDriveAccount } from "../../../types/applications/onedrive"; +import { MacosError } from "../../macos/errors"; +import { unixEpochToISO } from "../../time/conversion"; +import { WindowsError } from "../../windows/errors"; +import { ApplicationError } from "../errors"; + +/** + * Function to extract Account details associated with OneDrive + * @param path Path to NTUSER.DAT file + * @returns Array of `OneDriveAccount` + */ +export function accountWindows(path: string): OneDriveAccount[] | ApplicationError { + const accounts: OneDriveAccount[] = []; + const values = getRegistry(path, "\\\\software\\\\microsoft\\\\onedrive\\\\accounts"); + if (values instanceof WindowsError) { + return new ApplicationError(`ONEDRIVE`, `Failed to parse ${path}: ${values.message}`); + } + + + for (const reg of values) { + if (reg.values.length === 0) { + continue; + } + // Lazy check to see if UserEmail key found in Registry Key value names + if (!JSON.stringify(reg.values).includes("UserEmail")) { + continue; + } + + const account: OneDriveAccount = { + email: "", + device_id: "", + account_id: "", + last_signin: "", + cid: "", + message: "", + datetime: "", + timestamp_desc: "OneDrive Last Signin", + artifact: "OneDrive Account Info", + data_type: "applications:onedrive:account:entry" + }; + for (const value of reg.values) { + switch (value.value) { + case "UserEmail": + account.email = value.data; + account.message = `Last signin by ${account.email}`; + break; + case "cid": + account.cid = value.data; + break; + case "LastSignInTime": + account.last_signin = unixEpochToISO(Number(value.data)); + account.datetime = account.last_signin; + break; + case "OneDriveDeviceId": + account.device_id = value.data; + break; + case "OneAuthAccountId": + account.account_id = value.data; + break; + } + } + accounts.push(account); + + } + + return accounts; +} + +/** + * Function to extract Account details associated with OneDrive + * @param path Path to OneDriveStandaloneSuite.plist plist file + * @returns Array of `OneDriveAccount` + */ +export function accountMacos(path: string): OneDriveAccount[] | ApplicationError { + const accounts: OneDriveAccount[] = []; + const values = getPlist(path); + if (values instanceof MacosError) { + return new ApplicationError(`ONEDRIVE`, `Failed to parse ${path}: ${values.message}`); + + } + + if (Array.isArray(values) || values instanceof Uint8Array) { + return new ApplicationError(`ONEDRIVE`, `Unexpected PLIST type. Wanted HashMap. Got array`); + } + + for (const key in values) { + // Lazy check if the plist data contains the data we want + if (!JSON.stringify(values[key]).includes("UserEmail")) { + continue; + } + const account_value = values[key] as Record; + + const account: OneDriveAccount = { + email: account_value["UserEmail"] as string | undefined ?? "", + device_id: account_value["OneDriveDeviceId"] as string | undefined ?? "", + account_id: account_value["OneAuthAccountId"] as string | undefined ?? "", + last_signin: "1970-01-01T00:00:00.000Z", + cid: account_value["cid"] as string | undefined ?? "", + message: account_value["UserEmail"] as string | undefined ?? "", + datetime: "1970-01-01T00:00:00.000Z", + timestamp_desc: "OneDrive Last Signin", + artifact: "OneDrive Account Info", + data_type: "applications:onedrive:account:entry" + }; + accounts.push(account); + } + + + return accounts; +} \ No newline at end of file diff --git a/src/applications/onedrive/odl.ts b/src/applications/onedrive/odl.ts index 86acfd4a..3ba275c9 100644 --- a/src/applications/onedrive/odl.ts +++ b/src/applications/onedrive/odl.ts @@ -1,8 +1,10 @@ +import { readFile } from "../../../mod"; import { OneDriveLog } from "../../../types/applications/onedrive"; import { decompress_gzip } from "../../compression/decompress"; import { CompressionError } from "../../compression/errors"; import { encode } from "../../encoding/base64"; import { extractUtf8String } from "../../encoding/strings"; +import { FileError } from "../../filesystem/errors"; import { NomError } from "../../nom/error"; import { Endian, @@ -17,7 +19,33 @@ import { import { unixEpochToISO } from "../../time/conversion"; import { ApplicationError } from "../errors"; -export function parseOdl( + +/** + * Function to read and parse OneDrive Log files + * @param paths Array of `GlobInfo` to OneDrive Log files (odl) + * @returns Array of `OneDriveLog` entries + */ +export function readOdlFiles(path: string): OneDriveLog[] | ApplicationError { + const data = readFile(path); + if (data instanceof FileError) { + return new ApplicationError(`ONEDRIVE`, `could not read log ${path}: ${data.message}`); + } + let filename = ""; + if (path.includes("\\")) { + filename = path.split("\\").pop() ?? ""; + } else { + filename = path.split("/").pop() ?? ""; + } + + const logs = parseOdl(data, path, filename); + if (logs instanceof ApplicationError) { + return new ApplicationError(`ONEDRIVE`, `Failed to parse ${path}: ${logs.message}`); + + } + return logs; +} + +function parseOdl( data: Uint8Array, path: string, filename: string, @@ -81,7 +109,7 @@ export function parseOdl( ); } - const gzip_key = [ 31, 139, 8, 0 ]; + const gzip_key = [31, 139, 8, 0]; if ( Array.from(compressed_data.remaining.slice(0, 4) as Uint8Array) .toString() === gzip_key.toString() @@ -207,6 +235,7 @@ function odl_entry( } entry.created = unixEpochToISO(timestamp.value); + entry.datetime = entry.created; entry.version = version; entry.os_version = os_version; entry.filename = filename; @@ -313,6 +342,11 @@ function parseData( version: "", os_version: "", description, + message: `${code_file}: ${function_value}`, + datetime: "", + timestamp_desc: "OneDrive Log Entry Created", + artifact: "OneDrive Log", + data_type: "applications:onedrive:logs:entry" }; return entry; @@ -392,3 +426,89 @@ function parseDescription( remaining, }; } + +/** + * Function to test the OneDrive ODL file parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the OneDrive ODL parsing + */ +export function testReadOdlFiles(): void { + const test = "../../tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.2.odlgz"; + let results = readOdlFiles(test); + if (results instanceof ApplicationError) { + throw results; + } + + if (results.length !== 4910) { + throw `Got "${results.length}" expected 4910.......readOdlFiles āŒ` + } + + if (results[23]?.message !== "LoggingAPI.cpp: LoggingSetCommonDatapoint") { + throw `Got '${results[23]?.message}' expected "LoggingAPI.cpp: LoggingSetCommonDatapoint".......readOdlFiles āŒ` + } + + console.info(` Function readOdlFiles āœ…`); + + const data = readFile(test); + if (data instanceof FileError) { + throw data; + } + + results = parseOdl(data, "anything", "i want"); + if (results instanceof ApplicationError) { + throw results; + } + + if (results.length !== 4910) { + throw `Got "${results.length}" expected 4910.......parseOdl āŒ` + } + + if (results[83]?.message !== "BaseHost.cpp: BaseHost::Initialize") { + throw `Got '${results[83]?.message}' expected "BaseHost.cpp: BaseHost::Initialize".......parseOdl āŒ` + } + + console.info(` Function parseOdl āœ…`); + + const decom_test = "../../tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/decom_data.raw"; + const decom_data = readFile(decom_test); + if (decom_data instanceof FileError) { + throw data; + } + + results = odl_entry(decom_data, "anything", "i want", "totally real path", "super file"); + if (results instanceof ApplicationError) { + throw results; + } + + if (results[390]?.datetime !== "2024-09-23T13:48:25.571Z") { + throw `Got '${results[390]?.datetime}' expected "2024-09-23T13:48:25.571Z".......odl_entry āŒ` + } + console.info(` Function odl_entry āœ…`); + + + let desc_data = [190, 3, 59, 127, 95, 139, 9, 68, 159, 205, 101, 6, 103, 167, 150, 69, 224, 251, 193, 2, 1, 0, 0, 0, 14, 0, 0, 0, 76, 111, 103, 103, 105, 110, 103, 65, 80, 73, 46, 99, 112, 112, 36, 6, 0, 0, 30, 0, 0, 0, 85, 112, 100, 97, 116, 101, 79, 98, 102, 117, 115, 99, 97, 116, 105, 111, 110, 69, 110, 99, 114, 121, 112, 116, 105, 111, 110, 75, 101, 121, 14, 0, 0, 0, 76, 111, 103, 79, 98, 102, 117, 115, 99, 97, 116, 105, 111, 110, 22, 0, 0, 0, 82, 101, 116, 114, 105, 101, 118, 101, 79, 98, 102, 117, 115, 99, 97, 116, 105, 111, 110, 75, 101, 121, 7, 0, 0, 0, 83, 117, 99, 99, 101, 115, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + const entry = parseData(new Uint8Array(desc_data), 0); + if (entry instanceof ApplicationError) { + throw entry; + } + + if (entry.code_file !== "LoggingAPI.cpp") { + throw `Got '${entry.code_file}' expected "LoggingAPI.cpp".......parseData āŒ` + } + if (entry.params !== "DgAAAExvZ09iZnVzY2F0aW9uFgAAAFJldHJpZXZlT2JmdXNjYXRpb25LZXkHAAAAU3VjY2VzcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") { + throw `Got '${entry.params}' expected "DgAAAExvZ09iZnVzY2F0aW9uFgAAAFJldHJpZXZlT2JmdXNjYXRpb25LZXkHAAAAU3VjY2VzcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==".......parseData āŒ` + } + console.info(` Function parseData āœ…`); + + + desc_data = [1, 37, 0, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 105, 110, 103, 32, 79, 110, 101, 68, 114, 105, 118, 101, 32, 110, 97, 109, 101, 115, 112, 97, 99, 101, 32, 114, 111, 111, 116, 15, 115, 110, 97, 109, 101, 115, 112, 97, 99, 101, 82, 111, 111, 116, 73, 100, 21, 0, 0, 0, 78, 97, 109, 101, 115, 112, 97, 99, 101, 82, 111, 111, 116, 85, 116, 105, 108, 46, 99, 112, 112, 87, 1, 0, 0, 50, 0, 0, 0, 78, 97, 109, 101, 115, 112, 97, 99, 101, 82, 111, 111, 116, 85, 116, 105, 108, 58, 58, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 79, 110, 101, 68, 114, 105, 118, 101, 78, 97, 109, 101, 115, 112, 97, 99, 101, 82, 111, 111, 116, 38, 0, 0, 0, 123, 48, 49, 56, 68, 53, 67, 54, 54, 45, 52, 53, 51, 51, 45, 52, 51, 48, 55, 45, 57, 66, 53, 51, 45, 50, 50, 52, 68, 69, 50, 69, 68, 49, 70, 69, 54, 125]; + const desc = parseDescription(new Uint8Array(desc_data)); + if (desc instanceof ApplicationError) { + throw desc; + } + + if (desc.desc !== "Unregistering OneDrive namespace root: namespaceRootId;") { + throw `Got '${desc.desc}' expected "Unregistering OneDrive namespace root: namespaceRootId;".......parseDescription āŒ` + } + console.info(` Function parseDescription āœ…`); +} \ No newline at end of file diff --git a/src/applications/onedrive/onedrive.ts b/src/applications/onedrive/onedrive.ts new file mode 100644 index 00000000..b062bdf2 --- /dev/null +++ b/src/applications/onedrive/onedrive.ts @@ -0,0 +1,450 @@ +import { dumpData, glob, Output, outputResults, platform, PlatformType, readTextFile } from "../../../mod"; +import { KeyInfo, OneDriveAccount, OneDriveLog, OnedriveProfile, OneDriveSyncEngineRecord } from "../../../types/applications/onedrive"; +import { getEnvValue } from "../../environment/mod"; +import { FileError } from "../../filesystem/errors"; +import { ApplicationError } from "../errors"; +import { accountMacos, accountWindows } from "./config"; +import { readOdlFiles } from "./odl"; +import { extractSyncEngine } from "./sqlite"; + +/** + * Class to parse OneDrive artifacts + */ +export class OneDrive { + private platform: PlatformType; + private user = ""; + private profiles: OnedriveProfile[] = []; + + /** + * Construct an `OneDrive` object that can parse all OneDrive supported artifacts for all users + * @param platform OS `PlatformType` + * @param [user="*"] Optional specific user to parse OneDrive info. Default is all users + * @param alt_path Optional directory that contains *all* OneDrive related artifact files + */ + constructor (platform: PlatformType.Darwin | PlatformType.Windows, user = "*", alt_path?: string) { + this.platform = platform; + this.user = user; + + if (alt_path !== undefined) { + let separator = "/"; + let config = "*.OneDriveStandaloneSuite.plist"; + if (this.platform === PlatformType.Windows) { + separator = "\\"; + config = "NTUSER.DAT"; + } + + const profile: OnedriveProfile = { + sync_db: this.getFiles(`${alt_path}${separator}SyncEngineDatabase.db`), + odl_files: this.getFiles(`${alt_path}${separator}*odl*`), + key_file: this.getFiles(`${alt_path}${separator}general.keystore`), + config_file: this.getFiles(`${alt_path}${separator}${config}`), + }; + this.profiles.push(profile); + return; + } + this.setupProfiles(); + } + + /** + * View all artifacts the `OneDrive` object found related to OneDrive + * @returns Array of `OnedriveProfile` + */ + public oneDriveProfiles(): OnedriveProfile[] { + return this.profiles; + } + + /** + * Function to parse OneDrive key files. By default all keys are parsed based on how the `OneDrive` class was initialized + * By default all key entries are returned. You may provide an optional `Output` object to instead output the results to a file + * If results are outputted to a file. An empty array is returned + * @param files Optional array of specific keys files to parse + * @param output Optional `Output` object to output results instead of returning them to the caller + * @param [metadata_runtime=false] Append runtime metadata to the output. Default is false. Only applicable if the Output.Format is JSON or JSONL + * @returns Array of `KeyInfo` + */ + public oneDriveKeys(files?: string[], output?: Output, metadata_runtime = false): KeyInfo[] { + const keys: KeyInfo[] = []; + // If we only want to parse a subset of keys + if (files !== undefined) { + for (const entry of files) { + const key: KeyInfo = { + path: entry, + key: "", + }; + const data = readTextFile(entry); + if (data instanceof FileError) { + console.warn(`failed to read file ${entry}: ${data.message}`); + continue; + } + + const values = JSON.parse(data) as Record[]; + for (const value of values) { + key.key = value[ "Key" ] as string; + break; + } + keys.push(key); + } + if (output !== undefined) { + if (metadata_runtime) { + outputResults(keys, "onedrive_keys", output); + } else { + dumpData(keys, "onedrive_keys", output); + } + return []; + } + return keys; + } + + // Parse all keys + for (const profile of this.profiles) { + for (const entry of profile.key_file) { + const key: KeyInfo = { + path: entry, + key: "", + }; + const data = readTextFile(entry); + if (data instanceof FileError) { + console.warn(`failed to read file ${entry}: ${data.message}`); + continue; + } + + const values = JSON.parse(data) as Record[]; + for (const value of values) { + key.key = value[ "Key" ] as string; + break; + } + keys.push(key); + } + if (output !== undefined) { + if (metadata_runtime) { + outputResults(keys, "onedrive_keys", output); + } else { + dumpData(keys, "onedrive_keys", output); + } + return []; + } + } + return keys; + } + + /** + * Function to parse OneDrive Log (ODL) files. By default all logs are parsed based on how the `OneDrive` class was initialized + * By default all log entries are returned. You may provide an optional `Output` object to instead output the results to a file + * If results are outputted to a file. An empty array is returned + * @param files Optional array of specific ODL files to parse + * @param output Optional `Output` object to output results instead of returning them to the caller + * @param [metadata_runtime=false] Append runtime metadata to the output. Default is false. Only applicable if the Output.Format is JSON or JSONL + * @returns Array of `OneDriveLog` + */ + public oneDriveLogs(files?: string[], output?: Output, metadata_runtime = false): OneDriveLog[] { + let logs: OneDriveLog[] = []; + // Check if we only want to parse a subset of logs + if (files !== undefined) { + for (const entry of files) { + const values = readOdlFiles(entry); + if (values instanceof ApplicationError) { + console.error(`${values}`); + continue; + } + if (output !== undefined) { + if (metadata_runtime) { + outputResults(values, "onedrive_odl_logs", output); + } else { + dumpData(values, "onedrive_odl_logs", output); + } + continue; + } + logs = logs.concat(values); + } + return logs; + } + + // Parse all logs + for (const profile of this.profiles) { + for (const entry of profile.odl_files) { + const values = readOdlFiles(entry); + if (values instanceof ApplicationError) { + console.error(`${values}`); + continue; + } + if (output !== undefined) { + if (metadata_runtime) { + outputResults(values, "onedrive_odl_logs", output); + } else { + dumpData(values, "onedrive_odl_logs", output); + } + continue; + } + logs = logs.concat(values); + } + } + return logs; + } + + /** + * Function to parse OneDrive Account info. By default all accounts are parsed based on how the `OneDrive` class was initialized + * By default all account entries are returned. You may provide an optional `Output` object to instead output the results to a file + * If results are outputted to a file. An empty array is returned + * @param files Optional array of specific account configs files to parse. Windows will be NTUSER.DAT. macOS will be plist files + * @param output Optional `Output` object to output results instead of returning them to the caller + * @param [metadata_runtime=false] Append runtime metadata to the output. Default is false. Only applicable if the Output.Format is JSON or JSONL + * @returns Array of `OneDriveAccount` + */ + public oneDriveAccounts(files?: string[], output?: Output, metadata_runtime = false): OneDriveAccount[] { + let configs: OneDriveAccount[] = []; + // Check if we only want to parse a subset of accounts + if (files !== undefined) { + for (const entry of files) { + const values = this.platform === PlatformType.Windows ? accountWindows(entry) : accountMacos(entry); + if (values instanceof ApplicationError) { + console.error(`${values}`); + continue; + } + if (output !== undefined) { + if (metadata_runtime) { + outputResults(values, "onedrive_accounts", output); + } else { + dumpData(values, "onedrive_accounts", output); + } + continue; + } + configs = configs.concat(values); + } + return configs; + } + + // Parse all configs + for (const profile of this.profiles) { + for (const entry of profile.config_file) { + const values = this.platform === PlatformType.Windows ? accountWindows(entry) : accountMacos(entry); + if (values instanceof ApplicationError) { + console.error(`${values}`); + continue; + } + if (output !== undefined) { + if (metadata_runtime) { + outputResults(values, "onedrive_accounts", output); + } else { + dumpData(values, "onedrive_accounts", output); + } + continue; + } + configs = configs.concat(values); + } + } + return configs; + } + + /** + * Function to parse OneDrive Sync databases. By default all databases are parsed based on how the `OneDrive` class was initialized + * By default all database entries are returned. You may provide an optional `Output` object to instead output the results to a file + * If results are outputted to a file. An empty array is returned + * @param files Optional array of specific db files to query + * @param output Optional `Output` object to output results instead of returning them to the caller + * @param [metadata_runtime=false] Append runtime metadata to the output. Default is false. Only applicable if the Output.Format is JSON or JSONL + * @returns Array of `OneDriveSyncEngineRecord` + */ + public oneDriveSyncDatabase(files?: string[], output?: Output, metadata_runtime = false): OneDriveSyncEngineRecord[] { + let db: OneDriveSyncEngineRecord[] = []; + // Check if we only want to parse a specific database + if (files !== undefined) { + for (const entry of files) { + const values = extractSyncEngine(entry); + if (values instanceof ApplicationError) { + console.error(`${values}`); + continue; + } + if (output !== undefined) { + if (metadata_runtime) { + outputResults(values, "onedrive_syncdb", output); + } else { + dumpData(values, "onedrive_syncdb", output); + } + continue; + } + db = db.concat(values); + } + return db; + } + + // Parse all databases + for (const profile of this.profiles) { + for (const entry of profile.sync_db) { + const values = extractSyncEngine(entry); + if (values instanceof ApplicationError) { + console.error(`${values}`); + continue; + } + if (output !== undefined) { + if (metadata_runtime) { + outputResults(values, "onedrive_syncdb", output); + } else { + dumpData(values, "onedrive_syncdb", output); + } + continue; + } + db = db.concat(values); + } + } + return db; + } + + /** + * Function that parses and timelines all OneDrive artifacts + * @param output `Object` object to output results + */ + public oneDriveRetrospect(output: Output): void { + this.oneDriveLogs(undefined, output); + this.oneDriveSyncDatabase(undefined, output); + this.oneDriveAccounts(undefined, output); + } + + /** + * Setup OneDrive paths for all users or specific user if provided + * @returns Nothing + */ + private setupProfiles(): void { + if (this.platform === PlatformType.Darwin) { + const base_users = `/Users/${this.user}`; + const all_users = glob(base_users); + if (all_users instanceof FileError) { + return; + } + + for (const user of all_users) { + const profile: OnedriveProfile = { + sync_db: [], + odl_files: [], + key_file: [], + config_file: [], + }; + const odl_glob = `${user.full_path}/Library/Logs/OneDrive/*/*odl*`; + profile.odl_files = this.getFiles(odl_glob); + + const sync_glob = `${user.full_path}/Library/Application Support/OneDrive/settings/*/SyncEngineDatabase.db`; + profile.sync_db = this.getFiles(sync_glob); + + const key_glob = `${user.full_path}/Library/Logs/OneDrive/*/general.keystore`; + profile.key_file = this.getFiles(key_glob); + + const config_glob = `${user.full_path}/Library/Group Containers/*.OneDriveStandaloneSuite/Library/Preferences/*.OneDriveStandaloneSuite.plist`; + profile.config_file = this.getFiles(config_glob); + + if (profile.config_file.length === 0 && + profile.key_file.length === 0 && + profile.odl_files.length === 0 && + profile.sync_db.length === 0) { + continue; + } + this.profiles.push(profile); + } + } + + let drive = getEnvValue("HOMEDRIVE"); + if (drive === "") { + drive = "C:"; + } + const base_users = `${drive}\\Users\\${this.user}`; + const all_users = glob(base_users); + if (all_users instanceof FileError) { + return; + } + + for (const user of all_users) { + const profile: OnedriveProfile = { + sync_db: [], + odl_files: [], + key_file: [], + config_file: [], + }; + + const odl_glob = `${user.full_path}\\AppData\\Local\\Microsoft\\OneDrive\\logs\\*\\*odl*`; + profile.odl_files = this.getFiles(odl_glob); + + const sync_glob = `${user.full_path}\\AppData\\Local\\Microsoft\\OneDrive\\settings\\*\\SyncEngineDatabase.db`; + profile.sync_db = this.getFiles(sync_glob); + + const key_glob = `${user.full_path}\\AppData\\Local\\Microsoft\\OneDrive\\logs\\*\\general.keystore`; + profile.key_file = this.getFiles(key_glob); + + const config_glob = `${user.full_path}\\NTUSER.*`; + + profile.config_file = this.getFiles(config_glob); + if (profile.key_file.length === 0 && + profile.odl_files.length === 0 && + profile.sync_db.length === 0) { + continue; + } + this.profiles.push(profile); + } + + + } + + /** + * Function to get file artifacts associated with OneDrive + * @param glob_string Glob string that points to files associated with OneDrive artifacts + * @returns Array of strings + */ + private getFiles(glob_string: string): string[] { + const files: string[] = []; + const glob_files = glob(glob_string); + if (glob_files instanceof FileError) { + return []; + } + + for (const entry of glob_files) { + if (entry.filename.toLowerCase().includes("ntuser.dat") && + !entry.filename.toLowerCase().endsWith("dat")) { + continue; + } + files.push(entry.full_path); + } + + return files; + } +} + +/** + * Function to test the OneDrive class + * This function should not be called unless you are developing the artemis-api + * Or want to validate the OneDrive parsing + */ +export function testOneDrive(): void { + let test = "../../tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock"; + let plat = PlatformType.Windows; + if (platform().toLowerCase() === "darwin") { + plat = PlatformType.Darwin; + test = "../../../tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock"; + } + + const client = new OneDrive(plat, undefined, test); + + const status = client.oneDriveLogs(); + if (status.length !== 367) { + throw `Got '${status.length}' expected "367".......OneDrive āŒ`; + } + + const sync = client.oneDriveSyncDatabase(); + if (sync.length !== 43) { + throw `Got '${sync.length}' expected "43".......OneDrive āŒ`; + } + + const account = client.oneDriveAccounts(); + if (account.length !== 0 && plat === PlatformType.Windows) { + throw `Got '${account.length}' expected "0".......OneDrive āŒ`; + } else if (account.length !== 1 && plat === PlatformType.Darwin) { + throw `Got '${account.length}' expected "1".......OneDrive āŒ`; + } + + if (plat === PlatformType.Darwin && account[ 0 ]?.account_id !== "aaaaaaaaa") { + throw `Got '${account[ 0 ]?.account_id}' expected "aaaaaaaaa".......OneDrive āŒ`; + } + + const key = client.oneDriveKeys(); + if (key.length !== 1) { + throw `Got '${key.length}' expected "1"......OneDrive āŒ`; + } + + console.info(` Mock OneDrive Class āœ…`); +} \ No newline at end of file diff --git a/src/applications/onedrive/parser.ts b/src/applications/onedrive/parser.ts deleted file mode 100644 index fbc0eae6..00000000 --- a/src/applications/onedrive/parser.ts +++ /dev/null @@ -1,303 +0,0 @@ -import { PlatformType } from "../../../mod"; -import { - KeyInfo, - OneDriveDetails, -} from "../../../types/applications/onedrive"; -import { - OneDriveAccount, - OneDriveLog, - OneDriveSyncEngineRecord, -} from "../../../types/applications/onedrive"; -import { GlobInfo } from "../../../types/filesystem/globs"; -import { getEnvValue } from "../../environment/mod"; -import { FileError } from "../../filesystem/errors"; -import { readFile, readTextFile } from "../../filesystem/files"; -import { glob } from "../../filesystem/files"; -import { MacosError } from "../../macos/errors"; -import { getPlist } from "../../macos/plist"; -import { unixEpochToISO } from "../../time/conversion"; -import { WindowsError } from "../../windows/errors"; -import { getRegistry } from "../../windows/registry"; -import { ApplicationError } from "../errors"; -import { parseOdl } from "./odl"; -import { extractSyncEngine } from "./sqlite"; - -/** - * Function to parse OneDrive artifacts - * @param platform PlatformType enum - * @param alt_path Optional alternative directory containing OneDrive files. **Must include trailing slash** - * @param [user="*"] Optional user to parse OneDrive info. By default artemis will try to parse all users - * @returns - */ -export function onedriveDetails( - platform: PlatformType.Darwin | PlatformType.Windows, - alt_path?: string, - user = "*", -): OneDriveDetails | ApplicationError { - let odl_files = ""; - let key_file = ""; - let sync_db = ""; - let reg_files = ""; - if (alt_path !== undefined) { - odl_files = `${alt_path}*.odl*`; - key_file = `${alt_path}general.keystore`; - sync_db = `${alt_path}SyncEngineDatabase.db`; - reg_files = `${alt_path}NTUSER.*`; - } - - if (platform === PlatformType.Darwin && alt_path === undefined) { - odl_files = `/Users/${user}/Library/Logs/OneDrive/*/*odl*`; - key_file = `/Users/${user}/Library/Logs/OneDrive/*/general.keystore`; - sync_db = - `/Users/${user}/Library/Application Support/OneDrive/settings/*/SyncEngineDatabase.db`; - reg_files = - `/Users/${user}/Library/Group Containers/*.OneDriveStandaloneSuite/Library/Preferences/*.OneDriveStandaloneSuite.plist`; - } else if (alt_path === undefined) { - const drive = getEnvValue("HOMEDRIVE"); - if (drive === "") { - return new ApplicationError(`ONEDRIVE`, `no HOMEDRIVE value`); - } - odl_files = - `${drive}\\Users\\${user}\\AppData\\Local\\Microsoft\\OneDrive\\logs\\*\\*odl*`; - key_file = - `${drive}\\Users\\${user}\\AppData\\Local\\Microsoft\\OneDrive\\logs\\*\\general.keystore`; - sync_db = - `${drive}\\Users\\${user}\\AppData\\Local\\Microsoft\\OneDrive\\settings\\*\\SyncEngineDatabase.db`; - reg_files = `${drive}\\Users\\${user}\\NTUSER.*`; - } - - const details: OneDriveDetails = { - logs: [], - files: [], - accounts: [], - keys: [], - }; - - const paths = glob(odl_files); - if (paths instanceof FileError) { - return new ApplicationError( - `ONEDRIVE`, - `failed to glob path ${odl_files}`, - ); - } - - const log_entries = readOdlFiles(paths); - details.logs = log_entries; - - const dbs = glob(sync_db); - if (dbs instanceof FileError) { - return new ApplicationError( - `ONEDRIVE`, - `failed to glob path ${sync_db}`, - ); - } - const db_records = querySqlite(dbs); - details.files = db_records; - - const key_paths = glob(key_file); - if (key_paths instanceof FileError) { - return new ApplicationError( - `ONEDRIVE`, - `failed to glob path ${key_paths}`, - ); - } - const keys = extractKeys(key_paths); - details.keys = keys; - - const reg_paths = glob(reg_files); - if (reg_paths instanceof FileError) { - return new ApplicationError( - `ONEDRIVE`, - `failed to glob path ${reg_paths}`, - ); - } - - if (platform === PlatformType.Windows) { - const accounts = accountWindows(reg_paths); - details.accounts = accounts; - } else if (platform === PlatformType.Darwin) { - const accounts = accountMacos(reg_paths); - details.accounts = accounts; - } - - return details; -} - -/** - * Function to read and parse OneDrive Log files - * @param paths Array of `GlobInfo` to OneDrive Log files (odl) - * @returns Array of `OneDriveLog` entries - */ -export function readOdlFiles(paths: GlobInfo[]): OneDriveLog[] { - let drive_logs: OneDriveLog[] = []; - for (const entry of paths) { - const data = readFile(entry.full_path); - if (data instanceof FileError) { - console.warn( - `Failed to read file ${entry.full_path}: ${data.message}`, - ); - continue; - } - - const logs = parseOdl(data, entry.full_path, entry.filename); - if (logs instanceof ApplicationError) { - console.warn( - `Failed to parse ${entry.full_path}: ${logs.message}`, - ); - continue; - } - drive_logs = drive_logs.concat(logs); - } - - return drive_logs; -} - -/** - * Function to query the SyncEngineDatabase - * @param paths Array of `GlobInfo` to SyncEngineDatabase - * @returns Array of `OneDriveSyncEngineRecord` entries - */ -function querySqlite(paths: GlobInfo[]): OneDriveSyncEngineRecord[] { - let db_records: OneDriveSyncEngineRecord[] = []; - for (const entry of paths) { - const records = extractSyncEngine(entry.full_path); - if (records instanceof ApplicationError) { - console.warn( - `Failed to parse ${entry.full_path}: ${records.message}`, - ); - continue; - } - db_records = db_records.concat(records); - } - - return db_records; -} - -/** - * Function to get the decryption keys - * @param paths Array of `GlobInfo` to general.keystore - * @returns Array of keys - */ -function extractKeys(paths: GlobInfo[]): KeyInfo[] { - const keys: KeyInfo[] = []; - for (const entry of paths) { - const key: KeyInfo = { - path: entry.full_path, - key: "", - }; - const data = readTextFile(entry.full_path); - if (data instanceof FileError) { - console.warn(`failed to read file ${entry.full_path}: ${data.message}`); - continue; - } - - const values = JSON.parse(data) as Record[]; - for (const value of values) { - key.key = value["Key"] as string; - break; - } - keys.push(key); - } - - return keys; -} - -/** - * Function to extract Account details associated with OneDrive - * @param paths Array of `GlobInfo` to NTUSER.DAT Registry files - * @returns Array of `OneDriveAccount` - */ -function accountWindows(paths: GlobInfo[]): OneDriveAccount[] { - const accounts: OneDriveAccount[] = []; - for (const entry of paths) { - if (!entry.filename.toLowerCase().endsWith("dat")) { - continue; - } - const values = getRegistry(entry.full_path); - if (values instanceof WindowsError) { - console.warn(`could not parse ${entry.full_path}: ${values.message}`); - continue; - } - - for (const reg of values) { - if ( - reg.path.includes("\\Software\\Microsoft\\OneDrive\\Accounts") && - reg.values.length !== 0 - ) { - // Lazy check to see if UserEmail key found in Registry Key value names - if (!JSON.stringify(reg.values).includes("UserEmail")) { - continue; - } - - const account: OneDriveAccount = { - email: "", - device_id: "", - account_id: "", - last_signin: "", - cid: "", - }; - for (const value of reg.values) { - switch (value.value) { - case "UserEmail": - account.email = value.data; - break; - case "cid": - account.cid = value.data; - break; - case "LastSignInTime": - account.last_signin = unixEpochToISO(Number(value.data)); - break; - case "OneDriveDeviceId": - account.device_id = value.data; - break; - case "OneAuthAccountId": - account.account_id = value.data; - break; - } - } - accounts.push(account); - } - } - } - return accounts; -} - -/** - * Function to extract Account details associated with OneDrive - * @param paths Array of `GlobInfo` to OneDriveStandaloneSuite.plist plist files - * @returns Array of `OneDriveAccount` - */ -function accountMacos(paths: GlobInfo[]): OneDriveAccount[] { - const accounts: OneDriveAccount[] = []; - for (const entry of paths) { - const values = getPlist(entry.full_path); - if (values instanceof MacosError) { - console.warn(`could not parse ${entry.full_path}: ${values.message}`); - continue; - } - - if (Array.isArray(values) || values instanceof Uint8Array) { - console.warn(`unexpected plist type`); - continue; - } - - for (const key in values) { - // Lazy check if the plist data contains the data we want - if (!JSON.stringify(values[key]).includes("UserEmail")) { - continue; - } - const account_value = values[key] as Record; - - const account: OneDriveAccount = { - email: account_value["UserEmail"] as string, - device_id: account_value["OneDriveDeviceId"] as string, - account_id: account_value["OneAutoAccountId"] as string, - last_signin: "1970-01-01T00:00:00.000Z", - cid: account_value["cid"] as string, - }; - accounts.push(account); - } - } - - return accounts; -} diff --git a/src/applications/onedrive/sqlite.ts b/src/applications/onedrive/sqlite.ts index 1a12e71a..74c57be0 100644 --- a/src/applications/onedrive/sqlite.ts +++ b/src/applications/onedrive/sqlite.ts @@ -33,6 +33,10 @@ export function extractSyncEngine( if (record.parent_resource_id === folder.resource_id) { record.path = `${folder.parents.join("/")}/${record.filename}`; record.directory = folder.parents.join("/"); + record.message = record.path; + if (record.message === "") { + record.message = record.filename; + } } } } @@ -78,41 +82,47 @@ function getRecords( const records: OneDriveSyncEngineRecord[] = []; for (const value of results) { const record: OneDriveSyncEngineRecord = { - parent_resource_id: value[ "parentResourceID" ] as string, - resource_id: value[ "resourceID" ] as string, - etag: value[ "eTag" ] as string, - filename: value[ "fileName" ] as string, + parent_resource_id: value["parentResourceID"] as string, + resource_id: value["resourceID"] as string, + etag: value["eTag"] as string, + filename: value["fileName"] as string, path: "", directory: "", - file_status: value[ "fileStatus" ] as number | null, - permissions: value[ "spoPermissions" ] as number | null, - volume_id: value[ "volumeID" ] as number | null, - item_index: value[ "itemIndex" ] as number | null, + file_status: value["fileStatus"] as number | null, + permissions: value["spoPermissions"] as number | null, + volume_id: value["volumeID"] as number | null, + item_index: value["itemIndex"] as number | null, last_change: "1970-01-01T00:00:00.000Z", - size: value[ "size" ] as number | null, + size: value["size"] as number | null, hash_digest: "", - shared_item: value[ "sharedItem" ] as string | null, + shared_item: value["sharedItem"] as string | null, media_date_taken: "", - media_width: value[ "mediaWidth" ] as number | null, - media_height: value[ "mediaHeight" ] as number | null, - media_duration: value[ "mediaDuration" ] as number | null, + media_width: value["mediaWidth"] as number | null, + media_height: value["mediaHeight"] as number | null, + media_duration: value["mediaDuration"] as number | null, graph_metadata: "", - created_by: "1970-01-01T00:00:00.000Z", - modified_by: "1970-01-01T00:00:00.000Z", + created_by: "", + modified_by: "", last_write_count: 0, db_path: path, + message: value["fileName"] as string, + datetime: "1970-01-01T00:00:00.000Z", + timestamp_desc: "OneDrive Sync Last Change", + artifact: "OneDrive Sync Record", + data_type: "applications:onedrive:sync:entry" }; - if (value[ "lastChange" ] !== null && value[ "lastChange" ] !== undefined) { - record.last_change = unixEpochToISO(value[ "lastChange" ] as number); + if (typeof value["lastChange"] === 'number') { + record.last_change = unixEpochToISO(value["lastChange"] as number); + record.datetime = record.last_change; } - if (value[ "mediaDateTaken" ] !== null && value[ "mediaDateTaken" ] !== undefined) { + if (typeof value["mediaDateTaken"] === 'number') { record.media_date_taken = unixEpochToISO( - value[ "mediaDateTaken" ] as number, + value["mediaDateTaken"] as number, ); } - if (value[ "localHashDigest" ] !== null && value[ "localHashDigest" ] !== undefined) { - const data = decode(value[ "localHashDigest" ] as string); + if (typeof value["localHashDigest"] === 'string') { + const data = decode(value["localHashDigest"] as string); if (!(data instanceof EncodingError)) { record.hash_digest = bytesToHexString(data); } @@ -145,15 +155,15 @@ function getFolders( const folders: OneDriveSyncEngineFolder[] = []; for (const value of results) { const folder: OneDriveSyncEngineFolder = { - parent_resource_id: value[ "parentResourceID" ] as string, - resource_id: value[ "resourceID" ] as string, - etag: value[ "eTag" ] as string, - parent_scope_id: value[ "parentScopeID" ] as string, - folder: value[ "folderName" ] as string, - folder_status: value[ "folderStatus" ] as number | null, - permissions: value[ "spoPermissions" ] as number | null, - volume_id: value[ "volumeID" ] as number | null, - item_index: value[ "itemIndex" ] as number | null, + parent_resource_id: value["parentResourceID"] as string, + resource_id: value["resourceID"] as string, + etag: value["eTag"] as string, + parent_scope_id: value["parentScopeID"] as string, + folder: value["folderName"] as string, + folder_status: value["folderStatus"] as number | null, + permissions: value["spoPermissions"] as number | null, + volume_id: value["volumeID"] as number | null, + item_index: value["itemIndex"] as number | null, parents: [], }; folders.push(folder); @@ -214,14 +224,101 @@ function getMeta(path: string): SyncMeta[] | ApplicationError { const values: SyncMeta[] = []; for (const value of results) { const meta: SyncMeta = { - created_by: value[ "createdBy" ] as string, - modified_by: value[ "modifiedBy" ] as string, - graph: value[ "graphMetadataJSON" ] as string, - count: value[ "lastWriteCount" ] as number, - id: value[ "resourceID" ] as string, + created_by: value["createdBy"] as string, + modified_by: value["modifiedBy"] as string, + graph: value["graphMetadataJSON"] as string, + count: value["lastWriteCount"] as number, + id: value["resourceID"] as string, }; values.push(meta); } return values; } + +/** + * Function to test the OneDrive Sync Database parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the OneDrive Sync Database parsing + */ +export function testExtractSyncEngine(): void { + const test = "../../tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SyncEngineDatabase.db"; + let results = extractSyncEngine(test); + if (results instanceof ApplicationError) { + throw results; + } + + if (results.length !== 43) { + throw `Got "${results.length}" expected 43.......extractSyncEngine āŒ` + } + + if (results[38]?.filename !== "4FDAA807B3CAB8D648CC3C82F11BB4B84D8ECF6E") { + throw `Got '${results[38]?.filename}' expected "4FDAA807B3CAB8D648CC3C82F11BB4B84D8ECF6E".......extractSyncEngine āŒ` + } + + console.info(` Function extractSyncEngine āœ…`); + + results = getRecords(test); + if (results instanceof ApplicationError) { + throw results; + } + + if (results.length !== 43) { + throw `Got "${results.length}" expected 43.......getRecords āŒ` + } + + if (results[3]?.filename !== "Capture.PNG") { + throw `Got '${results[3]?.filename}' expected "Capture.PNG".......extractSyncEngine āŒ` + } + + console.info(` Function getRecords āœ…`); + + const folders = getFolders(test); + if (folders instanceof ApplicationError) { + throw folders; + } + + if (folders.length !== 11) { + throw `Got "${folders.length}" expected 11.......getFolders āŒ` + } + + if (folders[3]?.folder !== "intro") { + throw `Got '${folders[3]?.folder}' expected "intro".......extractSyncEngine āŒ` + } + + console.info(` Function getFolders āœ…`); + + const parent: OneDriveSyncEngineFolder[] = [ + { + "parent_resource_id": "81b443a51d57432abea4457ec2023cfc", + "resource_id": "23814ecb0b784241bcec575edac5b493", + "etag": "\"{23814ECB-0B78-4241-BCEC-575EDAC5B493},37\"", + "parent_scope_id": "81b443a51d57432abea4457ec2023cfc", + "folder": "Personal Vault", + "folder_status": 7, + "permissions": 27, + "volume_id": null, + "item_index": null, + "parents": [] + } + ]; + const path = getParents("23814ecb0b784241bcec575edac5b493", parent); + if (path[0] !== "Personal Vault") { + throw `Got '${path[0]}' expected "Personal Vault".......getParents āŒ` + } + console.info(` Function getParents āœ…`); + + const meta = getMeta(test); + if (meta instanceof ApplicationError) { + throw meta; + } + + if (meta.length !== 43) { + throw `Got "${meta.length}" expected 43.......getMeta āŒ` + } + + if (meta[27]?.id !== "fd01a69c261520b9805bcd0100000000") { + throw `Got "${meta[27]?.id}" expected "fd01a69c261520b9805bcd0100000000".......getMeta āŒ` + } + console.info(` Function getMeta āœ…`); +} \ No newline at end of file diff --git a/src/applications/sqlite.ts b/src/applications/sqlite.ts index 4eaa99c2..408b1dfd 100644 --- a/src/applications/sqlite.ts +++ b/src/applications/sqlite.ts @@ -11,7 +11,7 @@ export function querySqlite( query: string, ): Record[] | ApplicationError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_query_sqlite(path, query); return data; diff --git a/src/applications/syncthing.ts b/src/applications/syncthing.ts new file mode 100644 index 00000000..e177d8ce --- /dev/null +++ b/src/applications/syncthing.ts @@ -0,0 +1,113 @@ +import { glob, readLines } from "../../mod"; +import { SyncthingClient, SyncthingLogs } from "../../types/applications/syncthing"; +import { GlobInfo } from "../../types/filesystem/globs"; +import { FileError } from "../filesystem/errors"; +import { PlatformType } from "../system/systeminfo"; +import { ApplicationError } from "./errors"; + +/** + * Class to extract Syncthing information + */ +export class Syncthing { + private paths: SyncthingClient[] = []; + private platform: PlatformType; + + /** + * Construct a `Syncthing` object that can be used to parse Syncthing logs + * @param platform OS `PlatformType`. Currently only Linux is supported + * @param alt_path Optional alternative path to Syncthing directory + * @returns `Syncthing` instance class + */ + constructor (platform: PlatformType.Linux, alt_path?: string) { + this.platform = platform; + if (alt_path === undefined) { + const results = this.profiles(); + if (results instanceof ApplicationError) { + return; + } + + this.paths = results; + return; + } + this.paths = [ { full_path: alt_path } ]; + + } + + /** + * Parse the plaintext Syncthing logs + * @returns Array of `SyncthingLogs` + */ + public logs(): SyncthingLogs[] { + const logs: SyncthingLogs[] = []; + for (const entry of this.paths) { + let path = `${entry.full_path}/syncthing.log`; + if (this.platform === PlatformType.Windows) { + path = `${entry.full_path}\\syncthing.log`; + } + + const limit = 1000; + let offset = 0; + while (true) { + const lines = readLines(path, offset, limit); + offset += limit; + if (lines instanceof FileError || lines.length === 0) { + break; + } + + for (const line of lines) { + const value = line.split(" "); + const message = value.slice(4).join(" "); + const log: SyncthingLogs = { + full_path: entry.full_path, + tag: (value[ 0 ] ?? "").replace("[", "").replace("]", ""), + datetime: `${(value[ 1 ] ?? "1970-01-01").replaceAll("/", "-")}T${value[ 2 ] ?? "00:00:00"}.000Z`, + timestamp_desc: "Syncthing Log Entry", + level: value[ 3 ] ?? "UNKNOWN", + message, + artifact: "Syncthing Log", + data_type: "application:syncthing:log:entry" + }; + logs.push(log); + } + } + } + return logs; + } + + /** + * Get base path for all Syncthing data + * @returns Array of `SyncthingClient` or `ApplicationError` + */ + private profiles(): SyncthingClient[] | ApplicationError { + let paths: GlobInfo[] = []; + switch (this.platform) { + case PlatformType.Linux: { + const linux_paths = glob("/home/*/.local/state/syncthing"); + if (linux_paths instanceof FileError) { + return new ApplicationError( + "SYNCTHING", + `failed to glob linux paths: ${linux_paths}`, + ); + } + paths = linux_paths; + break; + } + default: { + return []; + } + } + const clients: SyncthingClient[] = []; + for (const entry of paths) { + if (!entry.is_directory) { + continue; + } + + const profile: SyncthingClient = { + full_path: entry.full_path, + }; + + clients.push(profile); + } + return clients; + } +} \ No newline at end of file diff --git a/src/applications/vscode.ts b/src/applications/vscode.ts index 35ce09fc..f97134ab 100644 --- a/src/applications/vscode.ts +++ b/src/applications/vscode.ts @@ -1,4 +1,4 @@ -import { Extensions, FileHistory, RecentFiles, RecentType, VscodeStorage } from "../../types/applications/vscode"; +import { Entries, Extensions, FileHistory, RecentFiles, RecentType, VscodeStorage } from "../../types/applications/vscode"; import { encode } from "../encoding/base64"; import { encodeBytes } from "../encoding/bytes"; import { getEnvValue } from "../environment/env"; @@ -11,11 +11,13 @@ import { ApplicationError } from "./errors"; /** * Return the local file history for all VSCode files. Also supports VSCodium. * @param platform OS Platform type to lookup + * @param [include_content=false] Base64 the file history content. Default is false. If enabled expect that output to be very large * @param alt_glob Alternative glob path to `entries.json` * @returns Array of `FileHistory` entries or `ApplicationError` */ export function fileHistory( platform: PlatformType, + include_content = false, alt_glob?: string, ): FileHistory[] | ApplicationError { // Get all user paths @@ -65,42 +67,65 @@ export function fileHistory( // Parse JSON file into the FileHistory format const json_data: FileHistory = JSON.parse(string_data); json_data.history_path = path.full_path; + const file_entries = json_data[ "entries" ] as Entries[]; // Loop through each history entry and read the contents - for (let i = 0; i < json_data.entries.length; i++) { + for (let i = 0; i < file_entries.length; i++) { + const entry = file_entries[ i ]; + if (entry === undefined) { + continue; + } let hist_file = ""; switch (platform) { case PlatformType.Linux: case PlatformType.Darwin: { const dirs = path.full_path.split("/"); dirs.pop(); - hist_file = `${dirs.join("/")}/${json_data.entries[ i ]?.id}`; + hist_file = `${dirs.join("/")}/${file_entries[ i ]?.id}`; break; } case PlatformType.Windows: { const dirs = path.full_path.split("\\"); dirs.pop(); - hist_file = `${dirs.join("\\")}\\${json_data.entries[ i ]?.id}`; + hist_file = `${dirs.join("\\")}\\${file_entries[ i ]?.id}`; break; } } - // Read file data - const history_data = readTextFile(hist_file); - if (history_data instanceof FileError) { - console.warn( - `Could not read history file ${hist_file}: ${history_data}`, - ); - continue; + if (include_content) { + // Read file data + const history_data = readTextFile(hist_file); + if (history_data instanceof FileError) { + console.warn( + `Could not read history file ${hist_file}: ${history_data}`, + ); + continue; + } + // Base64 encode the history data + const history_encoded = encode(encodeBytes(history_data)); + entry.content = history_encoded; } - // Base64 encode the history data - const history_encoded = encode(encodeBytes(history_data)); - json_data.entries[ i ].timestamp = unixEpochToISO( - json_data.entries[ i ].timestamp as number, + + entry.timestamp = unixEpochToISO( + entry.timestamp as number, ); - json_data.entries[ i ].content = history_encoded; + const flat_data: FileHistory = { + version: json_data.version, + resource: json_data.resource, + history_path: json_data.history_path, + message: `${json_data.resource} - History Entry: ${entry.id}`, + datetime: entry.timestamp, + timestamp_desc: "File Saved", + artifact: "File History", + data_type: "applications:vscode:filehistory:entry", + id: entry.id, + file_saved: entry.timestamp, + content: entry.content ?? "", + path: hist_file, + source: entry.source ?? "", + sourceDescription: entry.sourceDescription ?? "" + }; + entries.push(flat_data); } - - entries.push(json_data); } return entries; @@ -239,8 +264,6 @@ export function vscodeRecentFiles(platform: PlatformType, alt_path?: string): Re } } - - } return recents; diff --git a/src/compression/decompress.ts b/src/compression/decompress.ts index b968cd18..609d0046 100644 --- a/src/compression/decompress.ts +++ b/src/compression/decompress.ts @@ -20,7 +20,7 @@ export function decompress_zlib( ); } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const bytes: Uint8Array = js_decompress_zlib(data, wbits, decom_size); return bytes; } catch (err) { @@ -37,7 +37,7 @@ export function decompress_gzip( data: Uint8Array, ): Uint8Array | CompressionError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const bytes: Uint8Array = js_decompress_gzip(data); return bytes; } catch (err) { @@ -52,7 +52,7 @@ export function decompress_gzip( */ export function decompress_snappy(data: Uint8Array): Uint8Array | CompressionError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const bytes: Uint8Array = js_decompress_snappy(data); return bytes; } catch (err) { @@ -67,7 +67,7 @@ export function decompress_snappy(data: Uint8Array): Uint8Array | CompressionErr */ export function decompress_zstd(data: Uint8Array): Uint8Array | CompressionError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const bytes: Uint8Array = js_decompress_zstd(data); return bytes; } catch (err) { diff --git a/src/decryption/decrypt.ts b/src/decryption/decrypt.ts index f6ba91cd..12f046e4 100644 --- a/src/decryption/decrypt.ts +++ b/src/decryption/decrypt.ts @@ -20,7 +20,7 @@ export function decryptAes( ); } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const bytes: Uint8Array = js_decrypt_aes(key, iv, data); return bytes; } catch (err) { diff --git a/src/encoding/base64.ts b/src/encoding/base64.ts index 6c1ac940..34c38f6e 100644 --- a/src/encoding/base64.ts +++ b/src/encoding/base64.ts @@ -6,7 +6,7 @@ import { EncodingError } from "./errors"; * @returns Base64 encoded string */ export function encode(data: Uint8Array): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_base64_encode(data); return result; } @@ -18,7 +18,7 @@ export function encode(data: Uint8Array): string { */ export function decode(b64: string): Uint8Array | EncodingError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const bytes: Uint8Array = js_base64_decode(b64); return bytes; } catch (err) { diff --git a/src/encoding/bytes.ts b/src/encoding/bytes.ts index a0fe0fc4..d7926252 100644 --- a/src/encoding/bytes.ts +++ b/src/encoding/bytes.ts @@ -4,7 +4,7 @@ * @returns Encode string into bytes */ export function encodeBytes(data: string): Uint8Array { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result: Uint8Array = js_encode_bytes(data); return result; } diff --git a/src/encoding/csv.ts b/src/encoding/csv.ts index e0c617a5..9184686c 100644 --- a/src/encoding/csv.ts +++ b/src/encoding/csv.ts @@ -9,7 +9,7 @@ import { EncodingError } from "./errors"; */ export function readCsv(path: string, offset: number = 0, limit: number = 100): Record[] | EncodingError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_read_csv(path, offset, limit); return result; } catch (err) { diff --git a/src/encoding/protobuf.ts b/src/encoding/protobuf.ts index 9be4a642..8749a0f0 100644 --- a/src/encoding/protobuf.ts +++ b/src/encoding/protobuf.ts @@ -10,7 +10,7 @@ export function parseProtobuf( data: Uint8Array, ): Record | EncodingError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_parse_protobuf(data); return result; } catch (err) { diff --git a/src/encoding/strings.ts b/src/encoding/strings.ts index 553647df..141f3b17 100644 --- a/src/encoding/strings.ts +++ b/src/encoding/strings.ts @@ -4,7 +4,7 @@ * @returns An UTF8 string. Will return base64 encoded string if extraction fails */ export function extractUtf8String(data: Uint8Array): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_extract_utf8_string(data); return result; } @@ -16,7 +16,7 @@ export function extractUtf8String(data: Uint8Array): string { * @returns An UTF8 string. Will return base64 encoded string if extraction fails */ export function extractUtf8StringLossy(data: Uint8Array): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_extract_utf8_string_lossy(data); return result; } @@ -27,7 +27,7 @@ export function extractUtf8StringLossy(data: Uint8Array): string { * @returns An UTF16 string.Will return base64 encoded string if extraction fails */ export function extractUtf16String(data: Uint8Array): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_extract_utf16_string(data); return result; } @@ -38,7 +38,7 @@ export function extractUtf16String(data: Uint8Array): string { * @returns A hexadecimal string */ export function bytesToHexString(data: Uint8Array): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_bytes_to_hex_string(data); return result; } diff --git a/src/encoding/uuid.ts b/src/encoding/uuid.ts index 764fb0ab..ecc72095 100644 --- a/src/encoding/uuid.ts +++ b/src/encoding/uuid.ts @@ -8,12 +8,12 @@ import { Endian } from "../nom/helpers"; */ export function formatGuid(format: Endian, data: Uint8Array): string { if (format === Endian.Be) { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_format_guid_be_bytes(data); return result; } - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_format_guid_le_bytes(data); return result; } @@ -23,7 +23,7 @@ export function formatGuid(format: Endian, data: Uint8Array): string { * @returns A UUID string */ export function generateUuid(): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_generate_uuid(); return result; } diff --git a/src/encoding/xml.ts b/src/encoding/xml.ts index e066ff61..2bab8a37 100644 --- a/src/encoding/xml.ts +++ b/src/encoding/xml.ts @@ -7,7 +7,7 @@ import { EncodingError } from "./errors"; */ export function readXml(path: string): Record | EncodingError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_read_xml(path); return result; } catch (err) { diff --git a/src/environment/env.ts b/src/environment/env.ts index ed48f9f9..eb5ff70e 100644 --- a/src/environment/env.ts +++ b/src/environment/env.ts @@ -1,9 +1,11 @@ +import { platform } from "../system/systeminfo"; + /** * Get all Environment variables associated with artemis process * @returns Record list of Environment variable values */ export function listEnv(): Record { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Record = js_env(); return data; } @@ -14,7 +16,22 @@ export function listEnv(): Record { * @returns Value of the provided Environment variable name */ export function getEnvValue(key: string): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: string = js_env_value(key); return data; } + +/** + * Function to get the Windows SystemDrive letter + * @returns The SystemDrive letter for Windows or empty string if called on non-Windows platforms + */ +export function getSystemDrive(): string { + if (platform().toLowerCase().includes("windows")) { + return ""; + } + let drive = getEnvValue("SystemDrive"); + if (drive === "") { + drive = "C:"; + } + return drive; +} \ No newline at end of file diff --git a/src/filesystem/acquire.ts b/src/filesystem/acquire.ts index c034afc8..9c3fcea1 100644 --- a/src/filesystem/acquire.ts +++ b/src/filesystem/acquire.ts @@ -9,7 +9,7 @@ import { FileError } from "./errors"; */ export function acquireFile(path: string, output: Output): boolean | FileError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const status: boolean = js_acquire_file(path, output); return status; } catch (err) { diff --git a/src/filesystem/directory.ts b/src/filesystem/directory.ts index f1f9cc8d..fffda0f9 100644 --- a/src/filesystem/directory.ts +++ b/src/filesystem/directory.ts @@ -8,7 +8,7 @@ import { FileError } from "./errors"; */ export async function readDir(path: string): Promise { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = await js_read_dir(path); return result; } catch (err) { diff --git a/src/filesystem/files.ts b/src/filesystem/files.ts index 233c2490..1ed03852 100644 --- a/src/filesystem/files.ts +++ b/src/filesystem/files.ts @@ -10,7 +10,7 @@ import { FileError } from "./errors"; */ export function stat(path: string): FileInfo | FileError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_stat(path); return result; } catch (err) { @@ -33,8 +33,8 @@ export function hash( sha256: boolean, ): Hashes | FileError { try { - //@ts-ignore: Custom Artemis function - const result = js_hash(path, md5, sha1, sha256); + // @ts-expect-error: Custom Artemis function + const result = js_hash_file(path, md5, sha1, sha256); return result; } catch (err) { return new FileError("HASH", `failed to hash ${path}: ${err}`); @@ -48,7 +48,7 @@ export function hash( */ export function readTextFile(path: string): string | FileError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_read_text_file(path); return result; } catch (err) { @@ -66,7 +66,7 @@ export function readTextFile(path: string): string | FileError { */ export function readFile(path: string): Uint8Array | FileError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_read_file(path); return result; } catch (err) { @@ -81,7 +81,7 @@ export function readFile(path: string): Uint8Array | FileError { */ export function glob(pattern: string): GlobInfo[] | FileError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_glob(pattern); return result; } catch (err) { @@ -101,7 +101,7 @@ export function readLines(path: string, offset: number = 0, limit: number = 100) return new FileError("READ_LINES", `neither offset (${offset}) or limit (${limit}) can be less than 0`); } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_read_lines(path, offset, limit); return result; } catch (err) { diff --git a/src/freebsd/packages.ts b/src/freebsd/packages.ts index 359e3608..6fb5185b 100644 --- a/src/freebsd/packages.ts +++ b/src/freebsd/packages.ts @@ -36,7 +36,7 @@ export function getPkgs(offset: number, limit: number, alt_path?: string): Pkg[] comment: entry[ "comment" ] as string, desc: entry[ "desc" ] as string, mtree_id: entry[ "mtree_id" ] as number | null, - message: entry[ "message" ] as string | null, + pkg_message: entry[ "message" ] as string | null, arch: entry[ "arch" ] as string, maintainer: entry[ "maintainer" ] as string, www: entry[ "message" ] as string | null, @@ -50,6 +50,11 @@ export function getPkgs(offset: number, limit: number, alt_path?: string): Pkg[] dep_formula: entry[ "dep_formula" ] as string | null, vital: Boolean(entry[ "vital" ]), manifest_digest: entry[ "manifest_digest" ] as string | null, + message: `Package ${entry[ "name" ] as string} version ${entry[ "version" ] as string} installed`, + datetime: unixEpochToISO(entry[ "time" ] as number ?? 0), + timestamp_desc: "Package Installed", + artifact: "FreeBSD PKG", + data_type: "freebsd:pkg:entry" }; pkg_entries.push(pkg_entry); } diff --git a/src/http/circlu.ts b/src/http/circlu.ts index 63bda84b..4cef9c96 100644 --- a/src/http/circlu.ts +++ b/src/http/circlu.ts @@ -1,4 +1,4 @@ -import { HashlookupResponse, HashType } from "../../types/http/circlu"; +import { HashlookupResponse, HashType, MissingHash } from "../../types/http/circlu"; import { encodeBytes } from "../encoding/bytes"; import { extractUtf8String } from "../encoding/strings"; import { ClientRequest, Protocol, request } from "./client"; @@ -13,7 +13,7 @@ import { HttpError } from "./errors"; export async function circluHashlookup( hashes: string | string[], hash_type: HashType, -): Promise { +): Promise { if (hash_type === HashType.SHA256 && Array.isArray(hashes)) { return new HttpError( `REQUEST_ERROR`, @@ -48,12 +48,15 @@ export async function circluHashlookup( if (response instanceof HttpError) { return response; - } else if (response.status !== 200) { + } else if (response.status !== 200 && response.status !== 404) { return new HttpError( `REQUEST_ERROR`, `received non-200 response: ${extractUtf8String(new Uint8Array(response.body)) }`, ); + } else if (response.status === 404) { + const missing: MissingHash = JSON.parse(extractUtf8String(new Uint8Array(response.body))); + return missing; } const result: HashlookupResponse | HashlookupResponse[] = JSON.parse( @@ -62,3 +65,47 @@ export async function circluHashlookup( return result; } + +/** + * Function to test circlu API + * This function should not be called unless you are developing the artemis-api + * Or want to validate the circlu API + */ +export async function testCircluHashlookup(): Promise { + const single_hash = "8ED4B4ED952526D89899E723F3488DE4"; + const single_response = await circluHashlookup(single_hash, HashType.MD5); + if (single_response instanceof HttpError) { + throw single_response; + } + + if (Array.isArray(single_response)) { + throw console.log("Got array response"); + } + + if (isMissing(single_response)) { + throw console.log(`Got ${single_response.message} wanted successful response.......circluHashlookup āŒ`); + } + + if (single_response.ProductCode?.ProductName != "Cumulative Update for Windows Server 2016 for x64 (KB4338817)") { + throw console.log(`Got ${single_response.ProductName} wanted "Cumulative Update for Windows Server 2016 for x64 (KB4338817)".......circluHashlookup āŒ`); + } + + + if (single_response.FileSize != "2520") { + throw console.log(`Got ${single_response.FileSize} wanted "2520".......circluHashlookup āŒ`); + } + + if (single_response.source != "NSRL") { + throw console.log(`Got ${single_response.source} wanted "NSRL".......circluHashlookup āŒ`); + } + + if (single_response.FileName != "wow64_microsoft-windows-i..timezones.resources_31bf3856ad364e35_10.0.16299.579_de-de_f24979c73226184d.manifest") { + throw console.log(`Got ${single_response.FileName} wanted "wow64_microsoft-windows-i..timezones.resources_31bf3856ad364e35_10.0.16299.579_de-de_f24979c73226184d.manifest".......circluHashlookup āŒ`); + } + console.info(` Function circluHashlookup āœ…`); + +} + +function isMissing(value: MissingHash | HashlookupResponse): value is MissingHash { + return 'query' in value; +} \ No newline at end of file diff --git a/src/http/client.ts b/src/http/client.ts index 1580d4af..7197a56a 100644 --- a/src/http/client.ts +++ b/src/http/client.ts @@ -54,7 +54,7 @@ export async function request( } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = await js_request(reqwest, body); const res: ClientResponse = result; return res; diff --git a/src/http/eol.ts b/src/http/eol.ts index 4d78ac8d..bdcf5807 100644 --- a/src/http/eol.ts +++ b/src/http/eol.ts @@ -13,7 +13,7 @@ export async function checkEolStatus( name: string, version: string, ): Promise { - const url = `https://endoflife.date/api/${name.toLocaleLowerCase()}.json`; + const url = `https://endoflife.date/api/${name.toLowerCase()}.json`; const client: ClientRequest = { url, protocol: Protocol.GET, @@ -55,3 +55,31 @@ export async function checkEolStatus( `no match for the software ${name} and version ${version}`, ); } + +/** + * Function to test End of Life API + * This function should not be called unless you are developing the artemis-api + * Or want to validate the End of Life API + */ +export async function testCheckEolStatus(): Promise { + const application = "firefox"; + const version = "130"; + const result = await checkEolStatus(application, version); + if (result instanceof HttpError) { + throw console.log(result); + } + + if (result.url !== "https://endoflife.date/firefox") { + throw console.log(`Got ${result.url} expected "https://endoflife.date/firefox".......checkEolStatus āŒ`); + } + + if (result.lts !== false) { + throw console.log(`Got ${result.lts} expected "false".......checkEolStatus āŒ`); + } + + if (result.release_date !== "2024-09-03") { + throw console.log(`Got ${result.release_date} expected "2024-09-03".......checkEolStatus āŒ`); + } + console.info(` Function checkEolStatus āœ…`); + +} \ No newline at end of file diff --git a/src/images/icns.ts b/src/images/icns.ts index 1f46b576..98aee24e 100644 --- a/src/images/icns.ts +++ b/src/images/icns.ts @@ -78,6 +78,9 @@ export function parseIcon(data: Uint8Array): Icon[] | ImageError { */ function osType(type: Uint8Array): number { const value = extractUtf8String(type) as OSType; + if(value.startsWith("[strings]")) { + return 0; + } if ( [ diff --git a/src/ios/domains/network/network.ts b/src/ios/domains/network/network.ts index a380ad2c..aaf402a6 100644 --- a/src/ios/domains/network/network.ts +++ b/src/ios/domains/network/network.ts @@ -1,4 +1,4 @@ -import { getPlist, parseCookies, queryTccDb } from "../../../../mod"; +import { getPlist, } from "../../../../mod"; import { FileType, ManifestApp, diff --git a/src/ios/domains/wireless/sqlite.ts b/src/ios/domains/wireless/sqlite.ts new file mode 100644 index 00000000..de02acfd --- /dev/null +++ b/src/ios/domains/wireless/sqlite.ts @@ -0,0 +1,40 @@ +import { ApplicationError } from "../../../applications/errors"; +import { querySqlite } from "../../../applications/sqlite"; +import { cocoatimeToUnixEpoch, unixEpochToISO } from "../../../time/conversion"; +import { IosError } from "../../error"; + +interface DataUsage { + datetime: string; + process_name: string; + bundle: + string; +} + +/** + * Function to extract data usage process. It is not super useful + * @param path Path to DataUsage.sqlite file + * @returns Array of `DataUsage` or `IosError` + */ +export function extractDataUsage(path: string): DataUsage[] | IosError { + const query = `SELECT ZTIMESTAMP,ZBUNDLENAME,ZPROCNAME FROM ZPROCESS`; + const results = querySqlite(path, query); + if (results instanceof ApplicationError) { + return new IosError( + `DATAUSAGE`, + `failed to query appt state db: ${results}` + ); + } + + const data: DataUsage[] = []; + + for (const entry of results) { + const usage: DataUsage = { + datetime: unixEpochToISO(cocoatimeToUnixEpoch(entry[ "ZTIMESTAMP" ] as number | undefined ?? 0)), + process_name: entry[ "ZPROCNAME" ] as string | undefined ?? "", + bundle: entry[ "ZBUNDLENAME" ] as string | undefined ?? "", + }; + data.push(usage); + } + + return data; +} \ No newline at end of file diff --git a/src/ios/domains/wireless/wireless.ts b/src/ios/domains/wireless/wireless.ts new file mode 100644 index 00000000..d9c40bdb --- /dev/null +++ b/src/ios/domains/wireless/wireless.ts @@ -0,0 +1,50 @@ +import { + FileType, + ManifestApp, +} from "../../../../types/ios/itunes/manifest"; +import { Output, outputResults } from "../../../system/output"; +import { IosError } from "../../error"; +import { parseManifestAppPlist } from "../../itunes/apps"; +import { extractDataUsage } from "./sqlite"; + +/** + * Function to extract Wireless info + * @param app_paths Array of `ManifestApp` + * @param db_path iTunes backup directory + * @param output `Output` configuration object + */ +export function extractWireless( + app_paths: ManifestApp[], + db_path: string, + output: Output, +) { + for (const path of app_paths) { + if (path.file_type !== FileType.IsFile) { + continue; + } + + const info = parseManifestAppPlist(path.file); + if (info instanceof IosError) { + continue; + } + + const target = `${db_path}/${path.directory}/${path.fileID}`; + + if (info.path.endsWith("DataUsage.sqlite")) { + const data = extractDataUsage(target); + if (data instanceof IosError) { + continue; + } + outputResults( + data, + "wirelessdomain_apple_datausage_sqlite", + output, + ); + continue; + } + + // Uncomment to view unsupported entries + //console.log(info.path); + //console.log(target); + } +} \ No newline at end of file diff --git a/src/ios/error.ts b/src/ios/error.ts index 6c884f15..46003ce0 100644 --- a/src/ios/error.ts +++ b/src/ios/error.ts @@ -15,6 +15,7 @@ export type ErrorName = | "ROOTDOMAIN" | "DUCKDUCKGO" | "APPLE_LINKD" - | "APPSTATE"; + | "APPSTATE" + | "DATAUSAGE"; export class IosError extends ErrorBase { } diff --git a/src/ios/itunes/apps.ts b/src/ios/itunes/apps.ts index af9fdd5e..219f37b2 100644 --- a/src/ios/itunes/apps.ts +++ b/src/ios/itunes/apps.ts @@ -19,6 +19,7 @@ import { extractNetworkDomain } from "../domains/network/network"; import { extractRootDomain } from "../domains/root/root"; import { extractAppleLinkd } from "../domains/syscontainer/linkd"; import { extractOsAnalytics } from "../domains/syssharedcontainer/osanalytics"; +import { extractWireless } from "../domains/wireless/wireless"; import { IosError } from "../error"; /** @@ -206,5 +207,8 @@ export function extractAppInfo( case "SysSharedContainerDomain-systemgroup.com.apple.osanalytics": extractOsAnalytics(paths, db_path, output); break; + case "WirelessDomain": + extractWireless(paths, db_path, output); + break; } } diff --git a/src/linux/abrt.ts b/src/linux/abrt.ts index 5a7e9370..719653f8 100644 --- a/src/linux/abrt.ts +++ b/src/linux/abrt.ts @@ -65,7 +65,12 @@ async function readAbrtDir(path: string): Promise { data_directory: path, backtrace: "", environment: "", - home: "" + home: "", + message: "", + datetime: "", + timestamp_desc: "Abrt Last Occurrence", + artifact: "Abrt", + data_type: "linux:abrt:entry" }; for (const entry of entries) { if (!entry.is_file) { @@ -75,6 +80,7 @@ async function readAbrtDir(path: string): Promise { switch (entry.filename) { case "executable": { abrt_entry.executable = readLine(entry.full_path); + abrt_entry.message = `${abrt_entry.executable} crashed`; break; } case "cmdline": { @@ -103,6 +109,7 @@ async function readAbrtDir(path: string): Promise { } case "last_occurrence": { abrt_entry.last_occurrence = unixEpochToISO(Number(readLine(entry.full_path))); + abrt_entry.datetime = abrt_entry.last_occurrence; break; } case "backtrace": { diff --git a/src/linux/elf.ts b/src/linux/elf.ts index 0a725cf0..f5a4d0bb 100644 --- a/src/linux/elf.ts +++ b/src/linux/elf.ts @@ -8,7 +8,7 @@ import { LinuxError } from "./errors"; */ export function getElf(path: string): ElfInfo | LinuxError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_get_elf(path); return data; } catch (err) { diff --git a/src/linux/errors.ts b/src/linux/errors.ts index 9bb86a82..acca4f34 100644 --- a/src/linux/errors.ts +++ b/src/linux/errors.ts @@ -14,6 +14,8 @@ export type ErrorName = | "ABRT" | "EPIPHANY" | "FIRMWARE_HISTORY" - | "FALKON"; + | "FALKON" + | "WTMPDB" + | "EXT4"; export class LinuxError extends ErrorBase { } diff --git a/src/linux/ext4.ts b/src/linux/ext4.ts new file mode 100644 index 00000000..e5ca723a --- /dev/null +++ b/src/linux/ext4.ts @@ -0,0 +1,60 @@ +import { FileEntry } from "../../types/linux/ext4"; +import { LinuxError } from "./errors"; + +/** + * Function to read a file by accessing the raw `EXT4` filesystem. + * It currently reads the whole file into memory! + * Use with **CAUTION** + * @param path Path to file you want to read + * @param device The device associated with the ext4 filesystem. Ex: /dev/sda1 + * @returns Bytes read or `LinuxError` + */ +export function readRawFileExt4(path: string, device: string): Uint8Array | LinuxError { + try { + // @ts-expect-error: Custom Artemis function + const data: Uint8Array = js_read_raw_file_ext4(path, device); + return data; + } catch (err) { + return new LinuxError("EXT4", `failed to read file ${path}: ${err}`); + } +} + +/** + * Function to search for directories and files. This is similar to globbing, except you can use regex. + * All entries are stored in memory! Use with **CAUTION** + * No bytes are read, but it will store any regex match in memory + * @param path Path you want to read. This can be a valid Rust regex string + * @param start Start path you want to start reading at + * @param device The device associated with the ext4 filesystem. Ex: /dev/sda1 + * @returns Array of `FileEntry` or `LinuxError` + */ +export function readRawDirExt4(path: string, start: string, device: string): FileEntry[] | LinuxError { + try { + // @ts-expect-error: Custom Artemis function + const data: FileEntry[] = js_read_raw_dir_ext4(path, start, device); + return data; + } catch (err) { + return new LinuxError("EXT4", `failed to read path ${path}: ${err}`); + } +} + +/** + * Function to read a file by its inode by accessing the raw `EXT4` filesystem. + * It currently reads the whole file into memory! + * Use with **CAUTION** + * @param inode Inode number to read. Must be a positive number + * @param device The device associated with the ext4 filesystem. Ex: /dev/sda1 + * @returns Bytes read or `LinuxError` + */ +export function readRawInodeExt4(inode: number, device: string): Uint8Array | LinuxError { + if (inode <= 0) { + return new LinuxError(`EXT4`, `You provided a bizarre inode number? It must be greater than 0`); + } + try { + // @ts-expect-error: Custom Artemis function + const data: Uint8Array = js_read_raw_inode_ext4(inode, device); + return data; + } catch (err) { + return new LinuxError("EXT4", `failed to read inode ${inode}: ${err}`); + } +} \ No newline at end of file diff --git a/src/linux/gnome/epiphany.ts b/src/linux/gnome/epiphany.ts index 00aae65d..2c98201a 100644 --- a/src/linux/gnome/epiphany.ts +++ b/src/linux/gnome/epiphany.ts @@ -1,5 +1,4 @@ import { EpiphanyCookies, EpiphanyHistory, EpiphanyPermissions, EpiphanyPrint, EpiphanyProfiles, EpiphanySessions, VisitType } from "../../../types/linux/gnome/epiphany"; -import { TimesketchTimeline } from "../../../types/timesketch/timeline"; import { ApplicationError } from "../../applications/errors"; import { querySqlite } from "../../applications/sqlite"; import { EncodingError } from "../../encoding/errors"; @@ -81,10 +80,15 @@ export class Epiphany { hidden_from_overview: Boolean(entry[ "hidden_from_overview" ] as number), visit_type: this.visitType(entry[ "visit_type" ] as number), db_path: db, - target_url: entry[ "url" ] as string | null, - title: entry[ "title" ] as string | null, + target_url: entry[ "url" ] as string | null ?? "", + title: entry[ "title" ] as string | null ?? "", referring_visit: entry[ "referring_visit" ] as string | null, sync_id: entry[ "sync_id" ] as string | null, + message: entry[ "url" ] as string | null ?? "", + datetime: unixEpochToISO(entry[ "last_visit_time" ] as bigint), + timestamp_desc: "URL Visited", + artifact: "URL History", + data_type: "linux:gnome:epiphany:history:entry" }; if (this.unfold && client !== undefined && value.target_url !== null) { @@ -124,28 +128,34 @@ export class Epiphany { value: entry[ "value" ] as string | null, host: entry[ "host" ] as string | null, path: entry[ "path" ] as string | null, - expiry: null, - last_accessed: null, - is_secure: null, - is_http_only: null, - same_site: null, - db_path: db + expiry: "", + last_accessed: "", + is_secure: false, + is_http_only: false, + same_site: false, + db_path: db, + message: `Cookie for ${entry[ "host" ] as string | null} | ${entry[ "name" ] as string | null ?? ""}`, + datetime: "", + timestamp_desc: "Cookie Expires", + artifact: "Website Cookie", + data_type: "linux:browser:epiphany:cookie:entry" }; - if (entry[ "last_access" ] !== null) { + if (entry[ "lastAccessed" ] !== null) { value.last_accessed = unixEpochToISO(entry[ "last_access" ] as number); } - if (entry[ "is_secure" ] !== null) { + if (entry[ "isSecure" ] !== null) { value.is_secure = Boolean(entry[ "is_secure" ] as number); } - if (entry[ "is_http_only" ] !== null) { + if (entry[ "isHttpOnly" ] !== null) { value.is_http_only = Boolean(entry[ "is_http_only" ] as number); } - if (entry[ "same_site" ] !== null) { + if (entry[ "sameSite" ] !== null) { value.same_site = Boolean(entry[ "same_site" ] as number); } if (entry[ "expiry" ] !== null) { value.expiry = unixEpochToISO(entry[ "expiry" ] as number); + value.datetime = value.expiry; } results.push(value); } @@ -168,14 +178,25 @@ export class Epiphany { } const entries = xml_data[ "session" ] as Record[]>; + if (entries[ "window" ] === undefined) { + continue; + } for (const values of entries[ "window" ]) { const embed = values[ "embed" ] as Record>[]; for (const value of embed) { + if (value[ "$" ] === undefined) { + continue; + } const session: EpiphanySessions = { - url: value[ "$" ][ "url" ], - title: value[ "$" ][ "title" ], - history: value[ "$" ][ "history" ], - session_path: xml_file + url: value[ "$" ][ "url" ] ?? "", + title: value[ "$" ][ "title" ] ?? "", + history: value[ "$" ][ "history" ] ?? "", + session_path: xml_file, + message: `Session for ${value[ "$" ][ "url" ] ?? ""}`, + datetime: "1970-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + artifact: "GNOME Epiphany Session", + data_type: "linux:browser:epiphany:session:entry" }; results.push(session); @@ -212,15 +233,21 @@ export class Epiphany { url: "", permissions: {}, file_path: perm_file, + message: "", + datetime: "1970-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + artifact: "GNOME Epiphany Site Permission", + data_type: "linux:browser:epiphany:permissions:entry" }; for (const line of lines) { if (line.startsWith("[")) { perms.url = line.replace("[org/gnome/epiphany/permissions/", "").replaceAll("/", ":").replace("http:", "http://").replace("https:", "https://").replace("]", "").replace(":0", ""); + perms.message = perms.url; } else if (line.includes("=")) { const perm_line = line.replace("'", ""); const perm_types = perm_line.split("="); - if (perm_types.length > 1) { + if (perm_types.length > 1 && perm_types[ 0 ] !== undefined) { perms.permissions[ perm_types[ 0 ] ] = perm_types.at(1) ?? ""; } } @@ -240,7 +267,7 @@ export class Epiphany { const results: EpiphanyPrint[] = []; for (const entry of this.paths) { const print_file = `${entry.full_path}/print-settings.ini`; - let print_data = readTextFile(print_file); + const print_data = readTextFile(print_file); if (print_data instanceof FileError) { continue; } @@ -257,6 +284,11 @@ export class Epiphany { pages: "", collate: false, file_path: print_file, + message: "", + datetime: "1970-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + artifact: "GNOME Epiphany Last Print", + data_type: "linux:browser:epiphany:cookie:entry" }; for (const line of lines) { @@ -276,6 +308,7 @@ export class Epiphany { print.page_set = line.replace("page-set=", ""); } else if (line.startsWith("output-uri=")) { print.output = line.replace("output-uri=", ""); + print.message = `Print page ${print.output}`; } else if (line.startsWith("print-pages=")) { const value = line.replace("print-pages=", ""); if (!Number.isNaN(Number(value))) { @@ -297,7 +330,7 @@ export class Epiphany { */ public retrospect(output: Output): void { let offset = 0; - let limit = 100; + const limit = 100; // Get all history info while (true) { @@ -305,25 +338,8 @@ export class Epiphany { if (entries.length === 0) { break; } - let timeline_entries: TimesketchTimeline[] = []; - - for (const entry of entries) { - let timeline: TimesketchTimeline = { - datetime: entry.last_visit_time, - timestamp_desc: "Last Visit", - message: entry.target_url ?? "", - artifact: "GNOME Epiphany History", - data_type: "linux:browser:epiphany:history:entry" - }; - timeline = { ...timeline, ...entry }; - if (this.unfold) { - timeline = { ...timeline, ...entry.unfold }; - } - delete timeline[ "unfold" ]; - timeline_entries.push(timeline); - } - const status = dumpData(timeline_entries, "retrospect_epiphany_history", output); + const status = dumpData(entries, "retrospect_epiphany_history", output); if (status instanceof SystemError) { console.error(`Failed timeline Epiphany history: ${status}`); } @@ -339,79 +355,27 @@ export class Epiphany { break; } - let timeline_entries: TimesketchTimeline[] = []; - - for (const entry of entries) { - let timeline: TimesketchTimeline = { - datetime: entry.last_accessed ?? "1970-01-01T00:00:00.000Z", - timestamp_desc: "Last Accessed", - message: entry.host ?? "", - artifact: "GNOME Epiphany Cookie", - data_type: "linux:browser:epiphany:cookie:entry" - }; - - timeline = { ...timeline, ...entry }; - timeline_entries.push(timeline); - } - const status = dumpData(timeline_entries, "retrospect_epiphany_cookies", output); + const status = dumpData(entries, "retrospect_epiphany_cookies", output); if (status instanceof SystemError) { console.error(`Failed timeline Epiphany cookies: ${status}`); } offset += limit; } - // Smaller data to timeline - let timeline_entries: TimesketchTimeline[] = []; - const sessions = this.sessions(); - for (const entry of sessions) { - let timeline: TimesketchTimeline = { - datetime: "1970-01-01T00:00:00.000Z", - timestamp_desc: "N/A", - message: "", - artifact: "GNOME Epiphany Sessions", - data_type: "linux:browser:epiphany:sessions:entry" - }; - - if (typeof entry[ "url" ] === 'string') { - timeline.message = entry[ "url" ]; - } - - timeline = { ...timeline, ...entry }; - timeline_entries.push(timeline); + let status = dumpData(sessions, "retrospect_epiphany_sessions", output); + if (status instanceof SystemError) { + console.error(`Failed timeline Epiphany sessions: ${status}`); } const permissions = this.permissions(); - // Get site permissions - for (let entry of permissions) { - let timeline: TimesketchTimeline = { - datetime: "1970-01-01T00:00:00.000Z", - timestamp_desc: "N/A", - message: entry.url, - artifact: "GNOME Epiphany Site Permissions", - data_type: "linux:browser:epiphany:permission:entry" - }; - - timeline = { ...timeline, ...entry.permissions }; - timeline[ "file_path" ] = entry.file_path; - delete timeline[ "permissions" ]; - timeline_entries.push(timeline); + status = dumpData(permissions, "retrospect_epiphany_permissions", output); + if (status instanceof SystemError) { + console.error(`Failed timeline Epiphany permissions: ${status}`); } const print_page = this.lastPrint(); - for (const entry of print_page) { - let timeline: TimesketchTimeline = { - datetime: "1970-01-01T00:00:00.000Z", - timestamp_desc: "N/A", - message: entry.output, - artifact: "GNOME Epiphany Last Print", - data_type: "linux:browser:epiphany:lastprint:entry" - }; - - timeline = { ...timeline, ...entry }; - timeline_entries.push(timeline); - } - const status = dumpData(timeline_entries, "retrospect_epiphany", output); + status = dumpData(print_page, "retrospect_epiphany_lastprint", output); if (status instanceof SystemError) { console.error(`Failed timeline Epiphany last print: ${status}`); } diff --git a/src/linux/gnome/extensions.ts b/src/linux/gnome/extensions.ts index 09281f1f..b9124053 100644 --- a/src/linux/gnome/extensions.ts +++ b/src/linux/gnome/extensions.ts @@ -59,6 +59,8 @@ export function getGnomeExtensions( } else { ext_data.extension_type = ExtensionType.Unknown; } + ext_data.message = ext_data.name; + ext_data.datetime = ext_data.created; extensions.push(ext_data); } } @@ -87,5 +89,4 @@ export function testGetGnomeExtensions(): void { } console.info(` Function getGnomeExtensions āœ…`); - } \ No newline at end of file diff --git a/src/linux/gnome/gedit.ts b/src/linux/gnome/gedit.ts index 9dcfc5bc..f1c3738b 100644 --- a/src/linux/gnome/gedit.ts +++ b/src/linux/gnome/gedit.ts @@ -46,9 +46,15 @@ export function geditRecentFiles( >; const docs = meta[ "document" ]; + if (docs === undefined) { + continue; + } for (const doc of docs) { + if (doc[ "$" ] === undefined) { + continue; + } const recent: RecentFiles = { - path: doc[ "$" ][ "uri" ], + path: doc[ "$" ][ "uri" ] ?? "", accessed: unixEpochToISO(Number(doc[ "$" ][ "atime" ])), gedit_source: entry.full_path, }; @@ -71,6 +77,10 @@ export function testGeditRecentFiles(): void { throw result; } + if (result[ 0 ] === undefined) { + throw `Got undefined results`; + } + if (result[ 0 ].path != "file:///home/devel/Downloads/analyzeMFT-3.0.7.1/src/analyzeMFT/__init__.py") { throw `Got path ${result[ 0 ].path} expected file:///home/devel/Downloads/analyzeMFT-3.0.7.1/src/analyzeMFT/__init__.py.......geditRecentFiles āŒ`; } diff --git a/src/linux/gnome/gvfs.ts b/src/linux/gnome/gvfs.ts index 232df15f..80c3726d 100644 --- a/src/linux/gnome/gvfs.ts +++ b/src/linux/gnome/gvfs.ts @@ -16,7 +16,7 @@ import { unixEpochToISO } from "../../time/conversion"; import { LinuxError } from "../errors"; /** - * Function to parse GVFS metadata files. By default will parse all GVFS metadata files at `/home/%/.local/share/gvfs-metadata/%` + * Function to parse GVFS metadata files. By default will parse all GVFS metadata files at `/home/%/.local/share/gvfs-metadata/*` * @param alt_path Alternative path (or glob) to a GVFS file * @returns Array of `GVFSEntry` or `LinuxError` */ @@ -169,7 +169,11 @@ function extractHeader(data: Uint8Array): Header | NomError { let magic_sig = 0; for (let i = 0; i < magic.nommed.length; i++) { - magic_sig |= (magic.nommed as Uint8Array)[ i ] << (i * 8); + const entry = (magic.nommed as Uint8Array)[ i ]; + if (entry === undefined) { + continue; + } + magic_sig |= entry << (i * 8); } const header: Header = { @@ -508,6 +512,11 @@ function getChildren( last_change: unixEpochToISO(last_change.value + base_time), path: `${parents.join("/")}/${name}`.replace("//", "/"), source, + message: `${parents.join("/")}/${name}`.replace("//", "/"), + datetime: unixEpochToISO(last_change.value + base_time), + timestamp_desc: "Last Changed", + artifact: "GNOME Virtual Filesystem", + data_type: "linux:gnome:gvfs:entry" }; children.push(child); @@ -557,3 +566,119 @@ function getName(offset: number, data: Uint8Array): string | NomError { const name = extractUtf8String(name_data.nommed as Uint8Array); return name; } + +/** + * Function to test GNOME GVFS parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the GNOME GVFS parsing + */ +export function testParseGvfs(): void { + const test = "../../test_data/linux/gnome/gvfs.raw"; + const result = parseGvfs(test); + if (result instanceof LinuxError) { + throw result; + } + + if (result.length != 5) { + throw `Got ${result.length} expected 5.......parseGvfs āŒ`; + } + if (result[ 4 ] === undefined) { + throw `Got GVFS path undefined expected "/storage/emulated/0/Music/NewPipe".......parseGvfs āŒ`; + } + + if (result[ 4 ].path != "/storage/emulated/0/Music/NewPipe") { + throw `Got path ${result[ 4 ].path} expected "/storage/emulated/0/Music/NewPipe".......parseGvfs āŒ`; + } + + console.info(` Function parseGvfs āœ…`); + + const header = new Uint8Array([ 218, 26, 109, 101, 116, 97, 1, 0, 0, 0, 0, 0, 158, 169, 70, 67, 0, 0, 0, 104, 0, 0, 0, 32, 0, 0, 0, 0, 103, 15, 6, 27, 0, 0, 0, 2, 0, 0, 0, 77, 0, 0, 0, 44, 110, 97, 117, 116, 105, 108, 117, 115, 45, 105, 99, 111, 110, 45, 118, 105, 101, 119, 45, 115, 111, 114, 116, 45, 114, 101, 118, 101, 114, 115, 101, 100, 0, 110, 97, 117, 116, 105, 108, 117, 115, 45, 105, 99, 111, 110, 45, 118, 105, 101, 119, 45, 115, 111, 114, 116, 45, 98, 121, 0, 0, 0, 0, 120, 0, 0, 0, 124, 0, 0, 1, 12, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 144, 0, 0, 0, 152, 0, 0, 1, 16, 0, 0, 0, 0, 115, 116, 111, 114, 97, 103, 101, 0, 0, 0, 0, 1, 0, 0, 0, 172, 0, 0, 0, 184, 0, 0, 1, 20, 0, 0, 0, 0, 101, 109, 117, 108, 97, 116, 101, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 204, 0, 0, 0, 208, 0, 0, 1, 24, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 228, 0, 0, 0, 236, 0, 0, 1, 28, 0, 0, 0, 0, 77, 117, 115, 105, 99, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 8, 0, 0, 1, 32, 0, 0, 0, 1, 78, 101, 119, 80, 105, 112, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 52, 0, 0, 0, 1, 0, 0, 1, 66, 100, 97, 116, 101, 95, 109, 111, 100, 105, 102, 105, 101, 100, 0, 116, 114, 117, 101, 0, 0 ]); + const header_results = extractHeader(header); + if (header_results instanceof NomError) { + throw header_results; + } + + if (header_results.base_time !== 1729037851) { + throw `Got base time ${header_results.base_time} expected "1729037851".......extractHeader āŒ`; + } + + console.info(` Function extractHeader āœ…`); + + const bytes = readFile(test); + if (bytes instanceof FileError) { + throw bytes; + } + + const keywords = getKeywords(bytes, 32); + if (keywords instanceof NomError) { + throw keywords; + } + + if (keywords.length !== 2) { + throw `Got ${keywords.length} expected 2.......getKeywords āŒ`; + } + + if (keywords[ 1 ] === undefined) { + throw `Got GVFS keyworkds undefined expected "nautilus-icon-view-sort-reversed".......getKeywords āŒ`; + } + + if (keywords[ 1 ] != "nautilus-icon-view-sort-reversed") { + throw `Got ${keywords[ 1 ]} expected "nautilus-icon-view-sort-reversed".......getKeywords āŒ`; + } + console.info(` Function getKeywords āœ…`); + + const root = getRoot(bytes, 104, 1729037851); + if (root instanceof NomError) { + throw root; + } + + if (root.name !== "/") { + throw `Got ${root.name} expected "/".......getRoot āŒ`; + } + + if (root.last_change != "2024-10-16T00:17:31.000Z") { + throw `Got ${root.last_change} expected "2024-10-16T00:17:31.000Z".......getRoot āŒ`; + } + console.info(` Function getRoot āœ…`); + + const meta = extractMetadata(288, bytes, [ "nautilus-icon-view-sort-by", "nautilus-icon-view-sort-reversed" ]); + if (meta instanceof NomError) { + throw meta; + } + + + if (meta[ "nautilus-icon-view-sort-by" ] !== "date_modified") { + throw `Got ${meta[ "nautilus-icon-view-sort-by" ]} expected "date_modified".......extractMetadata āŒ`; + } + + if (meta[ "nautilus-icon-view-sort-reversed" ] !== "true") { + throw `Got ${meta[ "nautilus-icon-view-sort-reversed" ]} expected "true".......extractMetadata āŒ`; + } + console.info(` Function extractMetadata āœ…`); + + const child = getChildren(124, bytes, [ "/" ], 1729037851, [ "nautilus-icon-view-sort-by", "nautilus-icon-view-sort-reversed" ], "test"); + if (child instanceof NomError) { + throw child; + } + + if (child.length !== 5) { + throw `Got ${child.length} expected 5.......getChildren āŒ`; + } + + if (child[ 0 ]?.message !== "/storage") { + throw `Got ${child[ 0 ]?.message} expected "/storage".......getChildren āŒ`; + } + console.info(` Function getChildren āœ…`); + + const name = getName(120, bytes); + if (name instanceof NomError) { + throw name; + } + + + if (name !== "/") { + throw `Got ${name} expected "/".......getName āŒ`; + } + console.info(` Function getName āœ…`); + +} \ No newline at end of file diff --git a/src/linux/gnome/usage.ts b/src/linux/gnome/usage.ts index 6f51b66f..980fef9e 100644 --- a/src/linux/gnome/usage.ts +++ b/src/linux/gnome/usage.ts @@ -40,23 +40,38 @@ export function gnomeAppUsage(alt_path?: string): AppUsage[] | LinuxError { const context = data[ "application-state" ] as Record; const context_entries = context[ "context" ]; + if (context_entries === undefined) { + continue; + } + for (const value of context_entries) { const applications = value as Record< string, unknown[] >; + if (applications[ "application" ] === undefined) { + continue; + } for (const app_entry of applications[ "application" ]) { const app = app_entry as Record< string, Record >; + if (app[ "$" ] === undefined) { + continue; + } const app_usage: AppUsage = { - id: app[ "$" ][ "id" ], + id: app[ "$" ][ "id" ] ?? "", score: Number(app[ "$" ][ "score" ]), "last-seen": unixEpochToISO(Number(app[ "$" ][ "last-seen" ])), source: entry.full_path, + message: app[ "$" ][ "id" ] ?? "", + datetime: unixEpochToISO(Number(app[ "$" ][ "last-seen" ])), + timestamp_desc: "Last Seen", + artifact: "GNOME Application Usage", + data_type: "linux:gnome:usage:entry" }; apps.push(app_usage); @@ -66,3 +81,31 @@ export function gnomeAppUsage(alt_path?: string): AppUsage[] | LinuxError { return apps; } + +/** + * Function to test GNOME App usage parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the GNOME App usage parsing + */ +export function testGnomeAppUsage(): void { + const app = "../../test_data/linux/gnome/usage.xml"; + const results = gnomeAppUsage(app); + if (results instanceof LinuxError) { + throw results; + } + + if (results.length !== 23) { + throw `Got ${results.length} entries expected 23.......gnomeAppUsage āŒ`; + } + + if (results[ 2 ]?.id !== "libreoffice-startcenter.desktop") { + throw `Got ${results[ 2 ]?.id} entries expected "libreoffice-startcenter.desktop".......gnomeAppUsage āŒ`; + } + + if (results[ 3 ]?.[ "last-seen" ] !== "2025-09-22T01:39:36.000Z") { + throw `Got ${results[ 3 ]?.[ "last-seen" ]} entries expected "2025-09-22T01:39:36.000Z".......gnomeAppUsage āŒ`; + } + + console.info(` Function gnomeAppUsage āœ…`); + +} \ No newline at end of file diff --git a/src/linux/journal.ts b/src/linux/journal.ts index 7c160e4f..6a5dfb7a 100644 --- a/src/linux/journal.ts +++ b/src/linux/journal.ts @@ -8,7 +8,7 @@ import { LinuxError } from "./errors"; */ export function getJournal(path: string): Journal[] | LinuxError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_get_journal(path); return data; } catch (err) { diff --git a/src/linux/kde/falkon/falkon.ts b/src/linux/kde/falkon/falkon.ts index 15e37d81..c40abead 100644 --- a/src/linux/kde/falkon/falkon.ts +++ b/src/linux/kde/falkon/falkon.ts @@ -10,7 +10,7 @@ import { falkonCookie, falkonHistory } from "./sqlite"; * Class to parse KDE Falkon browser data */ export class Falkon { - protected paths: FalkonProfile[]; + protected paths: FalkonProfile[] = []; protected platform: PlatformType; protected unfold: boolean; @@ -21,7 +21,7 @@ export class Falkon { * @param alt_path Optional alternative path to directory contain Falkon data * @returns `Falkon` instance class */ - constructor(platform: PlatformType, unfold = false, alt_path?: string) { + constructor (platform: PlatformType, unfold = false, alt_path?: string) { this.platform = platform; this.unfold = unfold; @@ -38,10 +38,10 @@ export class Falkon { return; } - this.paths = [{ + this.paths = [ { full_path: alt_path, version: browser_version, - }]; + } ]; } /** @@ -114,17 +114,17 @@ export class Falkon { created = meta.created; } // Get bookmarks in bar - for (const entry of json_data["roots"]["bookmark_bar"]["children"] as Record[]) { + for (const entry of json_data[ "roots" ][ "bookmark_bar" ][ "children" ] as Record[]) { const value: FalkonBookmark = { - bookmark_type: entry["type"] as string, - description: entry["description"] as string, - name: entry["description"] as string, + bookmark_type: entry[ "type" ] as string, + description: entry[ "description" ] as string, + name: entry[ "description" ] as string, location: BookmarkLocation.Bar, - url: entry["description"] as string, - visit_count: entry["visit_count"] as number, + url: entry[ "description" ] as string, + visit_count: entry[ "visit_count" ] as number, path: book_path, version: path.version, - message: entry["description"] as string, + message: entry[ "description" ] as string, datetime: created, timestamp_desc: "Falkon Bookmark File Created", artifact: "KDE Falkon Bookmark", @@ -134,17 +134,17 @@ export class Falkon { } // Get bookmarks in menu folder - for (const entry of json_data["roots"]["bookmark_menu"]["children"] as Record[]) { + for (const entry of json_data[ "roots" ][ "bookmark_menu" ][ "children" ] as Record[]) { const value: FalkonBookmark = { - bookmark_type: entry["type"] as string, - description: entry["description"] as string, - name: entry["name"] as string, + bookmark_type: entry[ "type" ] as string, + description: entry[ "description" ] as string, + name: entry[ "name" ] as string, location: BookmarkLocation.Menu, - url: entry["url"] as string, - visit_count: entry["visit_count"] as number, + url: entry[ "url" ] as string, + visit_count: entry[ "visit_count" ] as number, path: book_path, version: path.version, - message: entry["url"] as string, + message: entry[ "url" ] as string, datetime: created, timestamp_desc: "Falkon Bookmark File Created", artifact: "KDE Falkon Bookmark", @@ -154,17 +154,17 @@ export class Falkon { } // Get bookmarks in other - for (const entry of json_data["roots"]["other"]["children"] as Record[]) { + for (const entry of json_data[ "roots" ][ "other" ][ "children" ] as Record[]) { const value: FalkonBookmark = { - bookmark_type: entry["type"] as string, - description: entry["description"] as string, - name: entry["description"] as string, + bookmark_type: entry[ "type" ] as string, + description: entry[ "description" ] as string, + name: entry[ "description" ] as string, location: BookmarkLocation.Other, - url: entry["description"] as string, - visit_count: entry["visit_count"] as number, + url: entry[ "description" ] as string, + visit_count: entry[ "visit_count" ] as number, path: book_path, version: path.version, - message: entry["description"] as string, + message: entry[ "description" ] as string, datetime: created, timestamp_desc: "Falkon Bookmark File Created", artifact: "KDE Falkon Bookmark", @@ -175,7 +175,6 @@ export class Falkon { } return hits; - } /** @@ -187,12 +186,12 @@ export class Falkon { const limit = 100; while (true) { - let entries = this.history(offset, limit); + const entries = this.history(offset, limit); if (entries.length === 0) { break; } if (!this.unfold) { - entries.forEach(x=> delete x["unfold"]); + entries.forEach(x => delete x[ "unfold" ]); } const status = dumpData(entries, "retrospect_falkon_history", output); if (status instanceof SystemError) { diff --git a/src/linux/kde/falkon/sqlite.ts b/src/linux/kde/falkon/sqlite.ts index 3fe40fad..5e10e515 100644 --- a/src/linux/kde/falkon/sqlite.ts +++ b/src/linux/kde/falkon/sqlite.ts @@ -24,21 +24,19 @@ export function falkonHistory(paths: FalkonProfile[], platform: PlatformType, un continue; } - - // Loop through history rows for (const entry of results) { const history_row: FalkonHistory = { - id: entry["id"] as number, - url: entry["url"] as string, + id: entry[ "id" ] as number, + url: entry[ "url" ] as string, unfold: undefined, db_path: full_path, version: path.version, - title: entry["title"] as string | null, - visited: unixEpochToISO(entry["date"] as number), - count: entry["count"] as number, - message: entry["url"] as string, - datetime: unixEpochToISO(entry["date"] as number), + title: entry[ "title" ] as string | null, + visited: unixEpochToISO(entry[ "date" ] as number), + count: entry[ "count" ] as number, + message: entry[ "url" ] as string, + datetime: unixEpochToISO(entry[ "date" ] as number), timestamp_desc: "Falkon URL Visited", artifact: "KDE Falkon History", data_type: "linux:browser:kde:history:entry" @@ -76,30 +74,30 @@ export function falkonCookie(paths: FalkonProfile[], platform: PlatformType, que // Loop through history rows for (const entry of results) { const history_row: FalkonCookie = { - created: unixEpochToISO(webkitToUnixEpoch(entry["creation_utc"] as number)), - host_key: entry["host_key"] as string, - top_frame_site_key: entry["top_frame_site_key"] as string, - name: entry["name"] as string, - value: entry["value"] as string, - encrypted_value: entry["encrypted_value"] as string, - path: entry["path"] as string, - expires: unixEpochToISO(webkitToUnixEpoch(entry["expires_utc"] as number)), - is_secure: !!(entry["is_secure"] as number), - is_httponly: !!(entry["is_httponly"] as number), - last_access: unixEpochToISO(webkitToUnixEpoch(entry["last_access_utc"] as number)), - has_expires: !!(entry["has_expires"] as number), - is_persistent: !!(entry["is_persistent"] as number), - priority: entry["priority"] as number, - samesite: entry["samesite"] as number, - source_scheme: entry["source_scheme"] as number, - source_port: entry["source_port"] as number, - last_update: unixEpochToISO(webkitToUnixEpoch(entry["last_access_utc"] as number)), - source_type: getChromiumCookieType(entry["source_type"] as number), - has_cross_site_ancestor: !!(entry["has_cross_site_ancestor"] as number), - message: entry["host_key"] as string, + created: unixEpochToISO(webkitToUnixEpoch(entry[ "creation_utc" ] as number)), + host_key: entry[ "host_key" ] as string, + top_frame_site_key: entry[ "top_frame_site_key" ] as string, + name: entry[ "name" ] as string, + value: entry[ "value" ] as string, + encrypted_value: entry[ "encrypted_value" ] as string, + path: entry[ "path" ] as string, + expires: unixEpochToISO(webkitToUnixEpoch(entry[ "expires_utc" ] as number)), + is_secure: !!(entry[ "is_secure" ] as number), + is_httponly: !!(entry[ "is_httponly" ] as number), + last_access: unixEpochToISO(webkitToUnixEpoch(entry[ "last_access_utc" ] as number)), + has_expires: !!(entry[ "has_expires" ] as number), + is_persistent: !!(entry[ "is_persistent" ] as number), + priority: entry[ "priority" ] as number, + samesite: entry[ "samesite" ] as number, + source_scheme: entry[ "source_scheme" ] as number, + source_port: entry[ "source_port" ] as number, + last_update: unixEpochToISO(webkitToUnixEpoch(entry[ "last_access_utc" ] as number)), + source_type: getChromiumCookieType(entry[ "source_type" ] as number), + has_cross_site_ancestor: !!(entry[ "has_cross_site_ancestor" ] as number), + message: entry[ "host_key" ] as string, db_path: full_path, version: path.version, - datetime: unixEpochToISO(webkitToUnixEpoch(entry["creation_utc"] as number)), + datetime: unixEpochToISO(webkitToUnixEpoch(entry[ "creation_utc" ] as number)), timestamp_desc: "Falkon Cookie Created", artifact: "KDE Falkon Cookie", data_type: "linux:browser:kde:cookie:entry" diff --git a/src/linux/logon.ts b/src/linux/logon.ts index cebe0b90..745c647a 100644 --- a/src/linux/logon.ts +++ b/src/linux/logon.ts @@ -13,7 +13,7 @@ export function getLogon(path: string): Logon[] | LinuxError { return new LinuxError("LOGON", `provided non-logon file ${path}`); } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_get_logon(path); return data; diff --git a/src/linux/rpm.ts b/src/linux/rpm.ts index 399444b9..cef4c23e 100644 --- a/src/linux/rpm.ts +++ b/src/linux/rpm.ts @@ -77,6 +77,11 @@ export function getRpmInfo( package_group: "", summary: "", url: "", + message: "", + datetime: "", + timestamp_desc: "RPM Package Installed", + artifact: "RPM Package", + data_type: "linux:rpm:entry" }; // Extract the tag values @@ -135,6 +140,8 @@ export function getRpmInfo( } } + rpm.message = `${rpm.name}-v${rpm.version} installed`; + rpm.datetime = rpm.install_time; rpm_entries.push(rpm); } @@ -202,9 +209,9 @@ enum TagName { DirIndexes = 1116, BaseNames = 1117, DirNames = 1118, - DistUrl = 1023, + DistUrl = 1123, PayloadCompressor = 1125, - PayloadFlags = 1026, + PayloadFlags = 1126, //Private Tag values. All optional HeaderImutable = 63, @@ -225,7 +232,6 @@ enum TagName { OldFileNames = 1027, FileRdevs = 1033, FileModifiedTime = 1034, - FileMD5s = 1035, FileLinkToS = 1036, FileUsername = 1039, FileDevices = 1042, @@ -472,7 +478,7 @@ function extractTagValue( ): string[] | number[] | bigint[] | LinuxError { let count_value = 1; let tag_data = data; - let values: any[] = []; + let values: unknown[] = []; if (data.length < count) { return new LinuxError(`RPMPACKAGES`, `count greater than remaining bytes`); @@ -487,12 +493,12 @@ function extractTagValue( values.push( extractUtf8String(new Uint8Array(value_data)), ); - return values; + return values as string[]; } case TagType.Int8: { const value_data = tag_data.buffer.slice(0, count); values = Array.from(new Uint8Array(value_data)); - return values; + return values as number[]; } case TagType.Int16: { const size = 2; @@ -505,7 +511,7 @@ function extractTagValue( values.push(value_data); count_value++; } - return values; + return values as number[]; } case TagType.Int32: { const size = 4; @@ -518,7 +524,7 @@ function extractTagValue( values.push(value_data); count_value++; } - return values; + return values as number[]; } case TagType.Int64: { const size = 8; @@ -531,7 +537,7 @@ function extractTagValue( values.push(value_data); count_value++; } - return values; + return values as bigint[]; } case TagType.StringArray: case TagType.I18nString: @@ -545,7 +551,7 @@ function extractTagValue( values.push(extractUtf8String(value_data.nommed as Uint8Array)); // Check if we reached end if (value_data.remaining.length === 0) { - return values; + return values as string[]; } const eol = nomUnsignedOneBytes(value_data.remaining as Uint8Array); @@ -557,13 +563,13 @@ function extractTagValue( count_value++; } - return values; + return values as string[]; } case TagType.Bin: { // For binary data, the count is actually the size of the data const value_data = tag_data.buffer.slice(0, count); values.push(encode(new Uint8Array(value_data))); - return values; + return values as string[]; } default: { console.warn(`Unknown TagType ${tag_type} with count ${count}`); diff --git a/src/linux/sqlite/wtmpdb.ts b/src/linux/sqlite/wtmpdb.ts new file mode 100644 index 00000000..32137701 --- /dev/null +++ b/src/linux/sqlite/wtmpdb.ts @@ -0,0 +1,68 @@ +import { LastLogons } from "../../../types/linux/sqlite/wtmpdb"; +import { ApplicationError } from "../../applications/errors"; +import { querySqlite } from "../../applications/sqlite"; +import { unixEpochToISO } from "../../time/conversion"; +import { LinuxError } from "../errors"; + +/** + * Function to query the wtmp sqlite database + * @param alt_path Optional alternative path to wtmp.db + * @returns Array of `LastLogons` or `LinuxError` + */ +export function queryLogons(alt_path?: string): LastLogons[] | LinuxError { + let path = "/var/lib/wtmpdb/wtmp.db"; + if (alt_path !== undefined) { + path = alt_path; + } + + const query = "SELECT id, type, user, login, logout, tty, remotehost, service from wtmp"; + const results = querySqlite(path, query); + if (results instanceof ApplicationError) { + return new LinuxError(`WTMPDB`, `Could not query ${path}: ${results}`); + } + + const values: LastLogons[] = []; + for (const entry of results) { + const logon: LastLogons = { + id: entry[ "ID" ] as number, + type: entry[ "Type" ] as number ?? 0, + user: entry[ "User" ] as string, + login: unixEpochToISO(entry[ "Login" ] as number ?? 0), + logout: unixEpochToISO(entry[ "Logout" ] as number ?? 0), + tty: entry[ "TTY" ] as string ?? "", + remote: entry[ "RemoteHost" ] as string ?? "", + service: entry[ "Service" ] as string ?? "", + message: `Logon by ${entry[ "User" ] as string}`, + datetime: unixEpochToISO(entry[ "Login" ] as number ?? 0), + timestamp_desc: "User Logon", + artifact: "wtmpdb Logons", + data_type: "linux:wtmpdb:entry" + }; + values.push(logon); + } + + return values; +} + +/** + * Function to test WTMPDB parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the WTMPDB parsing + */ +export function testQueryLogons(): void { + const test = "../../test_data/linux/wtmp/wtmp.db"; + const result = queryLogons(test); + if (result instanceof LinuxError) { + throw result; + } + + if (result[ 0 ] === undefined) { + throw `Got logon undefined.......testQueryLogons āŒ`; + } + + if (result[ 0 ].user != "reboot") { + throw `Got extension name ${result[ 0 ].user} expected reboot.......testQueryLogons āŒ`; + } + + console.info(` Function testQueryLogons āœ…`); +} \ No newline at end of file diff --git a/src/linux/sudo.ts b/src/linux/sudo.ts index c14d4b36..8a6b4db0 100644 --- a/src/linux/sudo.ts +++ b/src/linux/sudo.ts @@ -8,7 +8,7 @@ import { LinuxError } from "./errors"; */ export function getSudoLogsLinux(path = ""): Journal[] | LinuxError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_get_sudologs_linux(path); return data; } catch (err) { diff --git a/src/macos/accounts.ts b/src/macos/accounts.ts index 875876df..c89f0306 100644 --- a/src/macos/accounts.ts +++ b/src/macos/accounts.ts @@ -8,7 +8,7 @@ import { MacosError } from "./errors"; */ export function getUsers(path?: string): Users[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_users_macos(path); return data; @@ -24,7 +24,7 @@ export function getUsers(path?: string): Users[] | MacosError { */ export function getGroups(path?: string): Groups[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_groups_macos(path); return data; diff --git a/src/macos/bom.ts b/src/macos/bom.ts index 0c241700..196dda89 100644 --- a/src/macos/bom.ts +++ b/src/macos/bom.ts @@ -10,7 +10,7 @@ import { Bom, BomFiles } from "../../types/macos/bom"; import { extractUtf8String } from "../encoding/mod"; import { FileError } from "../filesystem/errors"; -import { readFile } from "../filesystem/files"; +import { readFile, readTextFile } from "../filesystem/files"; import { NomError } from "../nom/error"; import { Endian, @@ -182,12 +182,12 @@ export function parseReceipt(path: string): Bom | MacosError { const receipt = plist_data as Record; const bom: Bom = { - package_name: receipt[ "PackageFileName" ] ?? "", - install_data: receipt[ "InstallDate" ] ?? "", - package_id: receipt[ "PackageIdentifier" ] ?? "", - package_version: receipt[ "PackageVersion" ] ?? "", - install_process_name: receipt[ "InstallProcessName" ] ?? "", - install_prefix_path: receipt[ "InstallPrefixPath" ] ?? "", + package_name: receipt["PackageFileName"] ?? "", + install_data: receipt["InstallDate"] ?? "", + package_id: receipt["PackageIdentifier"] ?? "", + package_version: receipt["PackageVersion"] ?? "", + install_process_name: receipt["InstallProcessName"] ?? "", + install_prefix_path: receipt["InstallPrefixPath"] ?? "", path, bom_path: "", files: [], @@ -204,6 +204,7 @@ interface Header { var_offset: number; var_length: number; } + /** * Parse the Header of the BOM file * @param data raw BOM bytes @@ -418,7 +419,7 @@ function getBlock( return new MacosError("BOM", `index greater than pointers length`); } - const pointer = pointers[ index ]; + const pointer = pointers[index]; if (pointer === undefined) { return new MacosError("BOM", `got undefined pointer`); } @@ -841,7 +842,7 @@ function assembleBom(files: Map): BomFiles[] { const boms: BomFiles[] = []; const root = 0; - for (const [ key, value ] of files) { + for (const [key, value] of files) { // Root directory if (key === root) { continue; @@ -874,3 +875,208 @@ function assembleBom(files: Map): BomFiles[] { return boms; } + + +export function testParseBom(): void { + const bom_test = "../../test_data/macos/bom/io.osquery.agent.bom"; + const results = parseBom(bom_test); + if (results instanceof MacosError) { + throw console.log(results); + } + + if (results.files.length !== 266) { + throw `Got ${results.files.length} wanted "266".......parseBom āŒ`; + } + + if (results.files[3]?.path !== "./usr") { + throw `Got ${results.files[3]?.path} wanted "./usr".......parseBom āŒ`; + } + console.info(` Function parseBom āœ…`); + + const test = "../../test_data/macos/bom/io.osquery.agent.plist"; + const recpeit = parseReceipt(test); + if (recpeit instanceof MacosError) { + throw console.log(recpeit); + } + + if (recpeit.package_id !== "io.osquery.agent") { + throw `Got ${recpeit.package_id} wanted "io.osquery.agent".......parseReceipt āŒ`; + } + console.info(` Function parseReceipt āœ…`); + + const data = readFile(bom_test); + if (data instanceof FileError) { + throw console.log(data); + } + + const header = parseHeader(data); + if (header instanceof MacosError) { + throw console.log(header); + } + + if (header.index_table_offset != 53928) { + throw `Got ${header.index_table_offset} wanted "53928".......parseHeader āŒ`; + } + + if (header.sig != 4778122750494470757n) { + throw `Got ${header.sig} wanted "4778122750494470757".......parseHeader āŒ`; + } + console.info(` Function parseHeader āœ…`); + + const pointers = "../../test_data/macos/bom/pointers.raw"; + const point_data = readFile(pointers); + if (point_data instanceof FileError) { + throw console.log(point_data); + } + + const point_info = getPointers(point_data); + if (point_info instanceof MacosError) { + throw console.log(point_info); + } + + if (point_info.pointers.length != 2730) { + throw `Got ${point_info.pointers.length} wanted "2730".......getPointers āŒ`; + } + + if (point_info.pointers[280]?.address != 18646) { + throw `Got ${point_info.pointers[280]?.address} wanted "18646".......getPointers āŒ`; + } + + console.info(` Function getPointers āœ…`); + + const vars = "../../test_data/macos/bom/vars.raw"; + const vars_data = readFile(vars); + if (vars_data instanceof FileError) { + throw console.log(vars_data); + } + + const vars_info = getVars(vars_data); + if (vars_info instanceof MacosError) { + throw console.log(vars_info); + } + + if (vars_info.vars.length != 5) { + throw `Got ${vars_info.vars.length} wanted "5".......getVars āŒ`; + } + + if (vars_info.vars[3]?.name != "VIndex") { + throw `Got ${vars_info.vars[3]?.name} wanted "VIndex".......getVars āŒ`; + } + + console.info(` Function getVars āœ…`); + + const block = getBlock(data, 2, point_info.pointers); + if (block instanceof MacosError) { + throw console.log(block); + } + + if (block.byteLength !== 21) { + throw `Got ${block.byteLength} wanted "21".......getBlock āŒ`; + } + console.info(` Function getBlock āœ…`); + + const tree_entry = parseTreeEntry(data, 2, point_info.pointers); + if (tree_entry instanceof MacosError) { + throw console.log(tree_entry); + } + + if (tree_entry.path_count !== 266) { + throw `Got ${tree_entry.path_count} wanted "266".......parseTreeEntry āŒ`; + } + console.info(` Function parseTreeEntry āœ…`); + + + const tree = parseTree(data, 3, point_info.pointers); + if (tree instanceof MacosError) { + throw console.log(tree); + } + + if (!tree.is_leaf) { + throw `Got ${tree.is_leaf} wanted "false".......parseTree āŒ`; + } + console.info(` Function parseTree āœ…`); + + const index = "../../test_data/macos/bom/tree_index.raw"; + const index_data = readFile(index); + if (index_data instanceof FileError) { + throw console.log(index_data); + } + + const index_info = parseTreeIndex(index_data); + if (index_info instanceof MacosError) { + throw console.log(index_info); + } + + if (index_info.tree_index.value_index != 13) { + throw `Got ${index_info.tree_index.value_index} wanted "13".......parseTreeIndex āŒ`; + } + if (index_info.tree_index.key_index != 12) { + throw `Got ${index_info.tree_index.key_index} wanted "12".......parseTreeIndex āŒ`; + } + console.info(` Function parseTreeIndex āœ…`); + + const file = getFile(new Uint8Array([0, 0, 0, 26, 103, 114, 117, 98, 101, 110, 118, 46, 97, 117, 103, 0])); + if (file instanceof MacosError) { + throw console.log(file); + } + + if (file.name !== "grubenv.aug") { + throw `Got ${file.name} wanted "grubenv.aug".......getFile āŒ`; + } + if (file.parent !== 26) { + throw `Got ${file.parent} wanted "26".......getFile āŒ`; + } + console.info(` Function getFile āœ…`); + + const path = getPath(new Uint8Array([0, 0, 0, 1, 0, 0, 0, 11])); + if (path instanceof MacosError) { + throw console.log(path); + } + + if (path.id !== 1) { + throw `Got ${path.id} wanted "1".......getPath āŒ`; + } + if (path.index !== 11) { + throw `Got ${path.index} wanted "11".......getPath āŒ`; + } + console.info(` Function getPath āœ…`); + + const path_info = getPathInfo(data, 11, point_info.pointers); + if (path_info instanceof MacosError) { + throw console.log(path_info); + } + + if (path_info.type !== PathType.DIR) { + throw `Got ${path_info.type} wanted "DIRECTORY".......getPathInfo āŒ`; + } + + if (path_info.size !== 160) { + throw `Got ${path_info.size} wanted "160".......getPathInfo āŒ`; + } + console.info(` Function getPathInfo āœ…`); + + const types = [1, 2, 3, 4]; + for (const entry of types) { + if (getType(entry) === PathType.UNKNOWN) { + throw `Got Unknown type!.......getType āŒ` + } + } + console.info(` Function getType āœ…`); + + + const json = "../../test_data/macos/bom/bom.json"; + const json_data = readTextFile(json); + if (json_data instanceof FileError) { + throw console.log(json_data); + } + + const bom = assembleBom(new Map(Object.entries(JSON.parse(json_data)) as unknown as Map)) + if (bom instanceof MacosError) { + throw console.log(bom); + } + if (bom.length !== 266) { + throw `Got ${results.files.length} wanted "266".......assembleBom āŒ`; + } + console.info(` Function assembleBom āœ…`); + +} \ No newline at end of file diff --git a/src/macos/bookmark.ts b/src/macos/bookmark.ts index 239162d8..ec49352f 100644 --- a/src/macos/bookmark.ts +++ b/src/macos/bookmark.ts @@ -8,7 +8,7 @@ import { MacosError } from "./errors"; */ export function parseBookmark(data: Uint8Array): BookmarkData | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const results = js_bookmark(data); return results; } catch (err) { diff --git a/src/macos/emond.ts b/src/macos/emond.ts index 3acf9633..4f65aedf 100644 --- a/src/macos/emond.ts +++ b/src/macos/emond.ts @@ -8,7 +8,7 @@ import { MacosError } from "./errors"; */ export function getEmond(path?: string): Emond[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_emond(path); return data; diff --git a/src/macos/execpolicy.ts b/src/macos/execpolicy.ts index c944a780..a9d54e9b 100644 --- a/src/macos/execpolicy.ts +++ b/src/macos/execpolicy.ts @@ -8,7 +8,7 @@ import { MacosError } from "./errors"; */ export function getExecpolicy(path?: string): ExecPolicy[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_execpolicy(path); return data; diff --git a/src/macos/fsevents.ts b/src/macos/fsevents.ts index 60fadf09..d00e1b35 100644 --- a/src/macos/fsevents.ts +++ b/src/macos/fsevents.ts @@ -8,7 +8,7 @@ import { MacosError } from "./errors"; */ export function getFsevents(path: string): Fsevents[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_fsevents(path); return data; } catch (err) { diff --git a/src/macos/homebrew.ts b/src/macos/homebrew.ts index 84e57b1f..9d27d367 100644 --- a/src/macos/homebrew.ts +++ b/src/macos/homebrew.ts @@ -38,7 +38,7 @@ export function getPackages(glob_path?: string): HomebrewReceipt[] { // Use user provided glob path if (glob_path !== undefined) { - paths = [glob_path]; + paths = [ glob_path ]; } const brew_receipts: HomebrewReceipt[] = []; @@ -109,12 +109,12 @@ export function getPackages(glob_path?: string): HomebrewReceipt[] { } const receipt_data = JSON.parse(receipt); - brew_info.installTime = unixEpochToISO(receipt_data["time"]); + brew_info.installTime = unixEpochToISO(receipt_data[ "time" ]); brew_info.installedAsDependency = - receipt_data["installed_as_dependency"]; - brew_info.installedOnRequest = receipt_data["installed_on_request"]; + receipt_data[ "installed_as_dependency" ]; + brew_info.installedOnRequest = receipt_data[ "installed_on_request" ]; brew_info.sourceModified = unixEpochToISO( - receipt_data["source_modified_time"], + receipt_data[ "source_modified_time" ], ); } @@ -139,7 +139,7 @@ export function getCasks(glob_path?: string): HomebrewFormula[] { ]; if (glob_path !== undefined) { - paths = [glob_path]; + paths = [ glob_path ]; } const casks: HomebrewFormula[] = []; @@ -163,13 +163,13 @@ export function getCasks(glob_path?: string): HomebrewFormula[] { const data = JSON.parse(text); const formula: HomebrewFormula = { - description: data["desc"], - homepage: data["homepage"], - url: data["url"], + description: data[ "desc" ], + homepage: data[ "homepage" ], + url: data[ "url" ], license: "", - caskName: data["name"].join(" "), + caskName: data[ "name" ].join(" "), formulaPath: entry.full_path, - version: data["version"], + version: data[ "version" ], }; casks.push(formula); } @@ -205,9 +205,9 @@ function parseRuby(path: string): HomebrewFormula | FileError { const versionvalue = path.split("/"); let version = ""; if (path.includes("/Casks/")) { - version = versionvalue[versionvalue.length - 4] ?? ""; + version = versionvalue[ versionvalue.length - 4 ] ?? ""; } else { - version = versionvalue[versionvalue.length - 3] ?? ""; + version = versionvalue[ versionvalue.length - 3 ] ?? ""; } const rubyText = readTextFile(path); @@ -225,28 +225,28 @@ function parseRuby(path: string): HomebrewFormula | FileError { formulaPath: path, version, }; - if (typeof description?.[0] === "string") { - receipt.description = description?.[0].replaceAll('"', ""); + if (typeof description?.[ 0 ] === "string") { + receipt.description = description?.[ 0 ].replaceAll('"', ""); } const homepage = rubyText.match(homepage_reg); - if (typeof homepage?.[0] === "string") { - receipt.homepage = homepage?.[0].replaceAll('"', ""); + if (typeof homepage?.[ 0 ] === "string") { + receipt.homepage = homepage?.[ 0 ].replaceAll('"', ""); } const license = rubyText.match(reg_license); - if (typeof license?.[0] === "string") { - receipt.license = license?.[0].replaceAll('"', ""); + if (typeof license?.[ 0 ] === "string") { + receipt.license = license?.[ 0 ].replaceAll('"', ""); } const url = rubyText.match(reg_url); - if (typeof url?.[0] === "string") { - receipt.url = url?.[0].replaceAll('"', ""); + if (typeof url?.[ 0 ] === "string") { + receipt.url = url?.[ 0 ].replaceAll('"', ""); } const name = rubyText.match(reg_name); - if (typeof name?.[0] === "string" && path.includes("Cask")) { - receipt.caskName = name?.[0].replaceAll('"', ""); + if (typeof name?.[ 0 ] === "string" && path.includes("Cask")) { + receipt.caskName = name?.[ 0 ].replaceAll('"', ""); } return receipt; @@ -259,36 +259,36 @@ function parseRuby(path: string): HomebrewFormula | FileError { */ export function testHomebrew(): void { const install = "../../test_data/macos/homebrew/INSTALL_RECEIPT.json"; - let results = getPackages(install); + const results = getPackages(install); - if (results.length !== 1 || results[0] === undefined) { + if (results.length !== 1 || results[ 0 ] === undefined) { throw `Got ${results.length} expected 1.......getPackages āŒ`; } - if (results[0].name != "typescript") { - throw `Got ${results[0].name} expected typescript.......getPackages āŒ`; + if (results[ 0 ].name != "typescript") { + throw `Got ${results[ 0 ].name} expected typescript.......getPackages āŒ`; } console.info(` Function getPackages āœ…`); const casks = "../../test_data/macos/homebrew/casks/.metadata/*/*/Casks/*"; - let results_casks = getCasks(casks); + const results_casks = getCasks(casks); - if (results_casks.length !== 1 || results_casks[0] === undefined) { + if (results_casks.length !== 1 || results_casks[ 0 ] === undefined) { throw `Got ${results_casks.length} expected 1.......getCasks āŒ`; } - if (results_casks[0].caskName != "DuckDuckGo") { - throw `Got ${results_casks[0].caskName} expected DuckDuckGo.......getCasks āŒ`; + if (results_casks[ 0 ].caskName != "DuckDuckGo") { + throw `Got ${results_casks[ 0 ].caskName} expected DuckDuckGo.......getCasks āŒ`; } console.info(` Function getCasks āœ…`); const ruby = "../../test_data/macos/homebrew/.brew/typescript.rb"; - let results_ruby = parseRuby(ruby); - if(results_ruby instanceof FileError) { + const results_ruby = parseRuby(ruby); + if (results_ruby instanceof FileError) { throw results; } diff --git a/src/macos/launchd.ts b/src/macos/launchd.ts index d3e215dc..f7763898 100644 --- a/src/macos/launchd.ts +++ b/src/macos/launchd.ts @@ -7,7 +7,7 @@ import { MacosError } from "./errors"; */ export function getLaunchdDaemons(): Launchd[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_launchd_daemons(); return data; @@ -22,7 +22,7 @@ export function getLaunchdDaemons(): Launchd[] | MacosError { */ export function getLaunchdAgents(): Launchd[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_launchd_agents(); return data; diff --git a/src/macos/loginitems.ts b/src/macos/loginitems.ts index 6da0d1ff..c711bafd 100644 --- a/src/macos/loginitems.ts +++ b/src/macos/loginitems.ts @@ -8,7 +8,7 @@ import { MacosError } from "./errors"; */ export function getLoginitems(path?: string): LoginItems[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_loginitems(path); return data; diff --git a/src/macos/macho.ts b/src/macos/macho.ts index b0e09b2b..6986d9f7 100644 --- a/src/macos/macho.ts +++ b/src/macos/macho.ts @@ -8,7 +8,7 @@ import { MacosError } from "./errors"; */ export function getMacho(path: string): MachoInfo[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_macho(path); return data; } catch (err) { diff --git a/src/macos/plist.ts b/src/macos/plist.ts index 9d342788..f0017027 100644 --- a/src/macos/plist.ts +++ b/src/macos/plist.ts @@ -16,7 +16,7 @@ export function getPlist( // Parse bytes containing plist data if (path instanceof Uint8Array) { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_plist_data(path); const plist_data: Record | number[] | Record< @@ -30,7 +30,7 @@ export function getPlist( } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_plist(path); const plist_data: Record | number[] | Record< string, diff --git a/src/macos/plist/apps.ts b/src/macos/plist/apps.ts index 8286971c..167635a4 100644 --- a/src/macos/plist/apps.ts +++ b/src/macos/plist/apps.ts @@ -7,11 +7,12 @@ import { parseIcon } from "../../images/icns"; import { MacosError } from "../errors"; /** - * Returns a very simple App listing on the system. Searches user installed Apps, System Apps, default Homebrew paths (/usr/local/Cellar, /opt/homebrew/Cellar). + * Returns a very simple App listing on the system. Searches user installed Apps, System Apps, default Homebrew paths (/usr/local/Cellar, /opt/homebrew/Cellar). * Use `scanApps()` if you want to scan the entire filesystem for Apps + * @param [skip_icon=false] Skip parsing of the App icon. Default is false * @returns Array of `Applications` */ -export function listApps(): Applications[] { +export function listApps(skip_icon = false): Applications[] { const app_paths = [ "/Applications/*/Contents/Info.plist", "/System/Applications/*/Contents/Info.plist", @@ -20,7 +21,7 @@ export function listApps(): Applications[] { ]; let all_apps: Applications[] = []; for (const path of app_paths) { - const results = getApps(path); + const results = getApps(path, skip_icon); if (results instanceof MacosError) { continue; } @@ -32,11 +33,12 @@ export function listApps(): Applications[] { /** * Scans the entire filesystem under /System and tries to parse all Applications. Includes embedded Apps, Frameworks, and any file that ends with `%/Contents/Info.plist` + * @param [skip_icon=false] Skip parsing of the App icon. Default is false * @returns Array of `Applications` */ -export async function scanApps(): Promise { +export async function scanApps(skip_icon = false): Promise { const apps: Applications[] = []; - await iterateVolumes("/System", apps); + await iterateVolumes("/System", apps, skip_icon); return apps; } @@ -45,8 +47,9 @@ export async function scanApps(): Promise { * Walk the entire filesystem to look for Applications * @param path Path to read * @param apps Array of `Applications` to track + * @param skip_icon Skip parsing of the App icon data */ -async function iterateVolumes(path: string, apps: Applications[]) { +async function iterateVolumes(path: string, apps: Applications[], skip_icon: boolean) { const entries = await readDir(path); if (entries instanceof FileError) { return; @@ -55,7 +58,7 @@ async function iterateVolumes(path: string, apps: Applications[]) { for (const entry of entries) { if (entry.full_path.endsWith("Contents/Info.plist") && entry.is_file) { try { - const app = parsePlist(entry.full_path); + const app = parsePlist(entry.full_path, skip_icon); if (app instanceof Error) { continue; } @@ -67,7 +70,7 @@ async function iterateVolumes(path: string, apps: Applications[]) { } if (entry.is_directory) { - await iterateVolumes(entry.full_path, apps); + await iterateVolumes(entry.full_path, apps, skip_icon); } } } @@ -75,16 +78,17 @@ async function iterateVolumes(path: string, apps: Applications[]) { /** * Get Application information by parse `Info.plist` file * @param path Path to glob for applications + * @param skip_icon Skip parsing the App icon data * @returns Array of `Applications` or `MacosError` */ -function getApps(path: string): Applications[] | MacosError { +function getApps(path: string, skip_icon: boolean): Applications[] | MacosError { const glob_paths = glob(path); if (glob_paths instanceof FileError) { return new MacosError(`PLIST`, `Failed to glob for plists: ${glob_paths}`); } const apps: Applications[] = []; for (const entry of glob_paths) { - const app = parsePlist(entry.full_path); + const app = parsePlist(entry.full_path, skip_icon); if (app instanceof MacosError) { continue; } @@ -96,9 +100,10 @@ function getApps(path: string): Applications[] | MacosError { /** * Parse the `Info.plist` file * @param path Path to `Info.plist` + * @param skip_icon Skip parsing the App icon data * @returns `Applications` info or error */ -function parsePlist(path: string): Applications | MacosError { +function parsePlist(path: string, skip_icon: boolean): Applications | MacosError { let data = getPlist(path); if (data instanceof Error || data instanceof Uint8Array) { console.error(`Failed to parse plist ${path}: ${data}`); @@ -131,7 +136,7 @@ function parsePlist(path: string): Applications | MacosError { bundle_version: `${data[ "CFBundleVersion" ]}`, display_name: `${data[ "CFBundleExecutable" ]}`, copyright: `${data[ "NSHumanReadableCopyright" ]}`, - icon: readIcon(icon_file), + icon: !skip_icon ? readIcon(icon_file) : "", info: path, }; diff --git a/src/macos/plist/docktile.ts b/src/macos/plist/docktile.ts index c4b393eb..9a8f0310 100644 --- a/src/macos/plist/docktile.ts +++ b/src/macos/plist/docktile.ts @@ -8,7 +8,8 @@ import { scanApps } from "./apps"; * @returns Array of `Applications` that contain DockTile entries */ export async function dockTiles(): Promise { - const apps = await scanApps(); + const skip_icons = true; + const apps = await scanApps(skip_icons); const dockTileApps = checkDockPersistence(apps); return dockTileApps; @@ -33,8 +34,9 @@ function checkDockPersistence(apps: Applications[]): Applications[] { continue; } + const check = JSON.stringify(data).toLowerCase(); // Easy way to check for any DockTile Plugins - if (!JSON.stringify(data).toLowerCase().includes("docktileplugin")) { + if (!check.includes("docktileplugin") && !check.includes("docktile")) { continue; } diff --git a/src/macos/plist/firewall.ts b/src/macos/plist/firewall.ts index 444099d6..e970f58a 100644 --- a/src/macos/plist/firewall.ts +++ b/src/macos/plist/firewall.ts @@ -45,7 +45,7 @@ export function firewallStatus(alt_path?: string): Firewall[] | MacosError { global_state: !!results[ "globalstate" ], logging_option: !!results[ "loggingoption" ], stealth_enabled: !!results[ "stealthenabled" ], - version: results[ "version" ], + version: results[ "version" ] ?? "", applications: [], exceptions: [], explict_auths: [], @@ -147,8 +147,8 @@ function parseApplications( } // If we have the raw bytes, now parse the `alias` info - if (embedded_plist instanceof Array) { - const raw_bytes = Uint8Array.from(embedded_plist); + if (Array.isArray(embedded_plist)) { + const raw_bytes = Uint8Array.from(embedded_plist as number[]); const alias_result = parseAlias(raw_bytes); if (alias_result instanceof MacosError) { console.error( @@ -222,7 +222,7 @@ function getServices(services: Record): Services[] { function getAuths(auths: Record[]): string[] { const entries: string[] = []; for (const auth of auths) { - entries.push(auth[ "id" ]); + entries.push(auth[ "id" ] ?? ""); } return entries; } diff --git a/src/macos/plist/lulu.ts b/src/macos/plist/lulu.ts index b8188cd7..d16d78a8 100644 --- a/src/macos/plist/lulu.ts +++ b/src/macos/plist/lulu.ts @@ -33,6 +33,9 @@ export function luluRules(alt_file?: string): LuluRules | MacosError { }; const object_data = objects[ "$objects" ]; + if (object_data === undefined) { + return new MacosError(`LULU`, `Got undefined for LuLu FW objects`); + } for (const entry of object_data) { if (typeof entry !== "object") { continue; @@ -106,7 +109,11 @@ function getCodeSigning( } for (let i = 0; i < data[ "NS.keys" ].length; i++) { - const key = objects.at(data[ "NS.keys" ][ i ]) as string ?? `${i}`; + const ns_value = data[ "NS.keys" ][ i ]; + if (ns_value === undefined) { + continue; + } + const key = objects.at(ns_value) as string ?? `${i}`; const value_key = data[ "NS.objects" ].at(i); if (value_key === undefined) { @@ -129,8 +136,12 @@ function getCodeSigning( } const entries: string[] = []; + const object_values = value[ "NS.objects" ]; + if (object_values === undefined) { + continue; + } // more NS.Objects - for (const entry of value[ "NS.objects" ]) { + for (const entry of object_values) { const lulu_value = objects.at(entry) as string ?? `${entry}`; entries.push(lulu_value); } diff --git a/src/macos/plist/policies.ts b/src/macos/plist/policies.ts index eda6e697..9a833a92 100644 --- a/src/macos/plist/policies.ts +++ b/src/macos/plist/policies.ts @@ -51,7 +51,7 @@ export function passwordPolicy( const pass_policy: PasswordPolicy = { policy_id: policy_entry[ "policyIdentifier" ] as string, policy_content: policy_entry[ "policyContent" ] as string, - policy_description: policy_description[ "en" ], + policy_description: policy_description[ "en" ] ?? "", }; policies.push(pass_policy); } diff --git a/src/macos/plist/system_extensions.ts b/src/macos/plist/system_extensions.ts index 1a593e53..3ba4d398 100644 --- a/src/macos/plist/system_extensions.ts +++ b/src/macos/plist/system_extensions.ts @@ -24,7 +24,7 @@ export function systemExtensions( const exts: SystemExtension[] = []; for (const entry in plist_data) { - if (entry !== "extensions") { + if (entry !== "extensions" || Array.isArray(plist_data)) { continue; } @@ -37,9 +37,9 @@ export function systemExtensions( uuid: ext[ "uniqueID" ] as string, state: ext[ "state" ] as string, id: ext[ "identifier" ] as string, - version: ver[ "CFBundleVersion" ], + version: ver[ "CFBundleVersion" ] ?? "", categories: ext[ "categories" ] as string[], - bundle_path: bundle[ "bundlePath" ], + bundle_path: bundle[ "bundlePath" ] ?? "", team: ext[ "teamID" ] as string, }; exts.push(sys_ext); diff --git a/src/macos/plist/wifi.ts b/src/macos/plist/wifi.ts index a2d43b27..0586bd6e 100644 --- a/src/macos/plist/wifi.ts +++ b/src/macos/plist/wifi.ts @@ -39,20 +39,24 @@ function parseWifi(path: string): Wifi[] { const wifis: Wifi[] = []; for (const entry in wifi_data) { + const value = wifi_data[ entry ]; + if (value === undefined) { + continue; + } const wifi_value: Wifi = { name: entry.replace("wifi.network.ssid.", ""), - security: wifi_data[ entry ].SupportedSecurityTypes, - hidden: wifi_data[ entry ].Hidden, - roaming_profile: wifi_data[ entry ].__OSSpecific__.RoamingProfileType, - add_reason: wifi_data[ entry ].AddReason, - added_at: wifi_data[ entry ].AddedAt, - auto_join: wifi_data[ entry ].AutoJoinDisabled, - personal_hotspot: (wifi_data[ entry ].PersonalHotspot === undefined) + security: value.SupportedSecurityTypes, + hidden: value.Hidden, + roaming_profile: value.__OSSpecific__.RoamingProfileType, + add_reason: value.AddReason, + added_at: value.AddedAt, + auto_join: value.AutoJoinDisabled, + personal_hotspot: (value.PersonalHotspot === undefined) ? false - : wifi_data[ entry ].PersonalHotspot as boolean, - joined_by_user_at: wifi_data[ entry ].JoinedByUserAt, - last_discovered: wifi_data[ entry ].LastDiscoveredAt, - updated_at: wifi_data[ entry ].UpdatedAt, + : value.PersonalHotspot as boolean, + joined_by_user_at: value.JoinedByUserAt, + last_discovered: value.LastDiscoveredAt, + updated_at: value.UpdatedAt, }; wifis.push(wifi_value); } diff --git a/src/macos/plist/xprotect.ts b/src/macos/plist/xprotect.ts index f7305cb5..586b4abb 100644 --- a/src/macos/plist/xprotect.ts +++ b/src/macos/plist/xprotect.ts @@ -65,7 +65,7 @@ function extractXprotectEntries( break; case "LaunchServices": { const launch = xprotect[ key ] as Record; - entry.launch_type = launch[ "LSItemContentType" ]; + entry.launch_type = launch[ "LSItemContentType" ] ?? ""; break; } case "Matches": diff --git a/src/macos/safari/cookies.ts b/src/macos/safari/cookies.ts index 0c4a68fd..62811710 100644 --- a/src/macos/safari/cookies.ts +++ b/src/macos/safari/cookies.ts @@ -23,12 +23,12 @@ export function safariCookies(paths: SafariProfile[], platform: PlatformType): C } const cookie = parseCookies(full_path); - if(cookie instanceof MacosError) { + if (cookie instanceof MacosError) { console.warn(`failed to parse Safari cookie ${full_path}: ${cookie}`); continue; } - cookie.forEach(x => x["version"] = path.version); + cookie.forEach(x => x[ "version" ] = path.version); hits = hits.concat(cookie); } @@ -68,13 +68,13 @@ export function parseCookies(path: string): Cookie[] | MacosError { let cookies: Cookie[] = []; let remaining = header.remaining_bytes; for (let i = 0; i < header.pages_count; i++) { - const page_size = header.page_sizes[i]; - if(page_size === undefined) { + const page_size = header.page_sizes[ i ]; + if (page_size === undefined) { continue; } const page_bytes = take(remaining, page_size); - if(page_bytes instanceof NomError) { + if (page_bytes instanceof NomError) { continue; } remaining = page_bytes.remaining as Uint8Array; @@ -243,7 +243,7 @@ function parseRecord(data: Uint8Array): Cookie | NomError { const value_offset = input.value; // Unknown - let unknown = nomUnsignedEightBytes(input.remaining, Endian.Le); + const unknown = nomUnsignedEightBytes(input.remaining, Endian.Le); if (unknown instanceof NomError) { return unknown; } @@ -315,7 +315,7 @@ function extractOffsets(data: Uint8Array, offset: number): string | NomError { return start; } - const string_data = takeUntil(start.remaining, Uint8Array.from([0])); + const string_data = takeUntil(start.remaining, Uint8Array.from([ 0 ])); if (string_data instanceof NomError) { return string_data; } diff --git a/src/macos/safari/safari.ts b/src/macos/safari/safari.ts index 2f0d936c..cce257d2 100644 --- a/src/macos/safari/safari.ts +++ b/src/macos/safari/safari.ts @@ -21,7 +21,7 @@ export class Safari { * @param alt_path Optional alternative path to directory containing Safari data * @returns `Safari` instance class */ - constructor(platform: PlatformType, unfold = false, alt_path?: string) { + constructor (platform: PlatformType, unfold = false, alt_path?: string) { this.unfold = unfold; this.platform = platform; if (alt_path === undefined) { @@ -33,11 +33,11 @@ export class Safari { return; } - this.paths = [{ + this.paths = [ { full_path: alt_path, container_path: alt_path, version: 0 - }]; + } ]; } @@ -126,12 +126,12 @@ export class Safari { const limit = 100; while (true) { - let entries = this.history(offset, limit); + const entries = this.history(offset, limit); if (entries.length === 0) { break; } if (!this.unfold) { - entries.forEach(x => delete x["unfold"]); + entries.forEach(x => delete x[ "unfold" ]); } const status = dumpData(entries, "retrospect_safari_history", output); if (status instanceof SystemError) { @@ -142,7 +142,7 @@ export class Safari { offset = 0; while (true) { - let entries = this.favicons(offset, limit); + const entries = this.favicons(offset, limit); if (entries.length === 0) { break; } @@ -162,22 +162,22 @@ export class Safari { } - let entries = this.bookmarks(); + const entries = this.bookmarks(); status = dumpData(entries, "retrospect_safari_bookmarks", output); if (status instanceof SystemError) { console.error(`Failed timeline Safari bookmarks: ${status}`); } - let downs = this.downloads(); + const downs = this.downloads(); if (!this.unfold) { - downs.forEach(x => delete x["unfold"]); + downs.forEach(x => delete x[ "unfold" ]); } status = dumpData(downs, "retrospect_safari_downloads", output); if (status instanceof SystemError) { console.error(`Failed timeline Safari downloads: ${status}`); } - let exts = this.extensions(); + const exts = this.extensions(); status = dumpData(exts, "retrospect_safari_extensions", output); if (status instanceof SystemError) { console.error(`Failed timeline Safari extensions: ${status}`); @@ -228,7 +228,7 @@ export class Safari { return new MacosError(`SAFARI`, `got array for Safari Info.plist`); } - const version = info["CFBundleShortVersionString"] as string; + const version = info[ "CFBundleShortVersionString" ] as string; return Number(version); } } \ No newline at end of file diff --git a/src/macos/spotlight.ts b/src/macos/spotlight.ts index c4b3a778..41067d30 100644 --- a/src/macos/spotlight.ts +++ b/src/macos/spotlight.ts @@ -10,7 +10,7 @@ export function setupSpotlightParser( glob_path: string, ): StoreMeta | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_setup_spotlight_parser(glob_path); return data; } catch (err) { @@ -43,7 +43,7 @@ export function getSpotlight( } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_spotlight( store_file, meta, diff --git a/src/macos/sudo.ts b/src/macos/sudo.ts index af777c88..d007d8c5 100644 --- a/src/macos/sudo.ts +++ b/src/macos/sudo.ts @@ -10,7 +10,7 @@ export function getSudoLogsMacos( path?: string, ): UnifiedLog[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_sudologs_macos(path); return data; diff --git a/src/macos/unifiedlogs.ts b/src/macos/unifiedlogs.ts index 1303950d..0ccd9c1b 100644 --- a/src/macos/unifiedlogs.ts +++ b/src/macos/unifiedlogs.ts @@ -12,7 +12,7 @@ export function getUnifiedLog( archive_path?: string, ): UnifiedLog[] | MacosError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_unified_log(path, archive_path); return data; diff --git a/src/nom/parsers.ts b/src/nom/parsers.ts index 44238457..bf7bf926 100644 --- a/src/nom/parsers.ts +++ b/src/nom/parsers.ts @@ -39,7 +39,7 @@ export function takeUntil( if (typeof data === "string" && typeof input === "string") { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_nom_take_until_string( data, input, @@ -51,7 +51,7 @@ export function takeUntil( } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_nom_take_until_bytes( data, input, @@ -89,7 +89,7 @@ export function takeWhile( if (typeof data === "string" && typeof input === "string") { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result: Nom = js_nom_take_while_string( data, input, @@ -101,7 +101,7 @@ export function takeWhile( } } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_nom_take_while_bytes( data, input, diff --git a/src/system/command.ts b/src/system/command.ts index 84338fe0..1fa3502c 100644 --- a/src/system/command.ts +++ b/src/system/command.ts @@ -10,7 +10,7 @@ export function executeCommand( command: string, args: string[] = [], ): CommandResult | Error { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: CommandResult | Error = js_command(command, args); if (data instanceof Error) { return data; diff --git a/src/system/cpu.ts b/src/system/cpu.ts index ebeaab91..176218bb 100644 --- a/src/system/cpu.ts +++ b/src/system/cpu.ts @@ -5,7 +5,7 @@ import { Cpus } from "../../types/system/systeminfo"; * @returns Array of CPU information on system */ export function cpus(): Cpus[] { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Cpus[] = js_cpu(); return data; } diff --git a/src/system/disks.ts b/src/system/disks.ts index 0f742fdb..31c567e5 100644 --- a/src/system/disks.ts +++ b/src/system/disks.ts @@ -5,7 +5,7 @@ import { Disks } from "../../types/system/systeminfo"; * @returns Array of `Disk` information */ export function disks(): Disks[] { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Disks[] = js_disks(); return data; } diff --git a/src/system/memory.ts b/src/system/memory.ts index 7ee4282c..71a80836 100644 --- a/src/system/memory.ts +++ b/src/system/memory.ts @@ -7,7 +7,7 @@ import { Connection } from "../../types/system/connections"; * @returns `Memory` information on the system */ export function memory(): Memory { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Memory = js_memory(); return data; } @@ -31,7 +31,7 @@ export function processListing( sha1, sha256, }; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: ProcessInfo[] = js_get_processes( hashes, binary, @@ -45,7 +45,7 @@ export function processListing( * @returns Array of `Connection` */ export function connections(): Connection[] { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Connection[] = js_connections(); return data; diff --git a/src/system/output.ts b/src/system/output.ts index 70f601f8..82e593ac 100644 --- a/src/system/output.ts +++ b/src/system/output.ts @@ -54,7 +54,7 @@ export function outputResults( output: Output, ): boolean | SystemError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const status: boolean = js_output_results( data, data_name, @@ -79,7 +79,7 @@ export function dumpData( output: Output, ): boolean | SystemError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const status: boolean = js_raw_dump( data, data_name, diff --git a/src/system/systeminfo.ts b/src/system/systeminfo.ts index 9cc4e583..fa1b2256 100644 --- a/src/system/systeminfo.ts +++ b/src/system/systeminfo.ts @@ -5,7 +5,7 @@ import { SystemInfo } from "../../types/system/systeminfo"; * @returns `SystemInfo` object */ export function getSysteminfo(): SystemInfo { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: SystemInfo = js_get_systeminfo(); return data; @@ -16,7 +16,7 @@ export function getSysteminfo(): SystemInfo { * @returns Uptime of system in seconds */ export function uptime(): number { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: number = js_uptime(); return data; } @@ -26,7 +26,7 @@ export function uptime(): number { * @returns Hostname of system */ export function hostname(): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: string = js_hostname(); return data; } @@ -36,7 +36,7 @@ export function hostname(): string { * @returns OS version of the system */ export function osVersion(): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: string = js_osVersion(); return data; } @@ -46,7 +46,7 @@ export function osVersion(): string { * @returns Kernel version of the system */ export function kernelVersion(): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: string = js_kernelVersion(); return data; } @@ -62,7 +62,7 @@ export enum PlatformType { * @returns Platform type of the system */ export function platform(): string { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: string = js_platform(); return data; } diff --git a/src/time/conversion.ts b/src/time/conversion.ts index 79ca94ad..db1942b2 100644 --- a/src/time/conversion.ts +++ b/src/time/conversion.ts @@ -3,7 +3,7 @@ * @returns Current time in UnixEpoch seconds */ export function timeNow(): number { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: bigint = js_time_now(); return Number(data); } @@ -14,7 +14,7 @@ export function timeNow(): number { * @returns UnixEpoch seconds */ export function filetimeToUnixEpoch(filetime: bigint): number { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: bigint = js_filetime_to_unixepoch(filetime); return Number(data); } @@ -25,7 +25,7 @@ export function filetimeToUnixEpoch(filetime: bigint): number { * @returns UnixEpoch seconds */ export function cocoatimeToUnixEpoch(cocoatime: number): number { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: bigint = js_cocoatime_to_unixepoch(cocoatime); return Number(data); } @@ -36,7 +36,7 @@ export function cocoatimeToUnixEpoch(cocoatime: number): number { * @returns UnixEpoch seconds */ export function hfsToUnixEpoch(hfstime: number): number { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: bigint = js_hfs_to_unixepoch(hfstime); return Number(data); } @@ -47,7 +47,7 @@ export function hfsToUnixEpoch(hfstime: number): number { * @returns UnixEpoch seconds */ export function oleToUnixEpoch(oletime: number): number { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: bigint = js_ole_automationtime_to_unixepoch(oletime); return Number(data); } @@ -58,7 +58,7 @@ export function oleToUnixEpoch(oletime: number): number { * @returns UnixEpoch seconds */ export function webkitToUnixEpoch(webkittime: number): number { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: bigint = js_webkit_time_to_unixepoch(webkittime); return Number(data); } @@ -69,7 +69,7 @@ export function webkitToUnixEpoch(webkittime: number): number { * @returns UnixEpoch seconds */ export function fatToUnixEpoch(fattime: Uint8Array): number { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: bigint = js_fat_time_utc_to_unixepoch(fattime); return Number(data); } diff --git a/src/timesketch/artifacts/applications/chromium/history.ts b/src/timesketch/artifacts/applications/chromium/history.ts deleted file mode 100644 index bf199871..00000000 --- a/src/timesketch/artifacts/applications/chromium/history.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { - TimesketchArtifact, - TimesketchTimeline, -} from "../../../../../types/timesketch/timeline"; -import { ChromiumHistory } from "../../../../../types/applications/chromium"; - -/** - * Function to timeline Chromium based history - * @param data Array of `ChromiumHistory` - * @param artifact `TimesketchArtifact` to specify an explicit Chromium based browser - * @returns Array `TimesketchTimeline` for Chromium History - */ -export function timelineChromiumHistory( - data: ChromiumHistory[], - artifact: TimesketchArtifact, -): TimesketchTimeline[] { - const entries: TimesketchTimeline[] = []; - - for (const item of data) { - const entry: TimesketchTimeline = { - datetime: "", - timestamp_desc: "URL Visited", - message: "", - artifact, - data_type: `application:${artifact.split("-").at(0)}:url`, - }; - - entry[ "path" ] = item.db_path; - let user_entry = entry; - - user_entry.datetime = item.last_visit_time; - user_entry.message = `${item.url} | ${item.title}`; - user_entry = { ...user_entry, ...item }; - - entries.push(user_entry); - - } - - return entries; -} diff --git a/src/timesketch/artifacts/applications/libreoffice.ts b/src/timesketch/artifacts/applications/libreoffice.ts deleted file mode 100644 index 92814438..00000000 --- a/src/timesketch/artifacts/applications/libreoffice.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { RecentFilesLibreOffice } from "../../../../types/applications/libreoffice"; -import { TimesketchTimeline } from "../../../../types/timesketch/timeline"; - -/** - * Function to timeline recent files opened by LibreOffice - * @param data Array of `RecentFilesLibreOffice` - * @returns Array of `TimesketchTimeline` - */ -export function timelineRecentFiles(data: RecentFilesLibreOffice[]): TimesketchTimeline[] { - const entries: TimesketchTimeline[] = []; - for (const entry of data) { - const value: TimesketchTimeline = { - datetime: "1970-01-01T00:00:00Z", - timestamp_desc: "N/A", - message: entry.path, - artifact: "LibreOffice Recent Files", - data_type: "application:libreoffice:recentfiles:entry", - title: entry.title, - filter: entry.filter, - pinned: entry.pinned, - password: entry.password, - readonly: entry.readonly, - thumbnail: entry.thumbnail, - path: entry.path, - source: entry.source, - }; - - entries.push(value); - } - - return entries; -} \ No newline at end of file diff --git a/src/timesketch/artifacts/applications/vscode.ts b/src/timesketch/artifacts/applications/vscode.ts deleted file mode 100644 index cd51eef1..00000000 --- a/src/timesketch/artifacts/applications/vscode.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { FileHistory } from "../../../../types/applications/vscode"; -import { TimesketchArtifact, TimesketchTimeline } from "../../../../types/timesketch/timeline"; - -/** - * Function to timeline VSCode File History - * @param data Array of `FileHistory` - * @returns Array of `TimesketchTimeline` - */ -export function timelineFileHistory(data: FileHistory[]): TimesketchTimeline[] { - const entries: TimesketchTimeline[] = []; - for (const item of data) { - for (const entry of item.entries) { - const value: TimesketchTimeline = { - datetime: entry.timestamp as string, - timestamp_desc: "File Saved", - message: item.path ?? item.resource, - artifact: "Visual Studio Code File History", - data_type: "application:vscode:filehistory:entry", - content: entry.content, - filename: entry.id, - version: item.version, - path: item.path ?? "", - history_path: item.history_path, - reason: entry.source ?? "", - description: entry.sourceDescription ?? "", - file_saved: entry.timestamp as string, - }; - - entries.push(value); - } - } - - return entries; -} \ No newline at end of file diff --git a/src/timesketch/artifacts/linux/abrt.ts b/src/timesketch/artifacts/linux/abrt.ts deleted file mode 100644 index bc9db142..00000000 --- a/src/timesketch/artifacts/linux/abrt.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Abrt } from "../../../../types/linux/abrt"; -import { TimesketchTimeline } from "../../../../types/timesketch/timeline"; - -/** - * Function to timeline abrt process entries - * @param data Array of `Abrt` - * @returns Array of `TimesketchTimeline` - */ -export function timelineAbrt(data: Abrt[]): TimesketchTimeline[] { - const entries: TimesketchTimeline[] = []; - for (const item of data) { - let entry: TimesketchTimeline = { - datetime: item.last_occurrence, - timestamp_desc: "Abrt Last Occurrence", - message: item.executable, - artifact: "Abrt", - data_type: "linux:abrt:entry", - }; - - entry = { ...entry, ...item }; - entries.push(entry); - - } - - return entries; -} \ No newline at end of file diff --git a/src/timesketch/artifacts/linux/gnome/appusage.ts b/src/timesketch/artifacts/linux/gnome/appusage.ts deleted file mode 100644 index da773f96..00000000 --- a/src/timesketch/artifacts/linux/gnome/appusage.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { AppUsage } from "../../../../../types/linux/gnome/usage"; -import { TimesketchTimeline } from "../../../../../types/timesketch/timeline"; - -/** - * Function to timeline GNOME AppUsage - * @param data Array of `AppUsage` - * @returns Array of `TimesketchTimeline` - */ -export function timelineGnomeAppUsage(data: AppUsage[]): TimesketchTimeline[] { - const entries: TimesketchTimeline[] = []; - for (const item of data) { - let entry: TimesketchTimeline = { - datetime: item[ "last-seen" ], - timestamp_desc: "Last Seen", - message: item.id, - artifact: "GNOME Application Usage", - data_type: "linux:gnome:applicationusage:entry", - id: item.id, - last_seen: item[ "last-seen" ], - score: item.score, - source: item.source, - }; - - entries.push(entry); - } - - return entries; -} \ No newline at end of file diff --git a/src/timesketch/artifacts/linux/gnome/extensions.ts b/src/timesketch/artifacts/linux/gnome/extensions.ts deleted file mode 100644 index 2748d415..00000000 --- a/src/timesketch/artifacts/linux/gnome/extensions.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Extension } from "../../../../../types/linux/gnome/extensions"; -import { TimesketchTimeline } from "../../../../../types/timesketch/timeline"; - -/** - * Function to timeline GNOME Extensions - * @param data Array of `Extension` - * @returns Array of `TimesketchTimeline` - */ -export function timelineGnomeExtensions(data: Extension[]): TimesketchTimeline[] { - const entries: TimesketchTimeline[] = []; - for (const item of data) { - let entry: TimesketchTimeline = { - datetime: "", - timestamp_desc: "", - message: item.name, - artifact: "GNOME Extension", - data_type: "linux:gnome:extensions:entry", - }; - - entry = { ...entry, ...item }; - // Extract each unique timestamp to their own entry - const time_entries = extractApiTimes(item); - for (const time_entry of time_entries) { - entry.datetime = time_entry.datetime; - entry.timestamp_desc = time_entry.desc; - entries.push(Object.assign({}, entry)); - } - } - - return entries; -} - -interface TimeEntries { - datetime: string; - desc: string; -} - -/** - * Function to extract timestamps from file info - * @param entry A file info object. Can be `MacosFileInfo` or `WindowsFileInfo` or `LinuxFileInfo` - * @returns Array of `TimeEntries` - */ -function extractApiTimes( - entry: Extension, -): TimeEntries[] { - const check_times: Record = {}; - const entries: TimeEntries[] = []; - - check_times[ entry.created ] = "Created"; - check_times[ entry.modified ] === undefined - ? (check_times[ entry.modified ] = "Modified") - : (check_times[ entry.modified ] = `${check_times[ entry.modified ]} Modified`); - - check_times[ entry.changed ] === undefined - ? (check_times[ entry.changed ] = "Changed") - : (check_times[ entry.changed ] = `${check_times[ entry.changed ]} Changed`); - - - check_times[ entry.accessed ] === undefined - ? (check_times[ entry.accessed ] = "Accessed") - : (check_times[ entry.accessed ] = `${check_times[ entry.accessed ]} Accessed`); - - for (const value in check_times) { - const entry: TimeEntries = { - datetime: value, - desc: check_times[ value ] ?? "Undefined", - }; - entries.push(entry); - } - - return entries; -} \ No newline at end of file diff --git a/src/timesketch/artifacts/linux/gnome/gvfs.ts b/src/timesketch/artifacts/linux/gnome/gvfs.ts deleted file mode 100644 index 6bb82184..00000000 --- a/src/timesketch/artifacts/linux/gnome/gvfs.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GvfsEntry } from "../../../../../types/linux/gnome/gvfs"; -import { TimesketchTimeline } from "../../../../../types/timesketch/timeline"; - -/** - * Function to timeline GNOME Virtual Filesystem entries - * @param data Array of `GvfsEntry` - * @returns Array of `TimesketchTimeline` - */ -export function timelineGnomeVirtualFilesystem(data: GvfsEntry[]): TimesketchTimeline[] { - const entries: TimesketchTimeline[] = []; - for (const item of data) { - let entry: TimesketchTimeline = { - datetime: item.last_change, - timestamp_desc: "Last Changed", - message: item.path, - artifact: "GNOME Virtual Filesystem", - data_type: "linux:gnome:gvfs:entry", - name: item.name, - last_change: item.last_change, - path: item.path, - source: item.source, - }; - - entry = { ...entry, ...item.metadata }; - entries.push(entry); - } - - return entries; -} \ No newline at end of file diff --git a/src/timesketch/artifacts/linux/rpm.ts b/src/timesketch/artifacts/linux/rpm.ts deleted file mode 100644 index 34517bd5..00000000 --- a/src/timesketch/artifacts/linux/rpm.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { RpmPackages } from "../../../../types/linux/rpm"; -import type { TimesketchTimeline } from "../../../../types/timesketch/timeline"; - -/** - * Function to timeline RPM packages - * @param data Array of `RpmPackages` - * @returns Array `TimesketchTimeline` of RPM packages - */ -export function timelineRpm(data: RpmPackages[]): TimesketchTimeline[] { - const entries = []; - for (const item of data) { - let entry: TimesketchTimeline = { - datetime: item.install_time, - timestamp_desc: "RPM Package Installed", - message: `${item.name} - Version: ${item.version} installed`, - artifact: "RPM Package", - data_type: "linux:rpm:entry", - }; - - entry = { ...entry, ...item }; - - entries.push(entry); - } - - return entries; -} diff --git a/src/timesketch/client.ts b/src/timesketch/client.ts index 590635bf..616e7224 100644 --- a/src/timesketch/client.ts +++ b/src/timesketch/client.ts @@ -43,7 +43,7 @@ export class Timesketch { public async timelineAndUpload( data: unknown, artifact: TimesketchArtifact, - ): Promise { + ): Promise { const timeline_data = timelineArtifact(data, artifact); if (timeline_data instanceof TimesketchError) { return timeline_data; @@ -61,7 +61,7 @@ export class Timesketch { public async upload( data: TimesketchTimeline[], artifact: string, - ): Promise { + ): Promise { if (data.length === 0) { return new TimesketchError(`ARTIFACT`, `zero values for ${artifact}`); } @@ -96,7 +96,7 @@ export class Timesketch { private async uploadTimeline( data: TimesketchTimeline[], artifact: string, - ): Promise { + ): Promise { if (this.timeline_name === "") { this.timeline_name = artifact; } @@ -176,7 +176,7 @@ export class Timesketch { */ private async createSketch( artifact: string, - ): Promise { + ): Promise { if (this.timesketch_auth.sketch_name === undefined) { this.timesketch_auth.sketch_name = artifact; } @@ -222,7 +222,7 @@ export class Timesketch { * Function to verify if provided Sketch ID exists * @returns `TimesketchError` if we cannot verify the Sketch ID */ - private async verifySketchId(): Promise { + private async verifySketchId(): Promise { const headers = { "X-Csrftoken": this.token, Cookie: this.cookie, @@ -267,7 +267,7 @@ export class Timesketch { * Function to authenticate to Timesketch * @returns `TimesketchError` if authentication failed */ - private async authTimesketch(): Promise { + private async authTimesketch(): Promise { const client: ClientRequest = { url: `${this.timesketch_auth.url}/login/`, protocol: Protocol.GET, diff --git a/src/timesketch/timeline.ts b/src/timesketch/timeline.ts index 1fe203de..922fe727 100644 --- a/src/timesketch/timeline.ts +++ b/src/timesketch/timeline.ts @@ -48,7 +48,6 @@ import { UsnJrnl } from "../../types/windows/usnjrnl"; import { WmiPersist } from "../../types/windows/wmi"; import { LogonsWindows } from "../../types/windows/eventlogs/logons"; import { Journal } from "../../types/linux/journal"; -import { ChromiumHistory } from "../../types/applications/chromium"; /** * macOS artifact timelines @@ -74,25 +73,6 @@ import { GatekeeperEntries } from "../../types/macos/sqlite/gatekeeper"; * Linux artifact timelines */ import { timelineJournals } from "./artifacts/linux/journals"; -import type { RpmPackages } from "../../types/linux/rpm"; -import { timelineAbrt } from "./artifacts/linux/abrt"; -import { Abrt } from "../../types/linux/abrt"; -import { timelineRpm } from "./artifacts/linux/rpm"; -import { timelineGnomeExtensions } from "./artifacts/linux/gnome/extensions"; -import { Extension } from "../../types/linux/gnome/extensions"; -import { timelineGnomeVirtualFilesystem } from "./artifacts/linux/gnome/gvfs"; -import { GvfsEntry } from "../../types/linux/gnome/gvfs"; -import { timelineGnomeAppUsage } from "./artifacts/linux/gnome/appusage"; -import { AppUsage } from "../../types/linux/gnome/usage"; - -/** - * Application artifact timelines - */ -import { timelineChromiumHistory } from "./artifacts/applications/chromium/history"; -import { timelineFileHistory } from "./artifacts/applications/vscode"; -import { FileHistory } from "../../types/applications/vscode"; -import { timelineRecentFiles } from "./artifacts/applications/libreoffice"; -import { RecentFilesLibreOffice } from "../../types/applications/libreoffice"; /** * Cross platform artifact timelines @@ -157,14 +137,9 @@ export function timelineArtifact( return timelineGatekeeper(data as GatekeeperEntries[]); case TimesketchArtifact.FILES: return timelineFiles( - data as MacosFileInfo[] | LinuxFileInfo[], + data as MacosFileInfo[] | LinuxFileInfo[] | WindowsFileInfo[], false, ); - case TimesketchArtifact.FILES_WINDOWS: - return timelineFiles( - data as WindowsFileInfo[], - true, - ); case TimesketchArtifact.EMOND: return timelineEmond(data as Emond[]); case TimesketchArtifact.SPOTLIGHT: @@ -230,24 +205,6 @@ export function timelineArtifact( case TimesketchArtifact.JOURNALS: case TimesketchArtifact.SUDOLOGS_LINUX: return timelineJournals(data as Journal[]); - case TimesketchArtifact.CHROMIUM_HISTORY: - case TimesketchArtifact.CHROME_HISTORY: - case TimesketchArtifact.EDGE_HISTORY: - return timelineChromiumHistory(data as ChromiumHistory[], artifact); - case TimesketchArtifact.RPM: - return timelineRpm(data as RpmPackages[]); - case TimesketchArtifact.VSCODE_FILEHISTORY: - return timelineFileHistory(data as FileHistory[]); - case TimesketchArtifact.LIBREOFFICE_RECENTFILES: - return timelineRecentFiles(data as RecentFilesLibreOffice[]); - case TimesketchArtifact.ABRT: - return timelineAbrt(data as Abrt[]); - case TimesketchArtifact.GNOME_EXTENSIONS: - return timelineGnomeExtensions(data as Extension[]); - case TimesketchArtifact.GNOME_VIRTUAL_FILESYSTEM: - return timelineGnomeVirtualFilesystem(data as GvfsEntry[]); - case TimesketchArtifact.GNOME_APPLICATION_USAGE: - return timelineGnomeAppUsage(data as AppUsage[]); default: return new TimesketchError(`ARTIFACT`, `unknown artifact ${artifact}`); } diff --git a/src/unfold/client.ts b/src/unfold/client.ts index e7b342b4..23bf3a85 100644 --- a/src/unfold/client.ts +++ b/src/unfold/client.ts @@ -4,8 +4,11 @@ import { Bing } from "./plugins/bing"; import { Discord } from "./plugins/discord"; import { Dropbox } from "./plugins/dropbox"; import { DuckDuckGo } from "./plugins/duckduckgo"; +import { GithubUrl } from "./plugins/github"; import { Google } from "./plugins/google"; +import { detectJsonWebToken } from "./plugins/jwt"; import { Outlook } from "./plugins/outlook"; +import { ProxmoxUrl } from "./plugins/proxmox"; import { Yahoo } from "./plugins/yahoo"; /** @@ -51,6 +54,26 @@ export class Unfold { } else if (info.domain.includes("discord.com")) { const disc = new Discord(info); disc.parseDiscord(); + } else if (info.port === 8006) { + const prox = new ProxmoxUrl(info); + prox.parseProxmox(); + } else if (info.domain.includes("github.com")) { + const git = new GithubUrl(info); + git.parseGithub(); + } + + // Check for possible JSON Web Tokens + for (const query of info.query_pairs) { + const [ key, ...param ] = query.split("="); + if (key === undefined) { + break; + } + const payload = param.at(0) ?? ""; + const min_size = 400; + if (payload.length < min_size) { + continue; + } + detectJsonWebToken(payload, info); } return info; @@ -63,7 +86,7 @@ export class Unfold { */ private extractUrl(url: string): Url | UnfoldError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const url_info: Url = js_url_parse(url); url_info.url = url; url_info.last_segment = url_info.segments.at(-1) ?? ""; diff --git a/src/unfold/plugins/bing.ts b/src/unfold/plugins/bing.ts index df9a87f3..c7be754b 100644 --- a/src/unfold/plugins/bing.ts +++ b/src/unfold/plugins/bing.ts @@ -1,6 +1,7 @@ import type { Url } from "../../../types/http/unfold"; import { EncodingError } from "../../encoding/errors"; import { extractUtf8String } from "../../encoding/mod"; +import { parseProtobuf } from "../../encoding/protobuf"; import { NomError } from "../../nom/error"; import { takeUntil } from "../../nom/mod"; import { decodeBase64Url, extractUUID } from "./encoding"; @@ -11,7 +12,7 @@ import { decodeBase64Url, extractUUID } from "./encoding"; export class Bing { private url: Url; - constructor (url: Url) { + constructor(url: Url) { this.url = url; } @@ -21,7 +22,10 @@ export class Bing { */ public parseBing() { for (const entry of this.url.query_pairs) { - const [ key, ...param ] = entry.split("="); + const [key, ...param] = entry.split("="); + if (key === undefined) { + continue; + } const value = param.join("="); switch (key.toLowerCase()) { case "form": { @@ -29,7 +33,7 @@ export class Bing { break; } - this.url[ key ] = value; + this.url[key] = value; break; } case "sk": { @@ -37,7 +41,7 @@ export class Bing { break; } - this.url[ key ] = value; + this.url[key] = value; break; } case "ghpl": { @@ -45,48 +49,48 @@ export class Bing { break; } - this.url[ key ] = value; + this.url[key] = value; break; } case "q": { - this.url[ "search_query" ] = value; + this.url["search_query"] = value; break; } case "sp": { - this.url[ "suggested_position" ] = value; + this.url["suggested_position"] = value; break; } case "lq": { - this.url[ key ] = value; + this.url[key] = value; break; } case "pq": { - this.url[ "partial_query" ] = value; + this.url["partial_query"] = value; break; } case "sc": { - this.url[ "suggestion_count" ] = value; + this.url["suggestion_count"] = value; break; } case "qs": { - this.url[ "suggestion_type" ] = value; + this.url["suggestion_type"] = value; break; } case "ghc": { - this.url[ key ] = value; + this.url[key] = value; break; } case "cvid": { const uuid = value; if (uuid.length !== 32) { - this.url[ "conversation_id" ] = value; + this.url["conversation_id"] = value; break; } - this.url[ "conversation_id" ] = extractUUID(uuid); + this.url["conversation_id"] = extractUUID(uuid); break; } case "ghacc": { - this.url[ key ] = value; + this.url[key] = value; break; } // A little complex @@ -109,7 +113,7 @@ export class Bing { break; } - this.url[ key ] = extractUtf8String(data).split("!"); + this.url[key] = extractUtf8String(data).split("!"); // Remove quotes from second part of filter const remaining = (filter_value.remaining as string) @@ -117,14 +121,85 @@ export class Bing { const values = remaining.split(" "); for (const entry of values) { const filter_values = entry.split(":"); - this.url[ `filters_${filter_values.at(0) ?? ""}` ] = filter_values.at( + this.url[`filters_${filter_values.at(0) ?? ""}`] = filter_values.at( 1, ); } break; } case "ghsh": { - this.url[ key ] = value; + this.url[key] = value; + break; + } + case "pglt": { + // Could be page generation or load timing + // According to Copilot + // Always seems have value 2083 + this.url[key] = value; + break; + } + case "pc": { + // Always seems have value U531 + this.url[key] = value; + break; + } + case "ver": { + this.url["version"] = value; + break; + } + case "ptn": { + this.url[key] = value; + break; + } + case "hsh": { + this.url[key] = value; + break; + } + case "psq": { + // Seems to contain a shorter search query term + // Compilot refers to this as a "compact query" + this.url['compact_search_query'] = value; + break; + } + case "ntb": { + this.url[key] = value; + break; + } + case "!": break; + case "p": { + // Needs to be combined with "u" query to fully base64 decode? + // Seems to contain a timestamp at the end + this.url[key] = value; + break; + } + case "u": { + // Have to combine with the "p" query in order to decode + // Contains URL + this.url[key] = value; + break; + } + case "fclid": { + // Probably somekind of click identifier? + // gclid - Google Click idnetifier + // fbclid - Facebook Click identifier + this.url[key] = value; + break; + } + case "gs_lcrp": { + // Similar to Google "gs_lp"? + const value = param.at(1); + if (value === undefined) { + break; + } + const bytes = decodeBase64Url(value); + if (bytes instanceof EncodingError) { + break; + } + const proto_data = parseProtobuf(bytes); + if (proto_data instanceof EncodingError) { + break; + } + this.url[key] = proto_data; break; } case undefined: { @@ -134,7 +209,7 @@ export class Bing { console.warn( `unknown bing key: ${key}. Value: ${value}`, ); - this.url[ key ] = value; + this.url[key] = value; break; } } diff --git a/src/unfold/plugins/discord.ts b/src/unfold/plugins/discord.ts index 682dacf7..26f980b0 100644 --- a/src/unfold/plugins/discord.ts +++ b/src/unfold/plugins/discord.ts @@ -16,7 +16,7 @@ export class Discord { if (this.url.url.includes("/channels/")) { for (let i = 0; i < this.url.segments.length; i++) { const value = this.url.segments[ i ]; - if (value === "channels") { + if (value === "channels" || value === undefined) { continue; } diff --git a/src/unfold/plugins/dropbox.ts b/src/unfold/plugins/dropbox.ts index bc990bef..0eb41172 100644 --- a/src/unfold/plugins/dropbox.ts +++ b/src/unfold/plugins/dropbox.ts @@ -37,6 +37,9 @@ export class Dropbox { for (const entry of this.url.query_pairs) { const [ key, ...param ] = entry.split("="); + if (key === undefined) { + continue; + } const value = param.join("="); switch (key.toLowerCase()) { case "rlkey": { @@ -70,6 +73,9 @@ export class Dropbox { for (const entry of this.url.query_pairs) { const [ key, ...param ] = entry.split("="); + if (key === undefined) { + continue; + } const value = param.join("="); switch (key.toLowerCase()) { case "preview": { diff --git a/src/unfold/plugins/github.ts b/src/unfold/plugins/github.ts new file mode 100644 index 00000000..cf19a28e --- /dev/null +++ b/src/unfold/plugins/github.ts @@ -0,0 +1,32 @@ +import { Url } from "../../../types/http/unfold"; + +/** + * Class to parse some Github URL info + */ +export class GithubUrl { + private url: Url; + + constructor (url: Url) { + this.url = url; + } + + /** + * Function attempt to extract Github username and repositories from URL + * May produce false positives + */ + public parseGithub() { + if (this.url.segments.length !== 2 || this.url.query !== "") { + return; + } + + const username = this.url.segments.at(0) ?? ""; + // Some common URIs in Github that cannot be usernames + const github_uris = [ "security", "features", "resources", "enterprise", "solutions", "sponsors", "readme", "partners" ]; + if (github_uris.includes(username)) { + return; + } + this.url[ "username" ] = this.url.segments.at(0) ?? ""; + this.url[ "repository" ] = this.url.segments.at(1) ?? ""; + + } +} \ No newline at end of file diff --git a/src/unfold/plugins/jwt.ts b/src/unfold/plugins/jwt.ts new file mode 100644 index 00000000..1b580fe0 --- /dev/null +++ b/src/unfold/plugins/jwt.ts @@ -0,0 +1,69 @@ +import { Url } from "../../../types/http/unfold"; +import { EncodingError } from "../../encoding/errors"; +import { extractUtf8String } from "../../encoding/strings"; +import { NomError } from "../../nom/error"; +import { takeUntil } from "../../nom/parsers"; +import { decodeBase64Url } from "./encoding"; + +/** + * Function to attempt to parse JSON Web Tokens + * @param payload Base64 encoded string containing 2 periods (".") + * @param url `Url` object + * @returns Updated `Url` object containing JSON Web Token info + */ +export function detectJsonWebToken(payload: string, url: Url) { + const payload_components = payload.match(/\./g); + if (payload_components?.length !== 2) { + return; + } + const values = payload.split("."); + + const header = values.at(0) ?? ""; + + if (header.length % 4 !== 0 && !header.includes("=") && (header.length + 1) % 4 !== 0) { + return; + } + + const header_info = decodeBase64Url(header); + if (header_info instanceof EncodingError) { + return; + } + + const header_payload = extractUtf8String(header_info); + if (!header_payload.includes("{")) { + return; + } + url[ "jwt_header" ] = header_payload; + const payload_data = values.at(1) ?? ""; + + + + const payload_bytes = decodeBase64Url(payload_data); + if (payload_bytes instanceof EncodingError) { + return; + } + if (payload_bytes.at(0) === 123) { + const payload_value = extractUtf8String(payload_bytes); + if (!payload_value.includes("{")) { + return; + } + url[ "jwt_payload" ] = payload_value; + } else { + const payload_start = takeUntil(payload_bytes, new Uint8Array([ 123 ])); + if (payload_start instanceof NomError) { + return; + } + + const payload_end = takeUntil(payload_start.remaining, new Uint8Array([ 125, 63, 0, 0 ])); + if (payload_end instanceof NomError) { + return; + } + const payload_value = extractUtf8String(payload_end.nommed as Uint8Array); + if (!payload_value.includes("{")) { + return; + } + url[ "jwt_payload" ] = payload_value; + } + + url[ "jwt_signature" ] = values.at(2) ?? ""; +} \ No newline at end of file diff --git a/src/unfold/plugins/proxmox.ts b/src/unfold/plugins/proxmox.ts new file mode 100644 index 00000000..b6394f11 --- /dev/null +++ b/src/unfold/plugins/proxmox.ts @@ -0,0 +1,63 @@ +import { Url } from "../../../types/http/unfold"; + +/** + * Class to parse Proxmox web application + */ +export class ProxmoxUrl { + private url: Url; + + constructor (url: Url) { + this.url = url; + } + + /** + * Function to extract interactions with Proxmox VMs + */ + public parseProxmox() { + for (const entry of this.url.query_pairs) { + const param = entry.split("="); + const key = param.at(0); + + switch (key) { + case "console": { + this.url[ "console" ] = param.at(1) ?? ""; + break; + } + case "novnc": { + this.url[ "using_vnc" ] = Boolean(param.at(1) ?? 1); + break; + } + case "vmid": { + this.url[ "virtual_machine_id" ] = param.at(1) ?? 0; + break; + } + case "vmname": { + this.url[ "virtual_machine_name" ] = param.at(1) ?? ""; + break; + } + case "node": { + this.url[ "proxmox_node" ] = param.at(1) ?? ""; + break; + } + case "resize": { + this.url[ "resize" ] = param.at(1) ?? ""; + break; + } + case "cmd": { + this.url[ "command" ] = param.at(1) ?? ""; + break; + } + case undefined: { + break; + } + default: { + console.warn( + `unknown proxmox key: ${key}. Value: ${param.at(1)}`, + ); + this.url[ key ] = param.at(1); + break; + } + } + } + } +} \ No newline at end of file diff --git a/src/unfold/plugins/yahoo.ts b/src/unfold/plugins/yahoo.ts index 65673c5b..829e7354 100644 --- a/src/unfold/plugins/yahoo.ts +++ b/src/unfold/plugins/yahoo.ts @@ -17,6 +17,9 @@ export class Yahoo { public parseYahoo() { for (const entry of this.url.query_pairs) { const [ key, ...param ] = entry.split("="); + if (key === undefined) { + continue; + } const value = param.join("="); switch (key.toLowerCase()) { case "p": { diff --git a/src/unix/shell_history.ts b/src/unix/shell_history.ts index edc7b979..50550be0 100644 --- a/src/unix/shell_history.ts +++ b/src/unix/shell_history.ts @@ -7,7 +7,6 @@ import { FileError } from "../filesystem/errors"; import { glob, readTextFile } from "../filesystem/files"; import { PlatformType } from "../system/systeminfo"; import { unixEpochToISO } from "../time/conversion"; -import { UnixError } from "./errors"; export function getBashHistory(platform: PlatformType.Linux | PlatformType.Darwin, alt_file?: string): BashHistory[] { let paths: string[] = [ "/home/*/.bash_history" ]; @@ -103,24 +102,24 @@ function parseBash(text: string, path: string): BashHistory[] { const timestamp_regex = /^#([0-9]+)$/; const values: BashHistory[] = []; for (let i = 0; i < lines.length; i++) { - if (lines[ i ] === "") { + if (lines[ i ] === "" || lines[ i ] === undefined) { continue; } - let history: BashHistory = { + const history: BashHistory = { history: "", timestamp: "1970-01-01T00:00:00Z", line: 0, path, }; - const time_hit = timestamp_regex.exec(lines[ i ]); + const time_hit = timestamp_regex.exec(lines[ i ] ?? ""); if (time_hit === null || time_hit.length === 0) { - history.history = lines[ i ]; + history.history = lines[ i ] ?? ""; history.line = i; values.push(history); } else { const unixepoch_time = time_hit[ 0 ].substring(1); i++; - history.history = lines[ i ]; + history.history = lines[ i ] ?? ""; history.line = i; history.timestamp = unixEpochToISO(Number(unixepoch_time)); values.push(history); @@ -135,23 +134,23 @@ function parseZsh(text: string, path: string): ZshHistory[] { const timestamp_regex = /^: {0,10}([0-9]{1,11}):[0-9]+;(.*)$/; const values: ZshHistory[] = []; for (let i = 0; i < lines.length; i++) { - if (lines[ i ] === "") { + if (lines[ i ] === "" || lines[ i ] === undefined) { continue; } - let history: ZshHistory = { + const history: ZshHistory = { history: "", timestamp: "1970-01-01T00:00:00Z", line: 0, path, }; - const time_hit = timestamp_regex.exec(lines[ i ]); + const time_hit = timestamp_regex.exec(lines[ i ] ?? ""); if (time_hit === null || time_hit.length < 3) { - history.history = lines[ i ]; + history.history = lines[ i ] ?? ""; history.line = i; values.push(history); } else { const unixepoch_time = time_hit[ 1 ]; - history.history = time_hit[ 2 ]; + history.history = time_hit[ 2 ] ?? ""; history.line = i; history.timestamp = unixEpochToISO(Number(unixepoch_time)); values.push(history); diff --git a/src/unix/ssh.ts b/src/unix/ssh.ts index 29015f9f..187b3e3e 100644 --- a/src/unix/ssh.ts +++ b/src/unix/ssh.ts @@ -34,7 +34,7 @@ export function listKnownHosts(alt_glob?: string): KnownHosts[] | UnixError { const value = line.split(" "); - let host: KnownHosts = { + const host: KnownHosts = { target: value.at(0) ?? "", algorithm: value.at(1) ?? "", data: value.at(2) ?? "", diff --git a/src/windows/amcache.ts b/src/windows/amcache.ts index ef513dfe..a7a0277f 100644 --- a/src/windows/amcache.ts +++ b/src/windows/amcache.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getAmcache(path?: string): Amcache[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const results = js_amcache(path); return results; } catch (err) { diff --git a/src/windows/bits.ts b/src/windows/bits.ts index 25ad3ec8..7ac2bd55 100644 --- a/src/windows/bits.ts +++ b/src/windows/bits.ts @@ -9,7 +9,7 @@ import { WindowsError } from "./errors"; */ export function getBits(carve: boolean, path?: string): Bits | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const results = js_bits(carve, path); return results; } catch (err) { diff --git a/src/windows/chocolatey.ts b/src/windows/chocolatey.ts index d17da8ec..0a78430e 100644 --- a/src/windows/chocolatey.ts +++ b/src/windows/chocolatey.ts @@ -43,21 +43,25 @@ export function getChocolateyInfo( console.warn(`failed to parse ${path.full_path}: ${xml_data.message}`); continue; } + const entry = xml_data.package.metadata.at(0); + if (entry === undefined) { + continue; + } // Try to grab some info const chocolate: ChocolateyInfo = { - name: xml_data.package.metadata[ 0 ].id[ 0 ], - version: xml_data.package.metadata[ 0 ].version[ 0 ], - summary: typeof xml_data.package.metadata[ 0 ].summary === "undefined" + name: entry.id[ 0 ] ?? "", + version: entry.version[ 0 ] ?? "", + summary: typeof entry.summary === "undefined" ? "" - : xml_data.package.metadata[ 0 ].summary[ 0 ], - author: xml_data.package.metadata[ 0 ].authors[ 0 ], - license: typeof xml_data.package.metadata[ 0 ].licenseUrl === "undefined" + : entry.summary[ 0 ] ?? "", + author: entry.authors[ 0 ] ?? "", + license: typeof entry.licenseUrl === "undefined" ? "" - : xml_data.package.metadata[ 0 ].licenseUrl[ 0 ], - tags: typeof xml_data.package.metadata[ 0 ].tags === "undefined" + : entry.licenseUrl[ 0 ] ?? "", + tags: typeof entry.tags === "undefined" ? [] - : xml_data.package.metadata[ 0 ].tags[ 0 ].split(" "), + : (entry.tags[ 0 ] ?? "").split(" "), path: path.full_path, }; packages.push(chocolate); diff --git a/src/windows/errors.ts b/src/windows/errors.ts index 49698bde..64556264 100644 --- a/src/windows/errors.ts +++ b/src/windows/errors.ts @@ -38,6 +38,8 @@ export type ErrorName = | "BAM" | "SCRIPTBLOCK" | "FIREWALL_RULES" - | "EVENTLOG_PROCESSTREE"; + | "EVENTLOG_PROCESSTREE" + | "WIFI" + | "ADCERTIFICATES"; export class WindowsError extends ErrorBase {} diff --git a/src/windows/ese.ts b/src/windows/ese.ts index 83a48a7d..75db63f5 100644 --- a/src/windows/ese.ts +++ b/src/windows/ese.ts @@ -26,7 +26,7 @@ export class EseDatabase { */ public catalogInfo(): Catalog[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Catalog[] = js_get_catalog(this.path); return data; } catch (err) { @@ -95,7 +95,7 @@ export class EseDatabase { */ public getPages(first_page: number): number[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_get_pages(this.path, first_page); const results: number[] = data; @@ -119,7 +119,7 @@ export class EseDatabase { info: TableInfo, ): Record | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Record = js_page_data( this.path, pages, @@ -151,7 +151,7 @@ export class EseDatabase { column_data: Record, ): Record | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Record = js_filter_page_data( this.path, pages, @@ -183,7 +183,7 @@ export class EseDatabase { column_names: string[], ): Record | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Record = js_get_table_columns( this.path, pages, diff --git a/src/windows/ese/certs.ts b/src/windows/ese/certs.ts new file mode 100644 index 00000000..d47c4c02 --- /dev/null +++ b/src/windows/ese/certs.ts @@ -0,0 +1,214 @@ +import { TableInfo } from "../../../types/windows/ese" +import { Certificates, RequestAttributes, Requests, RequestType, StatusCode } from "../../../types/windows/ese/certs"; +import { getEnvValue } from "../../environment/mod"; +import { FileError } from "../../filesystem/errors"; +import { glob } from "../../filesystem/files"; +import { WindowsError } from "../errors"; +import { EseDatabase } from "../ese" + +/** + * Class to parse Windows AD Certificate Services + * References: + * - [CrowdStrike White Paper](https://www.crowdstrike.com/wp-content/uploads/2023/12/investigating-active-directory-certificate-abuse.pdf) + */ +export class ADCertificates extends EseDatabase { + /** + * Construct a `ADCertificates` object. By default it will parse the EDB file on the SystemDrive. + * @param alt_path Optional alternative path the CertLog EDB file + */ + constructor(alt_path?: string) { + let path = "\\Windows\\System32\\CertLog\\*.edb"; + if (alt_path !== undefined) { + path = alt_path; + } else { + let drive = getEnvValue("SystemDrive"); + if (drive === "") { + drive = "C:"; + } + path = `${drive}${path}`; + const paths = glob(path); + if (paths instanceof FileError) { + console.error(`Could not glob for EDB at ${path}`); + return; + } + if (paths.length < 1 || paths[0] === undefined) { + console.error(`No EDB files found`); + return; + } + path = paths[0].full_path; + } + + super(path); + } + + /** + * Function to extract rows from the `Certificates` ESE table + * @param pages Array of ESE pages to parse + * @param info `TableInfo` object + * @returns Array of `Certificates` or `WindowsError` + */ + public getCertificates(pages: number[], info: TableInfo): Certificates[] | WindowsError { + const rows = this.getRows(pages, info); + if (rows instanceof WindowsError) { + return rows; + } + + const certs: Certificates[] = []; + const cert_data = rows["Certificates"]; + if (cert_data === undefined) { + return new WindowsError(`ADCERTIFICATES`, `Could not find "Certificates" table`) + } + + for (const row of cert_data) { + const value: Certificates = { + common_name: "", + request_id: 0, + raw_cert: "", + hash: "", + serial_number: "", + distinguished_name: "", + domain: "" + }; + for (const column of row) { + switch (column.column_name) { + case "RequestID": + value.request_id = Number(column.column_data); + break; + case "$SerialNumber": + value.serial_number = column.column_data; + break; + case "RawCertificate": + value.raw_cert = column.column_data; + break; + case "$DistinguishedName": + value.distinguished_name = column.column_data; + break; + case "$CommonName": + value.common_name = column.column_data; + break; + case "$DomainComponent": + value.domain = column.column_data; + break; + case "$CertificateHash2": + value.hash = column.column_data.replace(" ", ""); + break; + default: + break; + } + } + certs.push(value); + } + + return certs; + } + + /** + * Function to extract rows from the `Requests` ESE table + * @param pages Array of ESE pages to parse + * @param info `TableInfo` object + * @returns Array of `Requests` or `WindowsError` + */ + public getRequests(pages: number[], info: TableInfo): Requests[] | WindowsError { + const rows = this.getRows(pages, info); + if (rows instanceof WindowsError) { + return rows; + } + + const reqs: Requests[] = []; + const req_data = rows["Requests"]; + if (req_data === undefined) { + return new WindowsError(`ADCERTIFICATES`, `Could not find "Requests" table`) + } + + for (const row of req_data) { + const value: Requests = { + request_id: 0, + request_type: RequestType.Unknown, + status_code_number: 0, + status_code: StatusCode.Unknown, + disposition_message: "", + requester_name: "", + caller_name: "", + request_attributes: "", + submitted: "1970-01-01T00:00:00Z", + resolved: "1970-01-01T00:00:00Z", + }; + for (const column of row) { + switch (column.column_name) { + case "RequestID": + value.request_id = Number(column.column_data); + break; + case "$RequesterName": + value.requester_name = column.column_data; + break; + case "$CallerName": + value.caller_name = column.column_data; + break; + case "$RequestAttributes": + value.request_attributes = column.column_data; + break; + case "$DispositionMessage": + value.disposition_message = column.column_data; + break; + case "StatusCode": + value.status_code_number = Number(column.column_data); + break; + case "ResolvedWhen": + value.resolved = column.column_data; + break; + case "SubmittedWhen": + value.submitted = column.column_data; + break; + default: + break; + } + } + reqs.push(value); + } + return reqs; + } + + /** + * Function to extract rows from the `RequestsAttributes` ESE table + * @param pages Array of ESE pages to parse + * @param info `TableInfo` object + * @returns Array of `RequestsAttributes` or `WindowsError` + */ + public requestAttributes(pages: number[], info: TableInfo): RequestAttributes[] | WindowsError { + const rows = this.getRows(pages, info); + if (rows instanceof WindowsError) { + return rows; + } + + const reqs: RequestAttributes[] = []; + const req_data = rows["RequestAttributes"]; + if (req_data === undefined) { + return new WindowsError(`ADCERTIFICATES`, `Could not find "RequestAttributes" table`) + } + + for (const row of req_data) { + const value: RequestAttributes = { + request_id: 0, + name: "", + value: "" + }; + for (const column of row) { + switch (column.column_name) { + case "RequestID": + value.request_id = Number(column.column_data); + break; + case "$AttributeName": + value.name = column.column_data; + break; + case "$AttributeValue": + value.value = column.column_data; + break; + default: + break; + } + } + reqs.push(value); + } + return reqs; + } +} \ No newline at end of file diff --git a/src/windows/ese/ual.ts b/src/windows/ese/ual.ts index b6273e8f..d52d3adf 100644 --- a/src/windows/ese/ual.ts +++ b/src/windows/ese/ual.ts @@ -57,7 +57,15 @@ export class UserAccessLogging extends EseDatabase { return rows; } - return this.parseIds(rows[ "ROLE_IDS" ]); + const row_data = rows[ "ROLE_IDS" ]; + if (row_data === undefined) { + return new WindowsError( + `UAL`, + `Could not find data from "ROLE_IDS" table. Got undefined`, + ); + } + + return this.parseIds(row_data); } /** @@ -82,8 +90,15 @@ export class UserAccessLogging extends EseDatabase { if (rows instanceof WindowsError) { return rows; } + const row_data = rows[ "CLIENTS" ]; + if (row_data === undefined) { + return new WindowsError( + `UAL`, + `Could not find data from "CLIENTS" table. Got undefined`, + ); + } - const clients = this.parseClients(rows[ "CLIENTS" ]); + const clients = this.parseClients(row_data); let roles_limit: number[] = []; if (roles_ual === undefined) { return clients; @@ -153,7 +168,7 @@ export class UserAccessLogging extends EseDatabase { this.pages = pages; } - private setupClients(): void | WindowsError { + private setupClients(): void { const catalog = this.catalogInfo(); if (catalog instanceof WindowsError) { return; diff --git a/src/windows/ese/updates.ts b/src/windows/ese/updates.ts index 5c50e78b..601a6bf2 100644 --- a/src/windows/ese/updates.ts +++ b/src/windows/ese/updates.ts @@ -26,7 +26,7 @@ export class Updates extends EseDatabase { * Contruct `Updates` to parse Windows Updates history. By default will parse updates at `\Windows\SoftwareDistribution\DataStore\DataStore.edb`. Unless you specify alternative file. * @param alt_path Optional alternative path to `DataStore.edb` */ - constructor (alt_path?: string) { + constructor(alt_path?: string) { const default_path = getEnvValue("SystemDrive"); let path = `${default_path}\\Windows\\SoftwareDistribution\\DataStore\\DataStore.edb`; @@ -63,7 +63,15 @@ export class Updates extends EseDatabase { return rows; } - return this.parseHistory(rows[ this.table ]); + const row_data = rows[this.table]; + if (row_data === undefined) { + return new WindowsError( + `UPDATESHISTORY`, + `Could not find "tbHistory" table. Got undefined`, + ); + } + + return this.parseHistory(row_data); } private setupHistory() { @@ -135,15 +143,15 @@ export class Updates extends EseDatabase { if (update_info instanceof Error) { console.warn(`could not parse update id info ${update_info}`); } else { - update.update_id = update_info[ "guid" ] as string; - update.update_revision = update_info[ "revision" ] as number; + update.update_id = update_info["guid"] as string; + update.update_revision = update_info["revision"] as number; } } else if (column.column_name === "ServerId") { const update_info = this.getUpdateId(column.column_data); if (update_info instanceof Error) { console.warn(`could not parse service id info ${update_info}`); } else { - update.service_id = update_info[ "guid" ] as string; + update.service_id = update_info["guid"] as string; } } else if (column.column_name === "ServerSelection") { update.server_selection = this.getServerSelection(column.column_data); @@ -171,7 +179,7 @@ export class Updates extends EseDatabase { } const update_id: Record = {}; - update_id[ "guid" ] = formatGuid(Endian.Le, guid.nommed as Uint8Array); + update_id["guid"] = formatGuid(Endian.Le, guid.nommed as Uint8Array); if (guid.remaining.length === 0) { return update_id; @@ -185,7 +193,7 @@ export class Updates extends EseDatabase { return revision_data; } - update_id[ "revision" ] = revision_data.value; + update_id["revision"] = revision_data.value; return update_id; } diff --git a/src/windows/eventlogs.ts b/src/windows/eventlogs.ts index e722ea1f..b0bfdb9c 100644 --- a/src/windows/eventlogs.ts +++ b/src/windows/eventlogs.ts @@ -32,7 +32,7 @@ export function getEventlogs( ); } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const results = js_eventlogs( path, offset, diff --git a/src/windows/eventlogs/logons.ts b/src/windows/eventlogs/logons.ts index 54e783cd..5a90164a 100644 --- a/src/windows/eventlogs/logons.ts +++ b/src/windows/eventlogs/logons.ts @@ -30,7 +30,7 @@ export function logonsWindows(path: string): LogonsWindows[] | WindowsError { `failed to parse eventlog ${path}: ${logs}`, ); } - const recordsData = logs[1]; + const recordsData = logs[ 1 ]; if (recordsData.length === 0) { break; } @@ -68,16 +68,21 @@ export function logonsWindows(path: string): LogonsWindows[] | WindowsError { // Try to correlate logon/logoff events for (let i = 0; i < logon_entries.length; i++) { + const entry = logon_entries[ i ]; + if (entry === undefined) { + continue; + } + for (const logoff of logoff_entries) { if ( - logon_entries[i].logon_id === logoff.data.Event.EventData.TargetLogonId + entry.logon_id === logoff.data.Event.EventData.TargetLogonId ) { - logon_entries[i].logoff_time = logoff.timestamp; - const duration = new Date(logon_entries[i].logoff_time).getTime() - - new Date(logon_entries[i].logon_time).getTime(); - logon_entries[i].duration = Number(duration); - if (logon_entries[i].duration === null) { - logon_entries[i].duration = 0; + entry.logoff_time = logoff.timestamp; + const duration = new Date(entry.logoff_time).getTime() - + new Date(entry.logon_time).getTime(); + entry.duration = Number(duration); + if (entry.duration === null) { + entry.duration = 0; } } } @@ -167,31 +172,34 @@ export function testLogonsWindows(): void { } if (results.length !== 198) { - throw `Got ${results.length} logon events, expected 198.......logonsWindows āŒ` + throw `Got ${results.length} logon events, expected 198.......logonsWindows āŒ`; + } + if (results[ 1 ] === undefined) { + throw `Got undefined logon event.......logonsWindows āŒ`; } - if (results[1].logon_time != "2022-10-31T03:30:46.218854000Z") { - throw `Got ${results[1].logon_time} for logon time, expected 2022-10-31T03:30:46.218854000Z.......logonsWindows āŒ` + if (results[ 1 ].logon_time != "2022-10-31T03:30:46.218854000Z") { + throw `Got ${results[ 1 ].logon_time} for logon time, expected 2022-10-31T03:30:46.218854000Z.......logonsWindows āŒ`; } - const logon_types = [2, 3, 4, 5, 7, 8, 9, 10, 11]; + const logon_types = [ 2, 3, 4, 5, 7, 8, 9, 10, 11 ]; for (const entry of logon_types) { const type_result = checkLogonType(entry); if (type_result === LogonType.Unknown) { - throw `Got Unknown logon type ${type_result}.......checkLogonType āŒ` + throw `Got Unknown logon type ${type_result}.......checkLogonType āŒ`; } } console.info(` Function checkLogonType āœ…`); const logon = `{"event_record_id":84182,"timestamp":"2025-08-31T03:06:46.605720000Z","data":{"Event":{"#attributes":{"xmlns":"http://schemas.microsoft.com/win/2004/08/events/event"},"System":{"Provider":{"#attributes":{"Name":"Microsoft-Windows-Security-Auditing","Guid":"54849625-5478-4994-A5BA-3E3B0328C30D"}},"EventID":4624,"Version":3,"Level":0,"Task":12544,"Opcode":0,"Keywords":"0x8020000000000000","TimeCreated":{"#attributes":{"SystemTime":"2025-08-31T03:06:46.605720Z"}},"EventRecordID":84182,"Correlation":null,"Execution":{"#attributes":{"ProcessID":876,"ThreadID":1340}},"Channel":"Security","Computer":"win","Security":null},"EventData":{"SubjectUserSid":"S-1-0-0","SubjectUserName":"-","SubjectDomainName":"-","SubjectLogonId":"0x0","TargetUserSid":"S-1-5-18","TargetUserName":"SYSTEM","TargetDomainName":"NT AUTHORITY","TargetLogonId":"0x3e7","LogonType":0,"LogonProcessName":"-","AuthenticationPackageName":"-","WorkstationName":"-","LogonGuid":"00000000-0000-0000-0000-000000000000","TransmittedServices":"-","LmPackageName":"-","KeyLength":0,"ProcessId":"0x4","ProcessName":"","IpAddress":"-","IpPort":"-","ImpersonationLevel":"-","RestrictedAdminMode":"-","RemoteCredentialGuard":"-","TargetOutboundUserName":"-","TargetOutboundDomainName":"-","VirtualAccount":"%%1843","TargetLinkedLogonId":"0x0","ElevatedToken":"%%1842"}}}}`; if (!isLogon(JSON.parse(logon))) { - throw `Did not get logon event.......isLogon āŒ` + throw `Did not get logon event.......isLogon āŒ`; } console.info(` Function isLogon āœ…`); - const logoff = `{"event_record_id":84336,"timestamp":"2025-08-31T03:07:39.322481000Z","data":{"Event":{"#attributes":{"xmlns":"http://schemas.microsoft.com/win/2004/08/events/event"},"System":{"Provider":{"#attributes":{"Name":"Microsoft-Windows-Security-Auditing","Guid":"54849625-5478-4994-A5BA-3E3B0328C30D"}},"EventID":4634,"Version":0,"Level":0,"Task":12545,"Opcode":0,"Keywords":"0x8020000000000000","TimeCreated":{"#attributes":{"SystemTime":"2025-08-31T03:07:39.322481Z"}},"EventRecordID":84336,"Correlation":null,"Execution":{"#attributes":{"ProcessID":876,"ThreadID":2132}},"Channel":"Security","Computer":"win","Security":null},"EventData":{"TargetUserSid":"S-1-5-96-0-1","TargetUserName":"UMFD-1","TargetDomainName":"Font Driver Host","TargetLogonId":"0x1381d","LogonType":2}}}}` + const logoff = `{"event_record_id":84336,"timestamp":"2025-08-31T03:07:39.322481000Z","data":{"Event":{"#attributes":{"xmlns":"http://schemas.microsoft.com/win/2004/08/events/event"},"System":{"Provider":{"#attributes":{"Name":"Microsoft-Windows-Security-Auditing","Guid":"54849625-5478-4994-A5BA-3E3B0328C30D"}},"EventID":4634,"Version":0,"Level":0,"Task":12545,"Opcode":0,"Keywords":"0x8020000000000000","TimeCreated":{"#attributes":{"SystemTime":"2025-08-31T03:07:39.322481Z"}},"EventRecordID":84336,"Correlation":null,"Execution":{"#attributes":{"ProcessID":876,"ThreadID":2132}},"Channel":"Security","Computer":"win","Security":null},"EventData":{"TargetUserSid":"S-1-5-96-0-1","TargetUserName":"UMFD-1","TargetDomainName":"Font Driver Host","TargetLogonId":"0x1381d","LogonType":2}}}}`; if (!isLogoff(JSON.parse(logoff))) { - throw `Did not get logoff event.......isLogoff āŒ` + throw `Did not get logoff event.......isLogoff āŒ`; } console.info(` Function isLogoff āœ…`); } \ No newline at end of file diff --git a/src/windows/eventlogs/processtree.ts b/src/windows/eventlogs/processtree.ts index 49a44f73..5aea32b2 100644 --- a/src/windows/eventlogs/processtree.ts +++ b/src/windows/eventlogs/processtree.ts @@ -33,13 +33,13 @@ export function processTreeEventLogs(path?: string): EventLogProcessTree[] | Win } // If empty we are done. No more entries are in the log - if (logs[1].length === 0) { + if (logs[ 1 ].length === 0) { break; } // Increase to next chunk of entries offset += limit; - const data = logs[1] as RawProcess[]; + const data = logs[ 1 ] as RawProcess[]; for (const entry of data) { // Skip non process 4688 events if (entry.data.Event.System.EventID !== eid) { @@ -50,7 +50,7 @@ export function processTreeEventLogs(path?: string): EventLogProcessTree[] | Win const pid = Number(entry.data.Event.EventData.NewProcessId); const name = entry.data.Event.EventData.NewProcessName; const parent_name = entry.data.Event.EventData.ParentProcessName ?? ""; - let track: ProcTracker = { + const track: ProcTracker = { login_id: logon_id, pid: pid, parent: parent, @@ -59,18 +59,18 @@ export function processTreeEventLogs(path?: string): EventLogProcessTree[] | Win record: entry.event_record_id, }; // Track new process - if (procs_map[`${logon_id}_${pid}`] !== undefined) { - const old = procs_map[`${logon_id}_${pid}`] as ProcTracker | ProcTracker[]; + if (procs_map[ `${logon_id}_${pid}` ] !== undefined) { + const old = procs_map[ `${logon_id}_${pid}` ] as ProcTracker | ProcTracker[]; if (Array.isArray(old)) { old.push(track); - procs_map[`${logon_id}_${pid}`] = old; + procs_map[ `${logon_id}_${pid}` ] = old; continue; } - procs_map[`${logon_id}_${pid}`] = [old, track]; + procs_map[ `${logon_id}_${pid}` ] = [ old, track ]; continue; } - procs_map[`${logon_id}_${pid}`] = track; + procs_map[ `${logon_id}_${pid}` ] = track; raw_procs.push(entry); } } @@ -141,16 +141,16 @@ function getParent(logon_id: number, parent: number, data: Record= record) { @@ -185,23 +185,23 @@ function duplicateIds(values: ProcTracker[], record: number): ProcTracker | unde return undefined; } if (filter.length === 1) { - return filter[0]; + return filter[ 0 ]; } // The parent record number closest to us we treat as our parent // Get the largest record in our filtered list - let key = filter[0].record; + let key = filter[ 0 ].record; for (const entry of filter) { if (entry.record > key) { key = entry.record; } } - for(const entry of filter) { - if(key !== entry.record) { + for (const entry of filter) { + if (key !== entry.record) { continue; } - return entry + return entry; } return undefined; } \ No newline at end of file diff --git a/src/windows/eventlogs/services.ts b/src/windows/eventlogs/services.ts index f907a395..5ba1e26f 100644 --- a/src/windows/eventlogs/services.ts +++ b/src/windows/eventlogs/services.ts @@ -7,12 +7,16 @@ import { getEventlogs } from "../eventlogs"; /** * Function to extract Service install events from EventLog - * @param path Path to the System.evtx file + * @param alt_path Optional alternative path to System.evtx. Default is path `C:\Windows\System32\winevt\Logs\System.evtx` * @returns Array of `ServiceInstalls` or `WindowsError` */ export function serviceInstalls( - path: string, + alt_path?: string, ): ServiceInstalls[] | WindowsError { + let path = "C:\\Windows\\System32\\winevt\\Logs\\System.evtx"; + if (alt_path !== undefined) { + path = alt_path + } let offset = 0; const limit = 10000; const events = []; @@ -50,6 +54,11 @@ export function serviceInstalls( process_id: entry.data.Event.System.Execution["#attributes"].ProcessID, thread_id: entry.data.Event.System.Execution["#attributes"].ThreadID, sid: entry.data.Event.System.Security["#attributes"].UserID, + message: `Service "${entry.data.Event.EventData["ServiceName"]}" installed`, + datetime: entry.timestamp, + timestamp_desc: "Windows Service Installed", + artifact: "EventLog Service 7045", + data_type: "windows:eventlog:system:service" }; events.push(service); } @@ -68,17 +77,106 @@ function isInstall(record: RawService7045): record is RawService7045 { typeof record.data.Event.System.EventID === "number" && record.data.Event.System.EventID === 7045 && record.data.Event.System.Provider["#attributes"].Name === - "Service Control Manager" + "Service Control Manager" ) { return true; } else if ( typeof record.data.Event.System.EventID === "object" && record.data.Event.System.EventID["#text"] === 7045 && record.data.Event.System.Provider["#attributes"].Name === - "Service Control Manager" + "Service Control Manager" ) { return true; } return false; } + +/** + * Function to test Windows Service install parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the Windows Service install parsing + */ +export function testServiceInstalls(): void { + const test = "../../tests/test_data/windows/eventlogs/System.evtx"; + const results = serviceInstalls(test); + if (results instanceof WindowsError) { + throw results; + } + + if (results.length !== 16) { + throw `Got ${results.length} service install events, expected 16.......serviceInstalls āŒ`; + } + if (results[1] === undefined) { + throw `Got undefined service install.......serviceInstalls āŒ`; + } + if (results[1].message != 'Service "Intel(R) PRO/1000 NDIS 6 Adapter Driver" installed') { + throw `Got ${results[1].message}, expected 'Service "Intel(R) PRO/1000 NDIS 6 Adapter Driver" installed'.......serviceInstalls āŒ`; + } + + console.info(` Function serviceInstalls āœ…`); + + const dumb: RawService7045 = { + event_record_id: 0, + timestamp: "", + data: { + Event: { + "#attributes": { + xmlns: "" + }, + System: { + Provider: { + "#attributes": { + Name: "", + Guid: "", + EventSourceName: "" + } + }, + EventID: 11, + Version: 0, + Level: 0, + Task: 0, + Opcode: 0, + Keywords: "", + TimeCreated: { + "#attributes": { + SystemTime: "" + } + }, + EventRecordID: 0, + Correlation: { + "#attributes": { + ActivityID: "" + } + }, + Execution: { + "#attributes": { + ProcessID: 0, + ThreadID: 0 + } + }, + Channel: "", + Computer: "", + Security: { + "#attributes": { + UserID: "" + } + } + }, + EventData: { + ServiceName: "", + ImagePath: "", + ServiceType: "", + StartType: "", + AccountName: "" + } + } + } + }; + if (isInstall(dumb)) { + throw `Got install event with bad data.......isInstall āŒ` + } + + console.info(` Function isInstall āœ…`); + +} \ No newline at end of file diff --git a/src/windows/jumplists.ts b/src/windows/jumplists.ts index f85d294f..e58568ae 100644 --- a/src/windows/jumplists.ts +++ b/src/windows/jumplists.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getJumplists(path?: string): Jumplists[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_jumplists(path); return data; } catch (err) { diff --git a/src/windows/ntfs.ts b/src/windows/ntfs.ts index bfe0133e..9eaa68ec 100644 --- a/src/windows/ntfs.ts +++ b/src/windows/ntfs.ts @@ -10,7 +10,7 @@ import { WindowsError } from "./errors"; */ export function readRawFile(path: string): Uint8Array | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Uint8Array = js_read_raw_file(path); return data; } catch (err) { @@ -32,7 +32,7 @@ export function readAdsData( ads_name: string, ): Uint8Array | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Uint8Array = js_read_ads( path, ads_name, diff --git a/src/windows/outlook.ts b/src/windows/outlook.ts index 902ec2e1..02d5d47b 100644 --- a/src/windows/outlook.ts +++ b/src/windows/outlook.ts @@ -29,7 +29,7 @@ export class Outlook { */ public rootFolder(): FolderInfo | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: FolderInfo = js_root_folder( this.path, this.use_ntfs, @@ -51,7 +51,7 @@ export class Outlook { */ public readFolder(folder: number): FolderInfo | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: FolderInfo = js_read_folder( this.path, this.use_ntfs, @@ -74,7 +74,7 @@ export class Outlook { */ public folderMetadata(folder: number): FolderMetadata | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: FolderMetadata = js_folder_meta( this.path, this.use_ntfs, @@ -96,7 +96,7 @@ export class Outlook { */ public messageStore(): PropertyContext[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: PropertyContext[] = js_message_store( this.path, this.use_ntfs, @@ -117,7 +117,7 @@ export class Outlook { */ public nameMaps(): Record | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Record = js_name_map( this.path, this.use_ntfs, @@ -152,7 +152,7 @@ export class Outlook { table.rows = rows; try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: MessageDetails[] = js_read_messages( this.path, this.use_ntfs, @@ -180,7 +180,7 @@ export class Outlook { descriptor_id: number, ): Attachment | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data: Attachment = js_read_attachment( this.path, this.use_ntfs, diff --git a/src/windows/pe.ts b/src/windows/pe.ts index b1f7865b..068a3db8 100644 --- a/src/windows/pe.ts +++ b/src/windows/pe.ts @@ -8,8 +8,8 @@ import { WindowsError } from "./errors"; */ export function getPe(path: string): PeInfo | WindowsError { try { - //@ts-ignore: Custom Artemis functionjs_ - const data: PeInfo = get_pe(path); + // @ts-expect-error: Custom Artemis function + const data: PeInfo = js_get_pe(path); return data; } catch (err) { return new WindowsError("PE", `failed to parse PE file ${path}: ${err}`); diff --git a/src/windows/powershell.ts b/src/windows/powershell.ts index 3dc42e72..a4b1cf56 100644 --- a/src/windows/powershell.ts +++ b/src/windows/powershell.ts @@ -106,7 +106,7 @@ export function testPowerShellHistory(): void { console.info(` Function powershellHistory āœ…`); - let values = parsePowershellHistory(test, PlatformType.Windows); + const values = parsePowershellHistory(test, PlatformType.Windows); if (values instanceof WindowsError) { throw values; } diff --git a/src/windows/prefetch.ts b/src/windows/prefetch.ts index 513d7905..8810e80d 100644 --- a/src/windows/prefetch.ts +++ b/src/windows/prefetch.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getPrefetch(path?: string): Prefetch[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_prefetch(path); return data; diff --git a/src/windows/recyclebin.ts b/src/windows/recyclebin.ts index 63e3a285..4a39a68a 100644 --- a/src/windows/recyclebin.ts +++ b/src/windows/recyclebin.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getRecycleBin(path?: string): RecycleBin[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_recycle_bin(path); return data; diff --git a/src/windows/registry.ts b/src/windows/registry.ts index ab03d151..1820385c 100644 --- a/src/windows/registry.ts +++ b/src/windows/registry.ts @@ -4,12 +4,14 @@ import { WindowsError } from "./errors"; /** * Function to parse a `Registry` file * @param path Full path to a `Registry` file + * @param [regex=""] Optional Rust compatible regular expression to filter Registry Key paths. All regex comparisons are done in lowercase. Registry values are not filtered + * @param [start_path=""] Optional Registry Key path to start * @returns `Registry` array or `WindowsError` */ -export function getRegistry(path: string): Registry[] | WindowsError { +export function getRegistry(path: string, regex = "", start_path = ""): Registry[] | WindowsError { try { - //@ts-ignore: Custom Artemis function - const data = js_registry(path); + // @ts-expect-error: Custom Artemis function + const data = js_registry(path, regex.toLowerCase(), start_path); return data; } catch (err) { @@ -34,7 +36,7 @@ export function lookupSecurityKey( return new WindowsError("REGISTRY", "Cannot use negative offset or zero!"); } try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_sk_info(path, offset); return data; diff --git a/src/windows/registry/bam.ts b/src/windows/registry/bam.ts index 0c4a8978..0db1bb09 100644 --- a/src/windows/registry/bam.ts +++ b/src/windows/registry/bam.ts @@ -20,7 +20,7 @@ export function backgroundActivitiesManager(alt_path?: string): Bam[] | WindowsE } const reg_data = getRegistry(path); if (reg_data instanceof WindowsError) { - return new WindowsError(`BAM`, `failed to parse ${path}: ${reg_data}`); + return new WindowsError(`BAM`, `failed to parse ${path}: ${reg_data.message}`); } const values: Bam[] = []; diff --git a/src/windows/registry/eventlog_providers.ts b/src/windows/registry/eventlog_providers.ts new file mode 100644 index 00000000..24fcc6f1 --- /dev/null +++ b/src/windows/registry/eventlog_providers.ts @@ -0,0 +1,218 @@ +import { Registry } from "../../../types/windows/registry"; +import { ChannelType, RegistryEventlogProviders } from "../../../types/windows/registry/eventlog_providers"; +import { WindowsError } from "../errors"; +import { getRegistry } from "../registry"; + +/** + * Function to list registered Windows EventLog providers + * @param alt_path Optional alternative path to the Windows Registry file + * @returns Array of `RegistryEventlogProviders` + */ +export function getEventlogProviders(alt_path?: string): RegistryEventlogProviders[] { + let default_paths = ["C:\\Windows\\System32\\config\\SYSTEM", "C:\\Windows\\System32\\config\\SOFTWARE"]; + if (alt_path !== undefined) { + default_paths = [alt_path]; + } + + const providers: RegistryEventlogProviders[] = []; + const pub: Record = {}; + for (const entry of default_paths) { + if (entry.endsWith("SYSTEM")) { + const system_filter = ".*ControlSet.*\\\\Services\\\\EventLog\\\\.*"; + const results = getRegistry(entry, system_filter); + if (results instanceof WindowsError) { + continue; + } + for (const value of results) { + if (value.values.length === 0) { + continue; + } + const info = extractProviderInfo(value); + if (info.message_file === "" && info.parameter_file === "" && info.guid === "") { + continue; + } + providers.push(info); + } + } else if (entry.endsWith("SOFTWARE")) { + const system_filter = ".*CurrentVersion.*\\\\WINEVT\\\\Channels|Publishers\\\\.*"; + const results = getRegistry(entry, system_filter); + if (results instanceof WindowsError) { + continue; + } + for (const value of results) { + if (value.values.length === 0) { + continue; + } + const info = extractPublisherInfo(value); + if (info.guid === "") { + continue; + } + const pub_value = pub[info.guid]; + if (pub_value !== undefined) { + pub_value.names = pub_value.names.concat(info.names); + pub_value.channel_types = pub_value.channel_types.concat(info.channel_types); + if (pub_value.message_file === "") { + pub_value.message_file = info.message_file; + } else if (pub_value.parameter_file === "") { + pub_value.parameter_file = info.parameter_file; + } + if(info.enabled) { + pub_value.enabled = info.enabled; + } + continue; + } + + pub[info.guid] = info; + } + } + } + + for (let i = 0; i < providers.length; i++) { + const entry = providers[i]; + if (entry === undefined) { + continue; + } + if (entry.guid === "") { + const value = pub[entry.name.toLowerCase()]; + if (value === undefined) { + continue; + } + entry.guid = value.guid; + entry.enabled = value.enabled; + entry.channel_types = value.channel_types; + entry.channel_names = value.names; + } else { + const value = pub[entry.guid.toLowerCase()]; + if (value === undefined) { + continue; + } + entry.guid = value.guid; + entry.enabled = value.enabled; + entry.channel_types = value.channel_types; + entry.channel_names = value.names; + } + } + + Object.keys(pub).forEach(key => { + const value = pub[key]; + if (value !== undefined && (value.message_file !== "" || value.parameter_file !== "")) { + const prov_value: RegistryEventlogProviders = { + registry_file: value.registry_file, + key_path: value.key_path.split("/").at(0) ?? "", + name: value.names.at(0) ?? "Unknown", + channel_names: value.names, + message_file: value.message_file, + last_modified: value.last_modified, + parameter_file: value.parameter_file, + guid: value.guid, + enabled: value.enabled, + channel_types: value.channel_types, + }; + providers.push(prov_value); + } + }) + + return providers; +} + +function extractProviderInfo(value: Registry): RegistryEventlogProviders { + const values: RegistryEventlogProviders = { + registry_file: value.registry_path, + key_path: value.path, + name: value.name, + channel_names: [], + message_file: "", + last_modified: value.last_modified, + parameter_file: "", + guid: "", + enabled: false, + channel_types: [] + }; + for (const entry of value.values) { + if (entry.value.toLowerCase() === "providerguid") { + values.guid = entry.data; + } else if (entry.value.toLowerCase() === "eventmessagefile") { + values.message_file = entry.data; + } else if (entry.value.toLowerCase() === "parametermessagefile") { + values.parameter_file = entry.data; + } + } + return values; +} + +interface Publisher { + guid: string; + names: string[]; + enabled: boolean; + channel_number: number; + channel_types: ChannelType[]; + message_file: string; + parameter_file: string; + registry_file: string; + key_path: string; + last_modified: string; +} + +function extractPublisherInfo(values: Registry): Publisher { + const value: Publisher = { + guid: "", + names: [], + enabled: false, + channel_number: 0, + channel_types: [], + message_file: "", + parameter_file: "", + registry_file: values.registry_path, + key_path: values.path, + last_modified: values.last_modified, + }; + for (const entry of values.values) { + if (values.path.includes("Publishers") && values.name.startsWith("{")) { + if (entry.value === "(default)") { + value.guid = values.name; + value.names.push(entry.data); + } else if (entry.value === "MessageFileName") { + value.message_file = entry.data; + } else if (entry.value === "ParameterFileName") { + value.parameter_file = entry.data; + } + } else if (values.path.includes("Publishers") && values.path.includes("ChannelReferences")) { + if (entry.value === "(default)") { + value.guid = `{${(values.path.split("{").at(1) ?? "").split("}").at(0)}}` + if (entry.data === "Application" || entry.data === "System") { + continue; + } + value.names.push(entry.data); + } + } else if (values.path.includes("Channels\\")) { + if (entry.value.toLowerCase() === "enabled") { + value.enabled = Boolean(Number(entry.data)); + } else if (entry.value.toLowerCase() === "owningpublisher") { + value.guid = entry.data; + } else if (entry.value.toLowerCase() === "type") { + value.channel_number = Number(entry.data); + switch (value.channel_number) { + case 0: { + value.channel_types.push(ChannelType.Admin); + break; + } + case 1: { + value.channel_types.push(ChannelType.Operational); + break; + } + case 2: { + value.channel_types.push(ChannelType.Analytic); + break; + } + case 3: { + value.channel_types.push(ChannelType.Debug); + break; + } + default: break; + } + } + } + } + + return value; +} \ No newline at end of file diff --git a/src/windows/registry/firewall_rules.ts b/src/windows/registry/firewall_rules.ts index fd20f868..4960be32 100644 --- a/src/windows/registry/firewall_rules.ts +++ b/src/windows/registry/firewall_rules.ts @@ -32,7 +32,7 @@ export function firewallRules(alt_file?: string): FirewallRules[] | WindowsError continue; } const entries = value.data.split("|"); - let rule: FirewallRules = { + const rule: FirewallRules = { action: "", active: false, direction: Direction.Unknown, diff --git a/src/windows/registry/recently_used.ts b/src/windows/registry/recently_used.ts index 82cceedc..4566603f 100644 --- a/src/windows/registry/recently_used.ts +++ b/src/windows/registry/recently_used.ts @@ -196,5 +196,4 @@ export function testParseMru(): void { } console.info(` Function assembleMru āœ…`); - } \ No newline at end of file diff --git a/src/windows/registry/run.ts b/src/windows/registry/run.ts new file mode 100644 index 00000000..680bf3f4 --- /dev/null +++ b/src/windows/registry/run.ts @@ -0,0 +1,236 @@ +import { Hashes } from "../../../types/filesystem/files"; +import { Registry } from "../../../types/windows/registry"; +import { RegistryRunKey } from "../../../types/windows/registry/run"; +import { getEnvValue, getSystemDrive } from "../../environment/env"; +import { FileError } from "../../filesystem/errors"; +import { glob, hash, stat } from "../../filesystem/files"; +import { WindowsError } from "../errors"; +import { getPe } from "../pe"; +import { getRegistry } from "../registry"; + +/** + * Function to extract Registry Run key information + * @param alt_path Optional alternative path to a Registry file + * @returns Array of `RegistryRunKey` + */ +export function getRunKeys(alt_path?: string): RegistryRunKey[] { + let drive = getSystemDrive(); + if (drive === "") { + drive = "C:"; + } + let paths = [`${drive}\\Users\\*\\NTUSER.DAT`, `${drive}\\Users\\*\\NTUSER.dat`, `${drive}\\Users\\*\\ntuser.dat`, `${drive}\\Windows\\System32\\config\\SOFTWARE`]; + if (alt_path !== undefined) { + paths = [alt_path]; + } + + const glob_paths: string[] = []; + // Try to get all the Registry files that Run keys for persistence + for (const path of paths) { + const results = glob(path); + if (results instanceof FileError) { + continue; + } + for (const entry of results) { + if (!entry.is_file) { + continue; + } + glob_paths.push(entry.full_path); + } + } + + let run_values: RegistryRunKey[] = []; + // Now parse each Registry file + for (const entry of glob_paths) { + const results = getRegistry(entry, ".*CurrentVersion\\\\Run.*"); + if (results instanceof WindowsError) { + continue; + } + + for (const reg of results) { + const values = parseKeys(reg); + run_values = run_values.concat(values); + } + } + + return run_values; +} + +/** + * Function to extract Run key information + * @param value `Registry` object associated with a Run + * @returns Array of `RegistryRunKey` + */ +function parseKeys(value: Registry): RegistryRunKey[] { + const values: RegistryRunKey[] = []; + for (const entry of value.values) { + const run_value: RegistryRunKey = { + key_modified: value.last_modified, + key_path: value.path, + registry_path: value.registry_path, + registry_file: value.registry_file, + path: "", + created: "", + has_signature: false, + md5: "", + value: entry.data, + name: entry.value, + sha1: "", + sha256: "" + }; + + // Try to get some metadata about the Run key values + if (entry.data.startsWith("%")) { + // Environment values + const env = /%.*?%/g; + for (const entry_match of entry.data.match(env) ?? []) { + const real_value = getEnvValue(entry_match.replaceAll("%", "")); + let path = entry.data.replace(entry_match, real_value); + if(path.includes("/")) { + path = path.split("/").at(0)?.trimEnd() ?? path; + } + const created = getCreation(path); + run_value.created = created; + + const hashes = getHash(path); + run_value.md5 = hashes.md5; + run_value.sha1 = hashes.sha1; + run_value.sha256 = hashes.sha256; + + run_value.has_signature = getPeInfo(path); + run_value.path = path; + + values.push(run_value); + break; + } + } else if (entry.data.startsWith("\"")) { + // Files with cli args + const cmd = /".*?"/; + for (const entry_match of entry.data.match(cmd) ?? []) { + const path = entry_match.replaceAll("\"", ""); + const created = getCreation(path); + run_value.created = created; + + const hashes = getHash(path); + run_value.md5 = hashes.md5; + run_value.sha1 = hashes.sha1; + run_value.sha256 = hashes.sha256; + + run_value.has_signature = getPeInfo(path); + run_value.path = path; + + values.push(run_value); + break; + } + } else if (entry.data.includes("/")) { + // Files with clie args with forward slashes + const file = entry.data.split("/").at(0); + if (file === undefined) { + values.push(run_value); + continue; + } + const path = file.replaceAll("\"", "").trimEnd(); + const created = getCreation(path); + run_value.created = created; + + const hashes = getHash(path); + run_value.md5 = hashes.md5; + run_value.sha1 = hashes.sha1; + run_value.sha256 = hashes.sha256; + + run_value.has_signature = getPeInfo(path); + run_value.path = path; + + values.push(run_value); + } + } + + return values; +} + +/** + * Function to pull the created timestamp for a file + * @param path Path to a file + * @returns Standard created timestamp + */ +function getCreation(path: string): string { + const meta = stat(path); + if (meta instanceof FileError) { + return "1970-01-01T00:00:00.00Z"; + } + return meta.created; +} + +/** + * Function to hash a file associated with the Registry Run key + * @param path Path to a file to hash + * @returns `Hashes` object + */ +function getHash(path: string): Hashes { + const hashes = hash(path, true, true, true); + if (hashes instanceof FileError) { + return { + md5: "", + sha1: "", + sha256: "" + }; + } + return hashes; +} + +/** + * Function to check if PE file has certificate info + * @param path Path to a PE file + * @returns `true` if signed. `false` if not signed + */ +function getPeInfo(path: string): boolean { + const info = getPe(path); + if (info instanceof WindowsError) { + return false; + } + + return info.cert.length !== 0; +} + +/** + * Function to test Windows Registry Run key parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the Windows Registry Run key parsing + */ +export function testGetRunKeys(): void { + const test = "../../tests/test_data/windows/registry/NTUSER.DAT"; + const results = getRunKeys(test); + if (results instanceof WindowsError) { + throw results; + } + + if (results.length !== 2) { + throw `Got ${results.length} expected 2.......getRunKeys āŒ` + } + + if (results[1]?.value !== "%ProgramFiles%\\Windows Mail\\wab.exe /Upgrade") { + throw `Got ${results[1]?.value} expected "%ProgramFiles%\\\\Windows Mail\\\\wab.exe /Upgrade".......getRunKeys āŒ` + } + + console.info(` Function getRunKeys āœ…`); + + + const created = getCreation("C:\\Windows\\notepad.exe"); + if (created === "1970-01-01T00:00:00.00Z") { + throw 'Got bad time.......getCreation āŒ' + } + console.info(` Function getCreation āœ…`); + + + const hash = getHash("C:\\Windows\\notepad.exe"); + if (hash.md5 === "") { + throw 'Got empty hash.......getHash āŒ' + } + console.info(` Function getHash āœ…`); + + const info = getPeInfo("C:\\Windows\\notepad.exe"); + if (info === true) { + throw 'Got signature for notepad? Should be in Catalog?.......getPeInfo āŒ' + } + console.info(` Function getPeInfo āœ…`); + +} \ No newline at end of file diff --git a/src/windows/registry/usb.ts b/src/windows/registry/usb.ts index 16b9c20e..4b781883 100644 --- a/src/windows/registry/usb.ts +++ b/src/windows/registry/usb.ts @@ -59,13 +59,17 @@ function usbSystem(path: string): UsbDevices[] | WindowsError { } for (let i = 0; i < usbs.length; i++) { + const usb_info = usbs[i]; + if(usb_info === undefined) { + continue; + } for (const reg of reg_data) { - if (reg.path.includes(usbs[ i ].tracking_id) && "Partmg") { + if (reg.path.includes(usb_info.tracking_id) && "Partmg") { for (const value of reg.values) { - if (value.value !== "DiskId" || usbs[ i ].disk_id !== "") { + if (value.value !== "DiskId" ||usb_info.disk_id !== "") { continue; } - usbs[ i ].disk_id = value.data.replace("{", "").replace("}", ""); + usb_info.disk_id = value.data.replace("{", "").replace("}", ""); } } else if (reg.path.includes(mounts) && reg.values.length !== 0) { for (const value of reg.values) { @@ -75,50 +79,50 @@ function usbSystem(path: string): UsbDevices[] | WindowsError { } const value_string = extractUtf16String(data); if ( - value_string.includes(usbs[ i ].tracking_id) && + value_string.includes(usb_info.tracking_id) && value.value.includes(":") ) { - usbs[ i ].drive_letter = value.value.split("\\").pop() as string; + usb_info.drive_letter = value.value.split("\\").pop() as string; } } } if ( - reg.path.includes(usbs[ i ].tracking_id) && + reg.path.includes(usb_info.tracking_id) && reg.path.includes("\\USBSTOR\\") && reg.name === "0064" ) { for (const value of reg.values) { - usbs[ i ].first_install = unixEpochToISO( + usb_info.first_install = unixEpochToISO( filetimeToUnixEpoch(BigInt(value.data)), ); } } else if ( - reg.path.includes(usbs[ i ].tracking_id) && + reg.path.includes(usb_info.tracking_id) && reg.path.includes("\\USBSTOR\\") && reg.name === "0065" ) { for (const value of reg.values) { - usbs[ i ].install = unixEpochToISO( + usb_info.install = unixEpochToISO( filetimeToUnixEpoch(BigInt(value.data)), ); } } else if ( - reg.path.includes(usbs[ i ].tracking_id) && + reg.path.includes(usb_info.tracking_id) && reg.path.includes("\\USBSTOR\\") && reg.name === "0066" ) { for (const value of reg.values) { - usbs[ i ].last_connected = unixEpochToISO( + usb_info.last_connected = unixEpochToISO( filetimeToUnixEpoch(BigInt(value.data)), ); } } else if ( - reg.path.includes(usbs[ i ].tracking_id) && + reg.path.includes(usb_info.tracking_id) && reg.path.includes("\\USBSTOR\\") && reg.name === "0067" ) { for (const value of reg.values) { - usbs[ i ].last_removal = unixEpochToISO( + usb_info.last_removal = unixEpochToISO( filetimeToUnixEpoch(BigInt(value.data)), ); } @@ -154,25 +158,29 @@ function usbStor(data: Registry): UsbDevices { const info = (data.key.split("\\").pop() as string).split("&"); for (let i = 0; i < info.length; i++) { + const value = info[i]; + if(value === undefined) { + continue; + } if (i === 0) { - entry.usb_type = info[ i ]; + entry.usb_type = value; } - if (info[ i ].includes("Ven_")) { - entry.vendor = info[ i ].slice(4); + if (value.includes("Ven_")) { + entry.vendor = value.slice(4); } - if (info[ i ].includes("Prod_")) { - entry.product = info[ i ].slice(5); + if (value.includes("Prod_")) { + entry.product = value.slice(5); } - if (info[ i ].includes("Rev_")) { - entry.revision = info[ i ].slice(4); + if (value.includes("Rev_")) { + entry.revision = value.slice(4); } } if (data.name.at(1) !== undefined && data.name.at(1) !== "&") { - entry.tracking_id = data.name.split("&")[ 0 ]; + entry.tracking_id = data.name.split("&")[ 0 ] ?? ""; } for (const value of data.values) { diff --git a/src/windows/registry/wifi.ts b/src/windows/registry/wifi.ts new file mode 100644 index 00000000..107ac290 --- /dev/null +++ b/src/windows/registry/wifi.ts @@ -0,0 +1,210 @@ +import { Registry } from "../../../types/windows/registry"; +import { NameType, Wifi, WifiCategory } from "../../../types/windows/registry/wifi"; +import { decode } from "../../encoding/base64"; +import { EncodingError } from "../../encoding/errors"; +import { getEnvValue } from "../../environment/mod"; +import { NomError } from "../../nom/error"; +import { Endian, nomUnsignedTwoBytes } from "../../nom/helpers"; +import { WindowsError } from "../errors"; +import { getRegistry } from "../registry"; + +/** + * Function to list connected Windows WiFi networks + * @param alt_path Optional alternative path to the `SOFTWARE` Registry file + * @returns Array of `Wifi` entries or `WindowsError` + */ +export function wifiNetworksWindows(alt_path?: string): Wifi[] | WindowsError { + let path = "\\Windows\\System32\\config\\SOFTWARE"; + if (alt_path !== undefined) { + path = alt_path; + } else { + let drive = getEnvValue("SystemDrive"); + if (drive === "") { + drive = "C:"; + } + path = `${drive}${path}`; + } + + const reg_entries = getRegistry(path, "\\\\currentversion\\\\networklist\\\\profiles\\\\\\{"); + if (reg_entries instanceof WindowsError) { + return new WindowsError(`WIFI`, `could not parse the SOFTWARE Registry file ${reg_entries}`); + } + + const profiles: Registry[] = []; + const networks: Wifi[] = []; + for (const entry of profiles) { + const net: Wifi = { + name: "", + description: "", + managed: false, + category: WifiCategory.Unknown, + created_local_time: "", + name_type: NameType.Unknown, + id: entry.name.replace("{", "").replace("}", ""), + last_connected_local_time: "", + registry_path: entry.path, + registry_file: path, + message: "", + datetime: entry.last_modified, + timestamp_desc: "Registry Key Modified", + artifact: "WiFi Network", + data_type: "windows:registry:wifi:entry" + }; + + for (const value of entry.values) { + if (value.value.toLowerCase() === "profilename") { + net.name = value.data; + } else if (value.value.toLowerCase() === "description") { + net.description = value.data; + net.message = `WiFi network '${value.data}'`; + } else if (value.value.toLowerCase() === "managed") { + net.managed = Boolean(Number(value.data)); + } else if (value.value.toLowerCase() === "category") { + switch (value.data) { + case "0": { + net.category = WifiCategory.Public; + break; + } + case "1": { + net.category = WifiCategory.Private; + break; + } + case "2": { + net.category = WifiCategory.Domain; + break; + } + default: net.category = WifiCategory.Unknown; + } + } else if (value.value.toLowerCase() === "datecreated") { + const bytes = decode(value.data); + if (bytes instanceof EncodingError) { + continue; + } + const time_value = decodeTime(bytes); + if (time_value instanceof NomError) { + continue; + } + net.created_local_time = time_value; + } else if (value.value.toLowerCase() === "nametype") { + switch (value.data) { + case "6": { + net.name_type = NameType.Wired; + break; + } + case "23": { + net.name_type = NameType.Vpn; + break; + } + case "71": { + net.name_type = NameType.Wireless; + break; + } + case "243": { + net.name_type = NameType.Mobile; + break; + } + default: net.name_type = NameType.Unknown; + } + } else if (value.value.toLowerCase() === "datelastconnected") { + const bytes = decode(value.data); + if (bytes instanceof EncodingError) { + continue; + } + const time_value = decodeTime(bytes); + if (time_value instanceof NomError) { + continue; + } + net.last_connected_local_time = time_value; + } + } + networks.push(net); + } + + return networks; +} + +/** + * Function to convert Network time bytes to proper timestamp. + * It uses a weird format: https://superuser.com/questions/1572038/ms-regedit-hex-to-date-conversion + * @param bytes Timestamp bytes + * @returns Timestamp or `NomError` + */ +function decodeTime(bytes: Uint8Array): string | NomError { + let input = nomUnsignedTwoBytes(bytes, Endian.Le); + if (input instanceof NomError) { + return input; + } + + const year = input.value; + input = nomUnsignedTwoBytes(input.remaining, Endian.Le); + if (input instanceof NomError) { + return input; + } + let month: number | string = input.value; + if (month < 10) { + month = `0${month}`; + } + + // Day of week (ex: Thursday) + input = nomUnsignedTwoBytes(input.remaining, Endian.Le); + if (input instanceof NomError) { + return input; + } + + input = nomUnsignedTwoBytes(input.remaining, Endian.Le); + if (input instanceof NomError) { + return input; + } + let day: number | string = input.value; + if (day < 10) { + day = `0${day}`; + } + + input = nomUnsignedTwoBytes(input.remaining, Endian.Le); + if (input instanceof NomError) { + return input; + } + let hour: number | string = input.value; + if (hour < 10) { + hour = `0${hour}`; + } + + input = nomUnsignedTwoBytes(input.remaining, Endian.Le); + if (input instanceof NomError) { + return input; + } + let mins: number | string = input.value; + if (mins < 10) { + mins = `0${mins}`; + } + + input = nomUnsignedTwoBytes(input.remaining, Endian.Le); + if (input instanceof NomError) { + return input; + } + let seconds: number | string = input.value; + if (seconds < 10) { + seconds = `0${seconds}`; + } + + return `${year}-${month}-${day}T${hour}:${mins}:${seconds}`; +} + +/** + * Function to test Windows WiFi parsing + * This function should not be called unless you are developing the artemis-api + * Or want to validate the Windows WiFi parsing + */ +export function testWindowsWifiNetworks(): void { + const test = new Uint8Array([233, 7, 7, 0, 4, 0, 10, 0, 1, 0, 10, 0, 43, 0, 94, 3]); + const results = decodeTime(test); + if (results instanceof NomError) { + throw results; + } + + if (results !== "2025-07-10T01:10:43") { + throw `Got ${results} expected "2025-07-10T01:10:43".......decodeTime āŒ` + } + console.info(` Function decodeTime āœ…`); + +} \ No newline at end of file diff --git a/src/windows/search.ts b/src/windows/search.ts index 7d082aa1..36be06ee 100644 --- a/src/windows/search.ts +++ b/src/windows/search.ts @@ -13,7 +13,7 @@ export function getSearch( page_limit = 50, ): SearchEntry[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_search(path, page_limit); return data; diff --git a/src/windows/services.ts b/src/windows/services.ts index 3b691683..f1abcec8 100644 --- a/src/windows/services.ts +++ b/src/windows/services.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getServices(path?: string): Services[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_services(path); return data; } catch (err) { diff --git a/src/windows/shellbags.ts b/src/windows/shellbags.ts index 50303c36..17aa88e5 100644 --- a/src/windows/shellbags.ts +++ b/src/windows/shellbags.ts @@ -12,7 +12,7 @@ export function getShellbags( path?: string, ): Shellbags[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_shellbags(resolve_guids, path); return data; diff --git a/src/windows/shellitems.ts b/src/windows/shellitems.ts index 39b993fe..6fd90d98 100644 --- a/src/windows/shellitems.ts +++ b/src/windows/shellitems.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getShellItem(data: Uint8Array): JsShellItem | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const result = js_shellitems(data); const item: JsShellItem = { item: result.item as ShellItems, diff --git a/src/windows/shimcache.ts b/src/windows/shimcache.ts index de1b6639..f84d84e7 100644 --- a/src/windows/shimcache.ts +++ b/src/windows/shimcache.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getShimcache(path?: string): Shimcache[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_shimcache(path); return data; diff --git a/src/windows/shimdb.ts b/src/windows/shimdb.ts index 3924b75f..fab379f5 100644 --- a/src/windows/shimdb.ts +++ b/src/windows/shimdb.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getShimdb(path?: string): Shimdb[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_shimdb(path); return data; diff --git a/src/windows/shortcuts.ts b/src/windows/shortcuts.ts index 5e4ccc91..8ec8d905 100644 --- a/src/windows/shortcuts.ts +++ b/src/windows/shortcuts.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getLnkFile(path: string): Shortcut | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_lnk(path); return data; diff --git a/src/windows/sqlite/updates.ts b/src/windows/sqlite/updates.ts index 44f37512..fba16eaf 100644 --- a/src/windows/sqlite/updates.ts +++ b/src/windows/sqlite/updates.ts @@ -2,7 +2,7 @@ import { UpdateHistoryV2 } from "../../../types/windows/ese/updates"; import { ApplicationError } from "../../applications/errors"; import { querySqlite } from "../../applications/sqlite"; import { getEnvValue } from "../../environment/env"; -import { filetimeToUnixEpoch, unixEpochToISO } from "../../time/conversion"; +import { unixEpochToISO } from "../../time/conversion"; import { WindowsError } from "../errors"; /** diff --git a/src/windows/srum.ts b/src/windows/srum.ts index e0821a14..1136c1e9 100644 --- a/src/windows/srum.ts +++ b/src/windows/srum.ts @@ -20,7 +20,7 @@ export function getSrumApplicationInfo( ): ApplicationInfo[] | WindowsError { try { const name = "{D10CA2FE-6FCF-4F6D-848E-B2E99266FA89}"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_srum(path, name); return data; @@ -42,7 +42,7 @@ export function getSrumApplicationTimeline( ): ApplicationTimeline[] | WindowsError { try { const name = "{5C8CF1C7-7257-4F13-B223-970EF5939312}"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_srum(path, name); return data; @@ -62,7 +62,7 @@ export function getSrumApplicationTimeline( export function getSrumApplicationVfu(path: string): AppVfu[] | WindowsError { try { const name = "{7ACBBAA3-D029-4BE4-9A7A-0885927F1D8F}"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_srum(path, name); return data; @@ -82,7 +82,7 @@ export function getSrumApplicationVfu(path: string): AppVfu[] | WindowsError { export function getSrumEnergyInfo(path: string): EnergyInfo[] | WindowsError { try { const name = "{DA73FB89-2BEA-4DDC-86B8-6E048C6DA477}"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_srum(path, name); return data; @@ -102,11 +102,11 @@ export function getSrumEnergyInfo(path: string): EnergyInfo[] | WindowsError { export function getSrumEnergyUsage(path: string): EnergyUsage[] | WindowsError { try { let name = "{FEE4E14F-02A9-4550-B5CE-5FA2DA202E37}"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_srum(path, name); name = "{FEE4E14F-02A9-4550-B5CE-5FA2DA202E37}LT"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data_lt: string = js_srum(path, name); const srum_all = data.concat(data_lt); @@ -127,7 +127,7 @@ export function getSrumEnergyUsage(path: string): EnergyUsage[] | WindowsError { export function getSrumNetworkInfo(path: string): NetworkInfo[] | WindowsError { try { const name = "{973F5D5C-1D90-4944-BE8E-24B94231A174}"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_srum(path, name); return data; @@ -149,7 +149,7 @@ export function getSrumNetworkConnectivity( ): NetworkConnectivityInfo[] | WindowsError { try { const name = "{DD6636C4-8929-4683-974E-22C046A43763}"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_srum(path, name); return data; @@ -171,7 +171,7 @@ export function getSrumNotifications( ): NotificationInfo[] | WindowsError { try { const name = "{D10CA2FE-6FCF-4F6D-848E-B2E99266FA86}"; - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_srum(path, name); return data; diff --git a/src/windows/tasks.ts b/src/windows/tasks.ts index dc2bdc49..06197737 100644 --- a/src/windows/tasks.ts +++ b/src/windows/tasks.ts @@ -11,7 +11,7 @@ export function getTasks( path?: string, ): TaskData | TaskJob | TaskXml | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_tasks(path); return data; diff --git a/src/windows/userassist.ts b/src/windows/userassist.ts index 42961ef8..c7cc0240 100644 --- a/src/windows/userassist.ts +++ b/src/windows/userassist.ts @@ -12,7 +12,7 @@ export function getUserassist( path?: string, ): UserAssist[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_userassist(resolve, path); return data; diff --git a/src/windows/users.ts b/src/windows/users.ts index b5226257..1385e8a4 100644 --- a/src/windows/users.ts +++ b/src/windows/users.ts @@ -8,7 +8,7 @@ import { WindowsError } from "./errors"; */ export function getUsersWin(path?: string): UserInfo[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_users_windows(path); return data; } catch (err) { diff --git a/src/windows/usnjrnl.ts b/src/windows/usnjrnl.ts index dd09fb1f..ebadc3fc 100644 --- a/src/windows/usnjrnl.ts +++ b/src/windows/usnjrnl.ts @@ -14,7 +14,7 @@ export function getUsnjrnl( mft?: string, ): UsnJrnl[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_usnjrnl(path, drive, mft); return data; diff --git a/src/windows/wmi.ts b/src/windows/wmi.ts index d21341c2..5951e871 100644 --- a/src/windows/wmi.ts +++ b/src/windows/wmi.ts @@ -8,7 +8,7 @@ import { ClassInfo, IndexBody, Namespace, WmiPersist } from "../../types/windows */ export function getWmiPersist(path?: string): WmiPersist[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_wmipersist(path); return data; @@ -27,7 +27,7 @@ export function getWmiPersist(path?: string): WmiPersist[] | WindowsError { */ export function listNamespaces(namespace = "root", indexes: IndexBody[], object_data: Uint8Array, pages: number[]): Namespace[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_list_namespaces_classes(namespace, indexes, object_data, pages, false); return data; @@ -46,7 +46,7 @@ export function listNamespaces(namespace = "root", indexes: IndexBody[], object_ */ export function listClasses(namespace = "root", indexes: IndexBody[], object_data: Uint8Array, pages: number[]): Record[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_list_namespaces_classes(namespace, indexes, object_data, pages, true); return data; @@ -67,7 +67,7 @@ export function listClasses(namespace = "root", indexes: IndexBody[], object_dat */ export function classDescriptions(namespace: string, locale: number, class_name: string, indexes: IndexBody[], object_data: Uint8Array, pages: number[]): ClassInfo | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_class_description(namespace, locale, class_name, indexes, object_data, pages); return data; @@ -83,7 +83,7 @@ export function classDescriptions(namespace: string, locale: number, class_name: */ export function getWmiPages(map_glob: string): number[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_get_wmi_pages(map_glob); return data; @@ -99,7 +99,7 @@ export function getWmiPages(map_glob: string): number[] | WindowsError { */ export function getWmiIndexes(indexes: Uint8Array): IndexBody[] | WindowsError { try { - //@ts-ignore: Custom Artemis function + // @ts-expect-error: Custom Artemis function const data = js_get_wmi_indexes(indexes); return data; diff --git a/tests/applications/anydesk/main.ts b/tests/applications/anydesk/main.ts index cc9c25ec..0ae4fdf8 100644 --- a/tests/applications/anydesk/main.ts +++ b/tests/applications/anydesk/main.ts @@ -1,4 +1,4 @@ -import { AnyDesk, dumpData, Format, Output, OutputType, PlatformType } from "../../../mod"; +import { AnyDesk, PlatformType } from "../../../mod"; import { testReadConfig, testReadTrace } from "../../test"; function main() { @@ -11,7 +11,7 @@ function main() { throw `Got ${hits.length} rows. Expected 2872`; } const configs = results.configs(used_alt_dir); - if(configs.length !== 2) { + if (configs.length !== 2) { throw `Got ${hits.length} rows. Expected 2`; } diff --git a/tests/applications/compile_tests.py b/tests/applications/compile_tests.py new file mode 100644 index 00000000..c2414c73 --- /dev/null +++ b/tests/applications/compile_tests.py @@ -0,0 +1,150 @@ +# AI took my simple 15 line bash script and turned it into a nice ~180 line Python script XD + +from pathlib import Path +import subprocess +import sys +import os +import time +from datetime import datetime +from contextlib import contextmanager +from statistics import mean, median, quantiles + +from colorama import init, Fore, Style + +# Initialize colorama (needed for Windows) +init(autoreset=True) + +@contextmanager +def pushd(new_dir: Path): + """Temporarily change working directory like `cd` in Bash.""" + prev_dir = Path.cwd() + try: + os.chdir(new_dir) + yield + finally: + os.chdir(prev_dir) + +def run_tests(): + base_dir = Path.cwd() + total_start = time.perf_counter() + + total_tests = 0 + passed_tests = 0 + durations = [] # (project_name, elapsed_time) + + for entry in base_dir.iterdir(): + if not entry.is_dir(): + continue + + total_tests += 1 + with pushd(entry): + start_time = time.perf_counter() + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + print(f"\n{Fore.CYAN}[{timestamp}] šŸ”„ Running test for {entry.name} šŸ”„{Style.RESET_ALL}") + + # Run esbuild + try: + subprocess.run( + ["esbuild", "--log-level=silent", "--bundle", "--outfile=main.js", "main.ts"], + check=True + ) + except subprocess.CalledProcessError: + print(f"{Fore.RED}āŒ Failed to build {entry.name}{Style.RESET_ALL}") + break + + # Run script_tester + try: + subprocess.run( + [str(base_dir / "script_tester"), "main.js"], + check=True + ) + except subprocess.CalledProcessError: + print(f"{Fore.RED}āŒ Failed test for {entry.name}{Style.RESET_ALL}") + break + else: + passed_tests += 1 + + # Duration reporting + elapsed = time.perf_counter() - start_time + durations.append((entry.name, elapsed)) + print(f"{Fore.GREEN}āœ… Completed {entry.name} in {elapsed:.2f} seconds{Style.RESET_ALL}") + + # Totals + total_elapsed = time.perf_counter() - total_start + print(f"\n{Fore.MAGENTA}šŸ“Š Test Summary{Style.RESET_ALL}") + print(f" Total tests: {total_tests}") + print(f" {Fore.GREEN}Passed: {passed_tests}{Style.RESET_ALL}") + print(f" {Fore.RED}Failed: {total_tests - passed_tests}{Style.RESET_ALL}") + print(f" Total time: {total_elapsed:.2f} seconds") + + # Stats + if durations: + slowest = max(durations, key=lambda x: x[1]) + fastest = min(durations, key=lambda x: x[1]) + times = [d[1] for d in durations] + + avg_time = mean(times) + q25, q50, q75 = quantiles(times, n=4) # quartiles + + print(f" {Fore.YELLOW}🐢 Slowest project: {slowest[0]} " + f"({slowest[1]:.2f} seconds){Style.RESET_ALL}") + print(f" {Fore.CYAN}⚔ Fastest project: {fastest[0]} " + f"({fastest[1]:.2f} seconds){Style.RESET_ALL}") + print(f" {Fore.BLUE}šŸ“ˆ Average duration: {avg_time:.2f} seconds{Style.RESET_ALL}") + print(f" {Fore.BLUE}šŸ“Š Median duration: {median(times):.2f} seconds{Style.RESET_ALL}") + + # Pareto 80% cumulative time + sorted_durations = sorted(durations, key=lambda x: x[1], reverse=True) + cumulative = 0.0 + cutoff = 0.8 * sum(times) + pareto_list = [] + for name, t in sorted_durations: + cumulative += t + pareto_list.append((name, t)) + if cumulative >= cutoff: + break + + print(f"\n{Fore.MAGENTA}šŸ“Œ Top 80% time contributors (Pareto){Style.RESET_ALL}") + for name, t in pareto_list: + print(f" {Fore.YELLOW}{name:<20}{t:.2f} sec{Style.RESET_ALL}") + + # Histogram chart with color coding + percentile + cumulative % + print(f"\n{Fore.MAGENTA}šŸ“Š Runtime Histogram (with percentiles & cumulative){Style.RESET_ALL}") + max_time = slowest[1] + scale = 40 / max_time if max_time > 0 else 1 + total_time = sum(times) + cumulative = 0.0 + + for name, t in sorted_durations: + cumulative += t + bar = "ā–ˆ" * int(t * scale) + # Color by relative speed + if t <= 0.75 * avg_time: + color = Fore.GREEN + elif t <= 1.25 * avg_time: + color = Fore.YELLOW + else: + color = Fore.RED + + # Percentile marker + if t <= q25: + marker = " (≤25th %ile)" + elif t <= q50: + marker = " (≤50th %ile)" + elif t <= q75: + marker = " (≤75th %ile)" + else: + marker = " (>75th %ile)" + + # Cumulative percentage + cum_pct = (cumulative / total_time) * 100 + print(f" {name:<20} {color}{bar}{Style.RESET_ALL} {t:.2f}s{marker} " + f"→ {cum_pct:5.1f}% total") + + # Exit code mirrors success/failure + if passed_tests < total_tests: + sys.exit(1) + +if __name__ == "__main__": + run_tests() \ No newline at end of file diff --git a/tests/applications/compile_tests.sh b/tests/applications/compile_tests.sh deleted file mode 100644 index 83491d60..00000000 --- a/tests/applications/compile_tests.sh +++ /dev/null @@ -1,14 +0,0 @@ -# Compile all test TypeScript files -for entry in */ -do -cd $entry -echo "šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„ Running test for $entry šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„" -esbuild --log-level=silent --bundle --outfile=main.js main.ts -if ../script_tester main.js -then - cd .. -else - echo "Failed test for $entry" - exit 1 -fi -done \ No newline at end of file diff --git a/tests/applications/edge/main.ts b/tests/applications/edge/main.ts new file mode 100644 index 00000000..db1b5c6b --- /dev/null +++ b/tests/applications/edge/main.ts @@ -0,0 +1,46 @@ +import { Edge, Format, Output, OutputType, PlatformType } from "../../../mod"; +import { testChromiumJsonFiles, testChromiumLocalStorage, testChromiumPreferences, testChromiumSessions, testChromiumSqlite } from "../../test"; + +function main() { + console.log('Running Microsoft Edge tests....'); + console.log(' Starting live test....'); + const client = new Edge(PlatformType.Darwin); + const out: Output = { + name: "edge_test", + directory: "./tmp", + format: Format.JSONL, + compress: false, + timeline: false, + endpoint_id: "", + collection_id: 0, + output: OutputType.LOCAL + }; + client.retrospect(out); + + + console.log(' Live test passed! 🄳\n'); + + console.log('Starting Microsoft Edge JSON tests....'); + testChromiumJsonFiles(); + console.log(' Microsoft Edge JSON tests passed! 🄳\n'); + + console.log('Starting Microsoft Edge Preferences tests....'); + testChromiumPreferences(); + console.log(' Microsoft Edge Preferences tests passed! 🄳\n'); + + console.log('Starting Microsoft Edge Local Storage tests....'); + testChromiumLocalStorage(); + console.log(' Microsoft Edge Local Storage tests passed! 🄳\n'); + + console.log('Starting Microsoft Edge Sessions tests....'); + testChromiumSessions(); + console.log(' Microsoft Edge Sessions tests passed! 🄳\n'); + + console.log('Starting Microsoft Edge SQLITE tests....'); + testChromiumSqlite(); + console.log(' Microsoft Edge SQLITE tests passed! 🄳\n'); + + console.log('All Microsoft Edge tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +main(); diff --git a/tests/linux/browsers/main.ts b/tests/linux/browsers/main.ts index 5402e259..62c3a992 100644 --- a/tests/linux/browsers/main.ts +++ b/tests/linux/browsers/main.ts @@ -2,22 +2,23 @@ import { Chromium, PlatformType } from "../../../mod"; import { BrowserType } from "../../../types/applications/chromium"; function main() { + console.log('Running Linux Chromium tests....'); + console.log(' Starting live test....'); const chromium_client = new Chromium(PlatformType.Linux, true, BrowserType.CHROMIUM); - console.log(`Chromium browser info: ${JSON.stringify(chromium_client)}`); - let history_hits = chromium_client.history(); + const history_hits = chromium_client.history(); if (history_hits.length === 0) { throw "No history???"; } - console.log(`Chromium history: ${JSON.stringify(history_hits[0])}`); - let cookie_hits = chromium_client.cookies(); + const cookie_hits = chromium_client.cookies(); if (cookie_hits.length === 0) { throw "No history???"; } + console.log(' Live test passed! 🄳\n'); + console.log('All Linux Chromium tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); - console.log(`Chromium cookies: ${JSON.stringify(cookie_hits[0])}`); } main(); diff --git a/tests/linux/circlu/main.ts b/tests/linux/circlu/main.ts new file mode 100644 index 00000000..b9860b48 --- /dev/null +++ b/tests/linux/circlu/main.ts @@ -0,0 +1,72 @@ +import { glob, hash } from "../../../mod"; +import { FileError } from "../../../src/filesystem/errors"; +import { circluHashlookup } from "../../../src/http/circlu"; +import { HttpError } from "../../../src/http/errors"; +import { HashlookupResponse, HashType, MissingHash } from "../../../types/http/circlu"; +import { testCircluHashlookup } from "../../test"; + +async function main() { + console.log('Running HTTP circlu tests....'); + console.log(' Starting live test....'); + const paths = glob("/bin/*"); + if (paths instanceof FileError) { + throw paths; + } + const limit = 10; + let count = 0; + const hash_array: string[] = [ "DCB0BDEF5B211DF6E0CB8B9BB6C037D3" ]; + for (const entry of paths) { + if (count === limit) { + break; + } + if (!entry.is_file) { + continue; + } + + const hashes = hash(entry.full_path, true, false, false); + if (hashes instanceof FileError) { + throw hashes; + } + hash_array.push(hashes.md5); + count++; + } + const results = await circluHashlookup(hash_array, HashType.MD5); + + if (results instanceof HttpError) { + throw results; + } + if (isMissing(results) || !Array.isArray(results)) { + throw console.log(`Did not get an array from response`); + } + + if (results.length !== 1) { + throw console.log(`Did not get expected array length`); + } + const single_hash = "DCB0BDEF5B211DF6E0CB8B9BB6C037D3"; + const response = await circluHashlookup(single_hash, HashType.MD5); + if (response instanceof HttpError) { + throw response; + } + if (isMissing(response) || Array.isArray(response)) { + throw `Got array or missing ${response}`; + } + if (response.FileName !== "./usr/bin/alsaunmute") { + throw response; + } + if (response.FileSize !== "127") { + throw response; + } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting circlu test....'); + await testCircluHashlookup(); + + console.log(' circlu test passed! 🄳'); + console.log('All circlu tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +function isMissing(value: MissingHash | HashlookupResponse | HashlookupResponse[]): value is MissingHash { + return 'query' in value; +} + +main(); diff --git a/tests/linux/compile_tests.py b/tests/linux/compile_tests.py new file mode 100644 index 00000000..c2414c73 --- /dev/null +++ b/tests/linux/compile_tests.py @@ -0,0 +1,150 @@ +# AI took my simple 15 line bash script and turned it into a nice ~180 line Python script XD + +from pathlib import Path +import subprocess +import sys +import os +import time +from datetime import datetime +from contextlib import contextmanager +from statistics import mean, median, quantiles + +from colorama import init, Fore, Style + +# Initialize colorama (needed for Windows) +init(autoreset=True) + +@contextmanager +def pushd(new_dir: Path): + """Temporarily change working directory like `cd` in Bash.""" + prev_dir = Path.cwd() + try: + os.chdir(new_dir) + yield + finally: + os.chdir(prev_dir) + +def run_tests(): + base_dir = Path.cwd() + total_start = time.perf_counter() + + total_tests = 0 + passed_tests = 0 + durations = [] # (project_name, elapsed_time) + + for entry in base_dir.iterdir(): + if not entry.is_dir(): + continue + + total_tests += 1 + with pushd(entry): + start_time = time.perf_counter() + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + print(f"\n{Fore.CYAN}[{timestamp}] šŸ”„ Running test for {entry.name} šŸ”„{Style.RESET_ALL}") + + # Run esbuild + try: + subprocess.run( + ["esbuild", "--log-level=silent", "--bundle", "--outfile=main.js", "main.ts"], + check=True + ) + except subprocess.CalledProcessError: + print(f"{Fore.RED}āŒ Failed to build {entry.name}{Style.RESET_ALL}") + break + + # Run script_tester + try: + subprocess.run( + [str(base_dir / "script_tester"), "main.js"], + check=True + ) + except subprocess.CalledProcessError: + print(f"{Fore.RED}āŒ Failed test for {entry.name}{Style.RESET_ALL}") + break + else: + passed_tests += 1 + + # Duration reporting + elapsed = time.perf_counter() - start_time + durations.append((entry.name, elapsed)) + print(f"{Fore.GREEN}āœ… Completed {entry.name} in {elapsed:.2f} seconds{Style.RESET_ALL}") + + # Totals + total_elapsed = time.perf_counter() - total_start + print(f"\n{Fore.MAGENTA}šŸ“Š Test Summary{Style.RESET_ALL}") + print(f" Total tests: {total_tests}") + print(f" {Fore.GREEN}Passed: {passed_tests}{Style.RESET_ALL}") + print(f" {Fore.RED}Failed: {total_tests - passed_tests}{Style.RESET_ALL}") + print(f" Total time: {total_elapsed:.2f} seconds") + + # Stats + if durations: + slowest = max(durations, key=lambda x: x[1]) + fastest = min(durations, key=lambda x: x[1]) + times = [d[1] for d in durations] + + avg_time = mean(times) + q25, q50, q75 = quantiles(times, n=4) # quartiles + + print(f" {Fore.YELLOW}🐢 Slowest project: {slowest[0]} " + f"({slowest[1]:.2f} seconds){Style.RESET_ALL}") + print(f" {Fore.CYAN}⚔ Fastest project: {fastest[0]} " + f"({fastest[1]:.2f} seconds){Style.RESET_ALL}") + print(f" {Fore.BLUE}šŸ“ˆ Average duration: {avg_time:.2f} seconds{Style.RESET_ALL}") + print(f" {Fore.BLUE}šŸ“Š Median duration: {median(times):.2f} seconds{Style.RESET_ALL}") + + # Pareto 80% cumulative time + sorted_durations = sorted(durations, key=lambda x: x[1], reverse=True) + cumulative = 0.0 + cutoff = 0.8 * sum(times) + pareto_list = [] + for name, t in sorted_durations: + cumulative += t + pareto_list.append((name, t)) + if cumulative >= cutoff: + break + + print(f"\n{Fore.MAGENTA}šŸ“Œ Top 80% time contributors (Pareto){Style.RESET_ALL}") + for name, t in pareto_list: + print(f" {Fore.YELLOW}{name:<20}{t:.2f} sec{Style.RESET_ALL}") + + # Histogram chart with color coding + percentile + cumulative % + print(f"\n{Fore.MAGENTA}šŸ“Š Runtime Histogram (with percentiles & cumulative){Style.RESET_ALL}") + max_time = slowest[1] + scale = 40 / max_time if max_time > 0 else 1 + total_time = sum(times) + cumulative = 0.0 + + for name, t in sorted_durations: + cumulative += t + bar = "ā–ˆ" * int(t * scale) + # Color by relative speed + if t <= 0.75 * avg_time: + color = Fore.GREEN + elif t <= 1.25 * avg_time: + color = Fore.YELLOW + else: + color = Fore.RED + + # Percentile marker + if t <= q25: + marker = " (≤25th %ile)" + elif t <= q50: + marker = " (≤50th %ile)" + elif t <= q75: + marker = " (≤75th %ile)" + else: + marker = " (>75th %ile)" + + # Cumulative percentage + cum_pct = (cumulative / total_time) * 100 + print(f" {name:<20} {color}{bar}{Style.RESET_ALL} {t:.2f}s{marker} " + f"→ {cum_pct:5.1f}% total") + + # Exit code mirrors success/failure + if passed_tests < total_tests: + sys.exit(1) + +if __name__ == "__main__": + run_tests() \ No newline at end of file diff --git a/tests/linux/compile_tests.sh b/tests/linux/compile_tests.sh deleted file mode 100644 index 83491d60..00000000 --- a/tests/linux/compile_tests.sh +++ /dev/null @@ -1,14 +0,0 @@ -# Compile all test TypeScript files -for entry in */ -do -cd $entry -echo "šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„ Running test for $entry šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„" -esbuild --log-level=silent --bundle --outfile=main.js main.ts -if ../script_tester main.js -then - cd .. -else - echo "Failed test for $entry" - exit 1 -fi -done \ No newline at end of file diff --git a/tests/linux/eol/main.ts b/tests/linux/eol/main.ts new file mode 100644 index 00000000..fee450ac --- /dev/null +++ b/tests/linux/eol/main.ts @@ -0,0 +1,30 @@ +import { testCheckEolStatus } from "../../test"; +import { HttpError } from "../../../src/http/errors"; +import { checkEolStatus } from "../../../src/http/eol"; + +async function main() { + console.log('Running HTTP End of Life tests....'); + console.log(' Starting live test....'); + const app = "libreoffice"; + const version = "25.2"; + const result = await checkEolStatus(app, version); + if (result instanceof HttpError) { + throw console.log(result); + } + if (result.url !== "https://endoflife.date/libreoffice") { + throw console.log(`Got empty URL wanted ${result.url}`); + } + if (result.latest_release_date !== "2025-09-01") { + throw console.log(`Got empty URL wanted ${result.latest_release_date}`); + } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting End of Life test....'); + await testCheckEolStatus(); + + console.log(' End of Life test passed! 🄳'); + console.log('All End of Life tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + + +main(); diff --git a/tests/linux/gvfs/main.ts b/tests/linux/gvfs/main.ts new file mode 100644 index 00000000..d4d36bf8 --- /dev/null +++ b/tests/linux/gvfs/main.ts @@ -0,0 +1,22 @@ +import { parseGvfs } from "../../../mod"; +import { LinuxError } from "../../../src/linux/errors"; +import { testParseGvfs } from "../../test"; + +function main() { + console.log('Running GNOME GVFS tests....'); + console.log(' Starting live test....'); + const results = parseGvfs(); + if (results instanceof LinuxError) { + throw results; + } + + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting GNOME GVFS test....'); + testParseGvfs(); + + console.log(' GNOME GVFS test passed! 🄳'); + console.log('All GNOME GVFS tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +main(); diff --git a/tests/linux/logons/main.ts b/tests/linux/logons/main.ts new file mode 100644 index 00000000..cde4392a --- /dev/null +++ b/tests/linux/logons/main.ts @@ -0,0 +1,21 @@ +import { queryLogons } from "../../../mod"; +import { LinuxError } from "../../../src/linux/errors"; +import { testQueryLogons } from "../../test"; + +function main() { + console.log('Running Logons tests....'); + console.log(' Starting live test....'); + const results = queryLogons(); + if (results instanceof LinuxError && !results.message.includes("unable to open database file")) { + throw results; + } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting wtmpdb query test....'); + testQueryLogons(); + + console.log(' WTMPDB query test passed! 🄳'); + console.log('All logons tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +main(); diff --git a/tests/linux/usage/main.ts b/tests/linux/usage/main.ts new file mode 100644 index 00000000..a43736a6 --- /dev/null +++ b/tests/linux/usage/main.ts @@ -0,0 +1,22 @@ +import { gnomeAppUsage } from "../../../mod"; +import { LinuxError } from "../../../src/linux/errors"; +import { testGnomeAppUsage } from "../../test"; + +function main() { + console.log('Running GNOME Application Usage tests....'); + console.log(' Starting live test....'); + const results = gnomeAppUsage(); + if (results instanceof LinuxError) { + throw results; + return; + } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting GNOME Application Usage test....'); + testGnomeAppUsage(); + + console.log(' GNOME Application Usage test passed! 🄳'); + console.log('All GNOME Application Usage tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +main(); diff --git a/tests/macos/apps/main.ts b/tests/macos/apps/main.ts index 01fed8a6..99a0f98b 100644 --- a/tests/macos/apps/main.ts +++ b/tests/macos/apps/main.ts @@ -1,10 +1,13 @@ import { listApps } from "../../../mod"; function main() { + console.log('Running macOS Apps tests....'); + console.log(' Starting live test....'); const results = listApps(); if (results.length === 0) { throw "no apps!?"; } + console.log(' Live test passed! 🄳\n'); } main(); diff --git a/tests/macos/bom/main.ts b/tests/macos/bom/main.ts index a2f4dfb1..413bdebe 100644 --- a/tests/macos/bom/main.ts +++ b/tests/macos/bom/main.ts @@ -2,23 +2,33 @@ import { parseBom } from "../../../mod"; import { FileError } from "../../../src/filesystem/errors"; import { glob } from "../../../src/filesystem/files"; import { MacosError } from "../../../src/macos/errors"; +import { testParseBom } from "../../test"; function main() { + console.log('Running macOS Bom tests....'); + console.log(' Starting live test....'); const path = "/var/db/receipts/*.bom"; const paths = glob(path); if (paths instanceof FileError) { - throw paths; + throw console.log(paths); } for (const entry of paths) { const data = parseBom(entry.full_path); if (data instanceof MacosError) { - throw data; + throw console.log(data); } if (data.package_name.length === 0) { throw "no name?!"; } } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting Bom test....'); + testParseBom(); + console.log(' Bom test passed! 🄳'); + + console.log('All Bom tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); } main(); diff --git a/tests/macos/compile_tests.py b/tests/macos/compile_tests.py new file mode 100644 index 00000000..c2414c73 --- /dev/null +++ b/tests/macos/compile_tests.py @@ -0,0 +1,150 @@ +# AI took my simple 15 line bash script and turned it into a nice ~180 line Python script XD + +from pathlib import Path +import subprocess +import sys +import os +import time +from datetime import datetime +from contextlib import contextmanager +from statistics import mean, median, quantiles + +from colorama import init, Fore, Style + +# Initialize colorama (needed for Windows) +init(autoreset=True) + +@contextmanager +def pushd(new_dir: Path): + """Temporarily change working directory like `cd` in Bash.""" + prev_dir = Path.cwd() + try: + os.chdir(new_dir) + yield + finally: + os.chdir(prev_dir) + +def run_tests(): + base_dir = Path.cwd() + total_start = time.perf_counter() + + total_tests = 0 + passed_tests = 0 + durations = [] # (project_name, elapsed_time) + + for entry in base_dir.iterdir(): + if not entry.is_dir(): + continue + + total_tests += 1 + with pushd(entry): + start_time = time.perf_counter() + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + print(f"\n{Fore.CYAN}[{timestamp}] šŸ”„ Running test for {entry.name} šŸ”„{Style.RESET_ALL}") + + # Run esbuild + try: + subprocess.run( + ["esbuild", "--log-level=silent", "--bundle", "--outfile=main.js", "main.ts"], + check=True + ) + except subprocess.CalledProcessError: + print(f"{Fore.RED}āŒ Failed to build {entry.name}{Style.RESET_ALL}") + break + + # Run script_tester + try: + subprocess.run( + [str(base_dir / "script_tester"), "main.js"], + check=True + ) + except subprocess.CalledProcessError: + print(f"{Fore.RED}āŒ Failed test for {entry.name}{Style.RESET_ALL}") + break + else: + passed_tests += 1 + + # Duration reporting + elapsed = time.perf_counter() - start_time + durations.append((entry.name, elapsed)) + print(f"{Fore.GREEN}āœ… Completed {entry.name} in {elapsed:.2f} seconds{Style.RESET_ALL}") + + # Totals + total_elapsed = time.perf_counter() - total_start + print(f"\n{Fore.MAGENTA}šŸ“Š Test Summary{Style.RESET_ALL}") + print(f" Total tests: {total_tests}") + print(f" {Fore.GREEN}Passed: {passed_tests}{Style.RESET_ALL}") + print(f" {Fore.RED}Failed: {total_tests - passed_tests}{Style.RESET_ALL}") + print(f" Total time: {total_elapsed:.2f} seconds") + + # Stats + if durations: + slowest = max(durations, key=lambda x: x[1]) + fastest = min(durations, key=lambda x: x[1]) + times = [d[1] for d in durations] + + avg_time = mean(times) + q25, q50, q75 = quantiles(times, n=4) # quartiles + + print(f" {Fore.YELLOW}🐢 Slowest project: {slowest[0]} " + f"({slowest[1]:.2f} seconds){Style.RESET_ALL}") + print(f" {Fore.CYAN}⚔ Fastest project: {fastest[0]} " + f"({fastest[1]:.2f} seconds){Style.RESET_ALL}") + print(f" {Fore.BLUE}šŸ“ˆ Average duration: {avg_time:.2f} seconds{Style.RESET_ALL}") + print(f" {Fore.BLUE}šŸ“Š Median duration: {median(times):.2f} seconds{Style.RESET_ALL}") + + # Pareto 80% cumulative time + sorted_durations = sorted(durations, key=lambda x: x[1], reverse=True) + cumulative = 0.0 + cutoff = 0.8 * sum(times) + pareto_list = [] + for name, t in sorted_durations: + cumulative += t + pareto_list.append((name, t)) + if cumulative >= cutoff: + break + + print(f"\n{Fore.MAGENTA}šŸ“Œ Top 80% time contributors (Pareto){Style.RESET_ALL}") + for name, t in pareto_list: + print(f" {Fore.YELLOW}{name:<20}{t:.2f} sec{Style.RESET_ALL}") + + # Histogram chart with color coding + percentile + cumulative % + print(f"\n{Fore.MAGENTA}šŸ“Š Runtime Histogram (with percentiles & cumulative){Style.RESET_ALL}") + max_time = slowest[1] + scale = 40 / max_time if max_time > 0 else 1 + total_time = sum(times) + cumulative = 0.0 + + for name, t in sorted_durations: + cumulative += t + bar = "ā–ˆ" * int(t * scale) + # Color by relative speed + if t <= 0.75 * avg_time: + color = Fore.GREEN + elif t <= 1.25 * avg_time: + color = Fore.YELLOW + else: + color = Fore.RED + + # Percentile marker + if t <= q25: + marker = " (≤25th %ile)" + elif t <= q50: + marker = " (≤50th %ile)" + elif t <= q75: + marker = " (≤75th %ile)" + else: + marker = " (>75th %ile)" + + # Cumulative percentage + cum_pct = (cumulative / total_time) * 100 + print(f" {name:<20} {color}{bar}{Style.RESET_ALL} {t:.2f}s{marker} " + f"→ {cum_pct:5.1f}% total") + + # Exit code mirrors success/failure + if passed_tests < total_tests: + sys.exit(1) + +if __name__ == "__main__": + run_tests() \ No newline at end of file diff --git a/tests/macos/compile_tests.sh b/tests/macos/compile_tests.sh deleted file mode 100644 index 8d1d99ff..00000000 --- a/tests/macos/compile_tests.sh +++ /dev/null @@ -1,14 +0,0 @@ -# Compile all test TypeScript files -for entry in */ -do -cd $entry -echo "Running test for $entry" -esbuild --log-level=silent --bundle --outfile=main.js main.ts -if ../script_tester main.js -then - cd .. -else - echo "Failed test for $entry" - exit 1 -fi -done \ No newline at end of file diff --git a/tests/macos/docktile/main.ts b/tests/macos/docktile/main.ts new file mode 100644 index 00000000..5c605559 --- /dev/null +++ b/tests/macos/docktile/main.ts @@ -0,0 +1,13 @@ +import { dockTiles } from "../../../mod"; + +async function main() { + console.log('Running macOS Docktile Apps tests....'); + console.log(' Starting live test....'); + const results = await dockTiles(); + if(results.length < 2) { + throw "Should have found Apple Apps with Docktile persistence?"; + } + console.log(' Live test passed! 🄳\n'); +} + +main(); diff --git a/tests/macos/gatekeeper/main.ts b/tests/macos/gatekeeper/main.ts index d8334495..822408bb 100644 --- a/tests/macos/gatekeeper/main.ts +++ b/tests/macos/gatekeeper/main.ts @@ -4,7 +4,7 @@ import { MacosError } from "../../../src/macos/errors"; function main() { const results = gatekeeperEntries(); if (results instanceof MacosError) { - throw results; + throw console.log(results); } if (results.length === 0) { diff --git a/tests/macos/onedrive/main.ts b/tests/macos/onedrive/main.ts index 08104bf6..73875a74 100644 --- a/tests/macos/onedrive/main.ts +++ b/tests/macos/onedrive/main.ts @@ -1,12 +1,24 @@ -import { ApplicationError } from "../../../src/applications/errors"; -import { onedriveDetails } from "../../../src/applications/onedrive/parser"; -import { PlatformType } from "../../../src/system/systeminfo"; +import { OneDrive, PlatformType } from "../../../mod"; +import { testOneDrive } from "../../test"; function main() { - const results = onedriveDetails(PlatformType.Darwin); - if (results instanceof ApplicationError) { - throw results; + console.log('Running macOS OneDrive tests....'); + console.log(' Starting live test....'); + const client = new OneDrive(PlatformType.Darwin); + if (client.oneDriveProfiles().length === 0) { + console.info('No OneDrive application!'); } + const keys = client.oneDriveKeys(); + if(client.oneDriveProfiles().length !== 0 && keys.length === 0) { + throw console.error(`No keys found?`); + } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting OneDrive Mock tests....'); + testOneDrive(); + console.log(' All OneDrive Mock tests passed! 🄳\n'); + + console.log('All macOS OneDrive tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); } main(); diff --git a/tests/test.ts b/tests/test.ts index dcc6b66e..b5414dd7 100644 --- a/tests/test.ts +++ b/tests/test.ts @@ -6,6 +6,14 @@ export { testLevelWal } from "../src/applications/leveldb/wal"; export { testRecentFiles } from "../src/applications/libreoffice"; export { testReadTrace } from "../src/applications/anydesk/trace"; export { testReadConfig } from "../src/applications/anydesk/conf"; +export { testReadOdlFiles } from "../src/applications/onedrive/odl"; +export { testOneDrive } from "../src/applications/onedrive/onedrive"; +export { testExtractSyncEngine } from "../src/applications/onedrive/sqlite"; +export { testChromiumJsonFiles } from "../src/applications/chromium/json"; +export { testChromiumPreferences } from "../src/applications/chromium/preferences"; +export { testChromiumLocalStorage } from "../src/applications/chromium/level"; +export { testChromiumSessions } from "../src/applications/chromium/sessions"; +export { testChromiumSqlite } from "../src/applications/chromium/sqlite"; /** * Linux exported test functions @@ -14,6 +22,9 @@ export { testGetGnomeExtensions } from "../src/linux/gnome/extensions"; export { testGeditRecentFiles } from "../src/linux/gnome/gedit"; export { testRpmInfo } from "../src/linux/rpm"; export { testFirmwareHistory } from "../src/linux/firmware"; +export { testGnomeAppUsage } from "../src/linux/gnome/usage"; +export { testParseGvfs } from "../src/linux/gnome/gvfs"; +export { testQueryLogons } from "../src/linux/sqlite/wtmpdb"; /** * Windows exported test functions @@ -21,8 +32,18 @@ export { testFirmwareHistory } from "../src/linux/firmware"; export { testPowerShellHistory } from "../src/windows/powershell"; export { testLogonsWindows } from "../src/windows/eventlogs/logons"; export { testParseMru } from "../src/windows/registry/recently_used"; +export { testWindowsWifiNetworks } from "../src/windows/registry/wifi"; +export { testGetRunKeys } from "../src/windows/registry/run"; +export { testServiceInstalls } from "../src/windows/eventlogs/services"; /** * macOS exported test functions */ export { testHomebrew } from "../src/macos/homebrew"; +export { testParseBom } from "../src/macos/bom"; + +/** + * HTTP exported test functions + */ +export { testCircluHashlookup } from "../src/http/circlu"; +export { testCheckEolStatus } from "../src/http/eol"; \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/LICENSE b/tests/test_data/DFIRArtifactMuseum/LICENSE new file mode 100644 index 00000000..60543524 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 DFIR Artifact Museum + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171B2-5A2C.pma b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171B2-5A2C.pma new file mode 100644 index 00000000..a4389baa Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171B2-5A2C.pma differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171BD-5BFC.pma b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171BD-5BFC.pma new file mode 100644 index 00000000..8d84bf17 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171BD-5BFC.pma differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171C7-3BE8.pma b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171C7-3BE8.pma new file mode 100644 index 00000000..25733832 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/BrowserMetrics/BrowserMetrics-66F171C7-3BE8.pma differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Crashpad/metadata b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Crashpad/metadata new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Crashpad/settings.dat b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Crashpad/settings.dat new file mode 100644 index 00000000..0ccc4c5c Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Crashpad/settings.dat differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Crashpad/throttle_store.dat b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Crashpad/throttle_store.dat new file mode 100644 index 00000000..9639e1b0 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Crashpad/throttle_store.dat @@ -0,0 +1 @@ +level=none expiry=0 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/ClientCertificates/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/ClientCertificates/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/ClientCertificates/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/ClientCertificates/LOG new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/ClientCertificates/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/ClientCertificates/LOG.old new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/js/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/js/index new file mode 100644 index 00000000..79bd403a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/js/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/js/index-dir/the-real-index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/js/index-dir/the-real-index new file mode 100644 index 00000000..71d4a3ce Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/js/index-dir/the-real-index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/wasm/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/wasm/index new file mode 100644 index 00000000..79bd403a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/wasm/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/wasm/index-dir/the-real-index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/wasm/index-dir/the-real-index new file mode 100644 index 00000000..71d4a3ce Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Code Cache/wasm/index-dir/the-real-index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_0 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_0 new file mode 100644 index 00000000..d76fb77e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_0 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_1 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_1 new file mode 100644 index 00000000..dcaafa97 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_1 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_2 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_2 new file mode 100644 index 00000000..c7e2eb9a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_2 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_3 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_3 new file mode 100644 index 00000000..5eec9735 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/data_3 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/index new file mode 100644 index 00000000..4268fdf1 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnGraphiteCache/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_0 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_0 new file mode 100644 index 00000000..d76fb77e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_0 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_1 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_1 new file mode 100644 index 00000000..dcaafa97 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_1 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_2 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_2 new file mode 100644 index 00000000..c7e2eb9a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_2 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_3 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_3 new file mode 100644 index 00000000..5eec9735 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/data_3 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/index new file mode 100644 index 00000000..3c87099c Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/DawnWebGPUCache/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/EdgeHubAppUsage/EdgeHubAppUsageSQLite.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/EdgeHubAppUsage/EdgeHubAppUsageSQLite.db new file mode 100644 index 00000000..9866d8a0 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/EdgeHubAppUsage/EdgeHubAppUsageSQLite.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/EdgeHubAppUsage/EdgeHubAppUsageSQLite.db-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/EdgeHubAppUsage/EdgeHubAppUsageSQLite.db-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/000003.log new file mode 100644 index 00000000..4acb4c8d Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/000003.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/LOG new file mode 100644 index 00000000..ecbd7516 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/LOG @@ -0,0 +1,2 @@ +2024/09/23-08:48:34.506 4d80 Creating DB C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Extension Rules since it was missing. +2024/09/23-08:48:34.547 4d80 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Extension Rules/MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Rules/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/000003.log new file mode 100644 index 00000000..4acb4c8d Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/000003.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/LOG new file mode 100644 index 00000000..cb908f33 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/LOG @@ -0,0 +1,2 @@ +2024/09/23-08:48:34.553 4d80 Creating DB C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Extension Scripts since it was missing. +2024/09/23-08:48:34.565 4d80 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Extension Scripts/MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension Scripts/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/000003.log new file mode 100644 index 00000000..b248f536 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/000003.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/LOG new file mode 100644 index 00000000..7bd4d1b4 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/LOG @@ -0,0 +1,3 @@ +2024/09/23-08:48:56.178 3138 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Extension State/MANIFEST-000001 +2024/09/23-08:48:56.180 3138 Recovering log #3 +2024/09/23-08:48:56.181 3138 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Extension State/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/LOG.old new file mode 100644 index 00000000..99c0340d --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/LOG.old @@ -0,0 +1,3 @@ +2024/09/23-08:48:47.192 4ea8 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Extension State/MANIFEST-000001 +2024/09/23-08:48:47.196 4ea8 Recovering log #3 +2024/09/23-08:48:47.198 4ea8 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Extension State/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Extension State/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Favicons b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Favicons new file mode 100644 index 00000000..28104a21 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Favicons differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Favicons-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Favicons-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_0 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_0 new file mode 100644 index 00000000..d76fb77e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_0 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_1 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_1 new file mode 100644 index 00000000..dcaafa97 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_1 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_2 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_2 new file mode 100644 index 00000000..c7e2eb9a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_2 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_3 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_3 new file mode 100644 index 00000000..5eec9735 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/data_3 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/index new file mode 100644 index 00000000..8c06a1a0 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/GPUCache/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/History b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/History new file mode 100644 index 00000000..e28aa749 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/History differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/History-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/History-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/LOG new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/LOG.old new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/000003.log new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/LOG new file mode 100644 index 00000000..03cd52d5 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/LOG @@ -0,0 +1,3 @@ +2024/09/23-08:48:56.412 4e70 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001 +2024/09/23-08:48:56.457 4e70 Recovering log #3 +2024/09/23-08:48:56.466 4e70 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Local Storage\leveldb/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/LOG.old new file mode 100644 index 00000000..17575919 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/LOG.old @@ -0,0 +1,3 @@ +2024/09/23-08:48:47.801 2700 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001 +2024/09/23-08:48:48.083 2700 Recovering log #3 +2024/09/23-08:48:48.093 2700 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Local Storage\leveldb/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Local Storage/leveldb/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Login Data b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Login Data new file mode 100644 index 00000000..99774189 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Login Data differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Login Data-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Login Data-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Cookies b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Cookies new file mode 100644 index 00000000..42aa0bd1 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Cookies differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Cookies-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Cookies-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Network Persistent State b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Network Persistent State new file mode 100644 index 00000000..2590bec5 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Network Persistent State @@ -0,0 +1 @@ +{"net":{"http_server_properties":{"servers":[],"version":5},"network_qualities":{"CAESABiAgICA+P////8B":"4G"}}} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/NetworkDataMigrated b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/NetworkDataMigrated new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/SCT Auditing Pending Reports b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/SCT Auditing Pending Reports new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/SCT Auditing Pending Reports @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Sdch Dictionaries b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Sdch Dictionaries new file mode 100644 index 00000000..8bca1008 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Sdch Dictionaries @@ -0,0 +1 @@ +{"SDCH":{"dictionaries":{},"version":2}} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Trust Tokens b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Trust Tokens new file mode 100644 index 00000000..799499fa Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Trust Tokens differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Trust Tokens-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Network/Trust Tokens-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/PersistentOriginTrials/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/PersistentOriginTrials/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/PersistentOriginTrials/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/PersistentOriginTrials/LOG new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/PersistentOriginTrials/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/PersistentOriginTrials/LOG.old new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Preferences b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Preferences new file mode 100644 index 00000000..27cf64e0 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Preferences @@ -0,0 +1 @@ +{"aadc_info":{"age_group":0},"account_tracker_service_last_update":"13371572914858923","alternate_error_pages":{"backup":true},"autocomplete":{"retention_policy_last_version":128},"autofill":{"last_version_deduped":128},"browser":{"available_dark_theme_options":"All","has_seen_welcome_page":false,"recent_theme_color_list":[4293914607.0,4293914607.0,4293914607.0,4293914607.0,4293914607.0]},"browser_content_container_height":252,"browser_content_container_width":450,"browser_content_container_x":0,"browser_content_container_y":0,"commerce_daily_metrics_last_update_time":"13371572914547032","credentials_enable_service":false,"domain_diversity":{"last_reporting_timestamp":"13371572914856140"},"edge":{"msa_sso_info":{"allow_for_non_msa_profile":true},"profile_sso_info":{"is_msa_first_profile":true,"msa_sso_algo_state":1},"services":{"signin_scoped_device_id":"1590f645-133b-4085-b003-a869e0b13212"}},"edge_rewards":{"cache_data":"CAA=","coachmark_promotions":{},"hva_promotions":[],"refresh_status_muted_until":"13372177714467233"},"edge_ux_config":{"assignmentcontext":"","dataversion":"0","experimentvariables":{},"flights":{}},"enterprise_profile_guid":"4cde41bf-0491-4e23-99aa-eb5383655a23","extensions":{"alerts":{"initialized":true},"chrome_url_overrides":{},"last_chrome_version":"128.0.2739.79","pdf_upsell_triggered":false,"pinned_extension_migration":true,"pinned_extensions":[]},"fsd":{"retention_policy_last_version":128},"intl":{"selected_languages":"en-US,en"},"muid":{"last_sync":"13371572914546603"},"optimization_guide":{"previously_registered_optimization_types":{"ABOUT_THIS_SITE":true,"HISTORY_CLUSTERS":true,"PAGE_ENTITIES":true,"PRICE_INSIGHTS":true,"PRICE_TRACKING":true,"SALIENT_IMAGE":true,"SHOPPING_DISCOUNTS":true,"SHOPPING_PAGE_TYPES":true,"V8_COMPILE_HINTS":true},"store_file_paths_to_delete":{}},"password_manager":{"autofillable_credentials_profile_store_login_database":false},"privacy_sandbox":{"first_party_sets_data_access_allowed_initialized":true},"profile":{"avatar_index":20,"content_settings":{"did_migrate_adaptive_notification_quieting_to_cpss":true,"disable_quiet_permission_ui_time":{"notifications":"13371572914504882"},"enable_cpss":{"notifications":true},"enable_quiet_permission_ui":{"notifications":false},"enable_quiet_permission_ui_enabling_method":{"notifications":1},"exceptions":{"3pcd_heuristics_grants":{},"3pcd_support":{},"abusive_notification_permissions":{},"access_to_get_all_screens_media_in_session":{},"accessibility_events":{},"anti_abuse":{},"app_banner":{},"ar":{},"auto_picture_in_picture":{},"auto_select_certificate":{},"automatic_downloads":{},"automatic_fullscreen":{},"autoplay":{},"background_sync":{},"bluetooth_chooser_data":{},"bluetooth_guard":{},"bluetooth_scanning":{},"camera_pan_tilt_zoom":{},"captured_surface_control":{},"clear_browsing_data_cookies_exceptions":{},"client_hints":{},"clipboard":{},"cookie_controls_metadata":{},"cookies":{},"direct_sockets":{},"display_media_system_audio":{},"durable_storage":{},"edge_ad_targeting":{},"edge_ad_targeting_data":{},"edge_sdsm":{},"edge_split_screen":{},"edge_u2f_api_request":{},"edge_user_agent_token":{},"fedcm_idp_registration":{},"fedcm_idp_signin":{},"fedcm_share":{},"file_system_access_chooser_data":{},"file_system_access_extended_permission":{},"file_system_access_restore_permission":{},"file_system_last_picked_directory":{},"file_system_read_guard":{},"file_system_write_guard":{},"formfill_metadata":{},"geolocation":{},"hid_chooser_data":{},"hid_guard":{},"http_allowed":{},"https_enforced":{},"idle_detection":{},"images":{},"important_site_info":{},"insecure_private_network":{},"intent_picker_auto_display":{},"javascript":{},"javascript_jit":{},"javascript_optimizer":{},"keyboard_lock":{},"legacy_cookie_access":{},"local_fonts":{},"media_engagement":{},"media_stream_camera":{},"media_stream_mic":{},"midi_sysex":{},"mixed_script":{},"nfc_devices":{},"notification_interactions":{},"notification_permission_review":{},"notifications":{},"password_protection":{},"payment_handler":{},"permission_autoblocking_data":{},"permission_autorevocation_data":{},"pointer_lock":{},"popups":{},"private_network_chooser_data":{},"private_network_guard":{},"protected_media_identifier":{},"protocol_handler":{},"reduced_accept_language":{},"safe_browsing_url_check_data":{},"secure_network":{},"secure_network_sites":{},"sensors":{},"serial_chooser_data":{},"serial_guard":{},"site_engagement":{},"sleeping_tabs":{},"sound":{},"speaker_selection":{},"ssl_cert_decisions":{},"storage_access":{},"storage_access_header_origin_trial":{},"subresource_filter":{},"subresource_filter_data":{},"third_party_storage_partitioning":{},"token_binding":{},"top_level_3pcd_origin_trial":{},"top_level_3pcd_support":{},"top_level_storage_access":{},"trackers":{},"trackers_data":{},"tracking_org_exceptions":{},"tracking_org_relationships":{},"tracking_protection":{},"unused_site_permissions":{},"usb_chooser_data":{},"usb_guard":{},"vr":{},"webid_api":{},"webid_auto_reauthn":{},"window_placement":{}},"pref_version":1},"created_by_version":"128.0.2739.79","creation_time":"13371572914398051","edge_password_is_using_new_login_db_path":false,"edge_password_login_db_path_flip_flop_count":0,"edge_profile_id":"3ef67a14-9678-49cf-adc1-82e093df2c50","has_seen_signin_fre":false,"is_relative_to_aad":false,"managed_user_id":"","name":"Profile 1","network_pbs":{},"password_account_storage_settings":{},"signin_fre_seen_time":"13371572914445403"},"reset_prepopulated_engines":false,"safety_hub":{"unused_site_permissions_revocation":{"migration_completed":true}},"sessions":{"event_log":[{"crashed":false,"time":"13371572914492021","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13371572915344094","type":2,"window_count":0},{"crashed":false,"time":"13371572926645018","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13371572932566398","type":2,"window_count":0},{"crashed":false,"time":"13371572935850823","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13371572939132104","type":2,"window_count":0}],"session_data_status":3},"signin":{"allowed":true},"spellcheck":{"dictionaries":["en-US"]},"tracking_protection":{"tracking_protection_3pcd_enabled":false},"translate_site_blacklist":[],"translate_site_blocklist_with_time":{},"user_experience_metrics":{"personalization_data_consent_enabled_last_known_value":false}} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/README b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/README new file mode 100644 index 00000000..4a344027 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/README @@ -0,0 +1 @@ +Microsoft Edge settings and storage represent user-selected preferences and information and MUST not be extracted, overwritten or modified except through Microsoft Edge defined APIs. \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Safe Browsing Network/NetworkDataMigrated b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Safe Browsing Network/NetworkDataMigrated new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Safe Browsing Network/Safe Browsing Cookies b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Safe Browsing Network/Safe Browsing Cookies new file mode 100644 index 00000000..42aa0bd1 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Safe Browsing Network/Safe Browsing Cookies differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Safe Browsing Network/Safe Browsing Cookies-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Safe Browsing Network/Safe Browsing Cookies-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Secure Preferences b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Secure Preferences new file mode 100644 index 00000000..a62d9e64 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Secure Preferences @@ -0,0 +1 @@ +{"extensions":{"settings":{"dgiklkfkllikcanfonkcabmbdfmgleag":{"active_permissions":{"api":[],"explicit_host":[],"manifest_permissions":[],"scriptable_host":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":[],"first_install_time":"13371572914502086","from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"last_update_time":"13371572914502086","location":5,"manifest":{"content_capabilities":{"include_globs":["https://*excel.officeapps.live.com/*","https://*onenote.officeapps.live.com/*","https://*powerpoint.officeapps.live.com/*","https://*word-edit.officeapps.live.com/*","https://*excel.officeapps.live.com.mcas.ms/*","https://*onenote.officeapps.live.com.mcas.ms/*","https://*word-edit.officeapps.live.com.mcas.ms/*","https://*excel.partner.officewebapps.cn/*","https://*onenote.partner.officewebapps.cn/*","https://*powerpoint.partner.officewebapps.cn/*","https://*word-edit.partner.officewebapps.cn/*","https://*excel.gov.online.office365.us/*","https://*onenote.gov.online.office365.us/*","https://*powerpoint.gov.online.office365.us/*","https://*word-edit.gov.online.office365.us/*","https://*excel.dod.online.office365.us/*","https://*onenote.dod.online.office365.us/*","https://*powerpoint.dod.online.office365.us/*","https://*word-edit.dod.online.office365.us/*","https://*visio.partner.officewebapps.cn/*","https://*visio.gov.online.office365.us/*","https://*visio.dod.online.office365.us/*"],"matches":["https://*.officeapps.live.com/*","https://*.officeapps.live.com.mcas.ms/*","https://*.partner.officewebapps.cn/*","https://*.gov.online.office365.us/*","https://*.dod.online.office365.us/*","https://*.app.whiteboard.microsoft.com/*","https://*.whiteboard.office.com/*","https://*.app.int.whiteboard.microsoft.com/*","https://*.whiteboard.office365.us/*","https://*.dev.whiteboard.microsoft.com/*"],"permissions":["clipboardRead","clipboardWrite"]},"default_locale":"en","description":"This extension grants Microsoft web sites permission to read and write from the clipboard.","key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCz4t/X7GeuP6GBpjmxndrjtzF//4CWeHlC68rkoV7hP3h5Ka6eX7ZMNlYJkSjmB5iRmPHO5kR1y7rGY8JXnRPDQh/CQNLVA7OsKeV6w+UO+vx8KGI+TrTAhzH8YGcMIsxsUjxtC4cBmprja+xDr0zVp2EMgqHu+GBKgwSRHTkDuwIDAQAB","manifest_version":2,"minimum_chrome_version":"77","name":"Microsoft Clipboard Extension","version":"1.0"},"path":"C:\\Program Files (x86)\\Microsoft\\EdgeWebView\\Application\\128.0.2739.79\\resources\\edge_clipboard","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"mhjfbmdgcfjbbpaeojofohoefgiehjai":{"active_permissions":{"api":["contentSettings","fileSystem","fileSystem.write","metricsPrivate","tabs","resourcesPrivate","pdfViewerPrivate","fileSystem.readFullPath","errorReporting","edgeLearningToolsPrivate","fileSystem.getCurrentEntry","edgePdfPrivate","edgeCertVerifierPrivate"],"explicit_host":["edge://resources/*","edge://webui-test/*"],"manifest_permissions":[],"scriptable_host":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":[],"first_install_time":"13371572914500183","from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"last_update_time":"13371572914500183","location":5,"manifest":{"content_security_policy":"script-src 'self' 'wasm-eval' blob: filesystem: chrome://resources chrome://webui-test; object-src * blob: externalfile: file: filesystem: data:","description":"","incognito":"split","key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDN6hM0rsDYGbzQPQfOygqlRtQgKUXMfnSjhIBL7LnReAVBEd7ZmKtyN2qmSasMl4HZpMhVe2rPWVVwBDl6iyNE/Kok6E6v6V3vCLGsOpQAuuNVye/3QxzIldzG/jQAdWZiyXReRVapOhZtLjGfywCvlWq7Sl/e3sbc0vWybSDI2QIDAQAB","manifest_version":2,"mime_types":["application/pdf"],"mime_types_handler":"edge_pdf/index.html","name":"Microsoft Edge PDF Viewer","offline_enabled":true,"permissions":["errorReporting","chrome://resources/","chrome://webui-test/","contentSettings","metricsPrivate","edgeCertVerifierPrivate","edgeLearningToolsPrivate","edgePdfPrivate","pdfViewerPrivate","resourcesPrivate","tabs",{"fileSystem":["write","readFullPath","getCurrentEntry"]}],"version":"1"},"path":"C:\\Program Files (x86)\\Microsoft\\EdgeWebView\\Application\\128.0.2739.79\\resources\\edge_pdf","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false}}},"protection":{"macs":{"browser":{"show_home_button":"9CC7616CC2B8804316F6755B229F4A39331799301DE898921940571002531800"},"default_search_provider_data":{"template_url_data":"6F2A9F08D0253C351716C2DD1D35F818EB61C9B8498F7C0B54A93C84CBC08405"},"edge":{"services":{"account_id":"E63772391DFD3ED615CA051323528CCCE47652A7D79CBCC6CB86CB3ABB5371CF","last_account_id":"EC673DA268991EE5C8D8C5F150ED7A4BC010FEBF3B57752606E3ED103CAB4051","last_username":"91DA50FEF3B4A44CDC8E0D5722CB490F58AB5EBE17305F8381503C74A87D0145"}},"enterprise_signin":{"policy_recovery_token":"3112E86C14D3098823E779DD6B782EFF46EB46EC85D8C27CAB45E87B89A64665"},"extensions":{"settings":{"dgiklkfkllikcanfonkcabmbdfmgleag":"A3E873282FD76EF187014E93C753779CEA3604A4F9FB85EB2327F5AE7635CEFF","mhjfbmdgcfjbbpaeojofohoefgiehjai":"99FF9C21BB20A397A9696BEF334311BE5A129226A5408990C7100AF76B58D588"}},"google":{"services":{"last_signed_in_username":"B21BC70C833625A1677A1F2E850C0F51DC1BC56D04AA7158C07971C42C6C0DDB"}},"homepage":"79455E680E87224E73EE41EB9DC2A6754CF662033FA51F6C784D9D3691B1CEE6","homepage_is_newtabpage":"F3275B9E9F44AE31022BC6F8327677FBF5A86A6B3A0BC0504946454E857F092B","media":{"cdm":{"origin_data":"9DE16996899025A777358FBE962DCC2526BE35BF7BA951500A90C0BB4C931DD2"},"storage_id_salt":"E30A78058D4A93473F33EF88A98C9123974EF5D7C6820B8CCDC6920629E92DA0"},"pinned_tabs":"ACAA98B02FB5184A3ED9C58991C254E5B42B38D42D95BC4C1473575302A9C823","prefs":{"preference_reset_time":"4F437852185A513275950A500C87A9077BBB3BEC660EE6704332377BC910D0E0"},"safebrowsing":{"incidents_sent":"2AD3E93BA95F8F9142E734AAE80D817CD652DFBE2460641FA14508B68386941C"},"search_provider_overrides":"62D7B5CA34D70951DBDBA7DC74D4FB5F645C2FE1208FB3B85148A289E320A6CE","session":{"restore_on_startup":"15F521D17475E533D4BAB44CA00263FC01D9D7C14103A071F2FDB955A9BD1E35","startup_urls":"137BB87F14BB37ABFAC0E0B0C3A8CB12415E03A54435185B11C8769A46CA1179"}},"super_mac":"ECF49BDA43DA9B3F65A1761F206D5FF41B2E7889BF97A09D0346EAABC5D5EBC6"}} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/000003.log new file mode 100644 index 00000000..85c73cbc Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/000003.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/LOG new file mode 100644 index 00000000..249f903a --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/LOG @@ -0,0 +1,3 @@ +2024/09/23-08:48:59.104 4e70 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Session Storage/MANIFEST-000001 +2024/09/23-08:48:59.110 4e70 Recovering log #3 +2024/09/23-08:48:59.163 4e70 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Session Storage/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/LOG.old new file mode 100644 index 00000000..9d86d90d --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/LOG.old @@ -0,0 +1,3 @@ +2024/09/23-08:48:52.504 2700 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Session Storage/MANIFEST-000001 +2024/09/23-08:48:52.507 2700 Recovering log #3 +2024/09/23-08:48:52.549 2700 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Session Storage/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Session Storage/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/cache/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/cache/index new file mode 100644 index 00000000..79bd403a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/cache/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/cache/index-dir/the-real-index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/cache/index-dir/the-real-index new file mode 100644 index 00000000..2d8587ab Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/cache/index-dir/the-real-index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/db new file mode 100644 index 00000000..204b6ea3 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/db-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Shared Dictionary/db-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/SharedStorage b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/SharedStorage new file mode 100644 index 00000000..210e7054 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/SharedStorage differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/000003.log new file mode 100644 index 00000000..46580fb8 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/000003.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/LOG new file mode 100644 index 00000000..a950dc02 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/LOG @@ -0,0 +1,3 @@ +2024/09/23-08:48:55.885 5f88 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Site Characteristics Database/MANIFEST-000001 +2024/09/23-08:48:55.886 5f88 Recovering log #3 +2024/09/23-08:48:55.887 5f88 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Site Characteristics Database/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/LOG.old new file mode 100644 index 00000000..6eaf936f --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/LOG.old @@ -0,0 +1,3 @@ +2024/09/23-08:48:46.628 14f4 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Site Characteristics Database/MANIFEST-000001 +2024/09/23-08:48:46.630 14f4 Recovering log #3 +2024/09/23-08:48:46.631 14f4 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Site Characteristics Database/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Site Characteristics Database/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/000003.log new file mode 100644 index 00000000..2b778f4b Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/000003.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/LOG new file mode 100644 index 00000000..a487b16d --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/LOG @@ -0,0 +1,3 @@ +2024/09/23-08:48:55.841 2b04 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Sync Data\LevelDB/MANIFEST-000001 +2024/09/23-08:48:55.844 2b04 Recovering log #3 +2024/09/23-08:48:55.845 2b04 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Sync Data\LevelDB/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/LOG.old new file mode 100644 index 00000000..2b9f65e4 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/LOG.old @@ -0,0 +1,3 @@ +2024/09/23-08:48:46.637 5658 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Sync Data\LevelDB/MANIFEST-000001 +2024/09/23-08:48:46.641 5658 Recovering log #3 +2024/09/23-08:48:46.645 5658 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\Sync Data\LevelDB/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Sync Data/LevelDB/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Visited Links b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Visited Links new file mode 100644 index 00000000..cf2655cf Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Visited Links differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Web Data b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Web Data new file mode 100644 index 00000000..c082298c Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Web Data differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Web Data-journal b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/Web Data-journal new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/commerce_subscription_db/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/commerce_subscription_db/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/commerce_subscription_db/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/commerce_subscription_db/LOG new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/commerce_subscription_db/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/commerce_subscription_db/LOG.old new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/discounts_db/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/discounts_db/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/discounts_db/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/discounts_db/LOG new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/discounts_db/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/discounts_db/LOG.old new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/parcel_tracking_db/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/parcel_tracking_db/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/parcel_tracking_db/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/parcel_tracking_db/LOG new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/parcel_tracking_db/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/parcel_tracking_db/LOG.old new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/000003.log new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/LOG new file mode 100644 index 00000000..cabdcebd --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/LOG @@ -0,0 +1,3 @@ +2024/09/23-08:48:55.934 1914 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\shared_proto_db/MANIFEST-000001 +2024/09/23-08:48:55.935 1914 Recovering log #3 +2024/09/23-08:48:55.936 1914 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\shared_proto_db/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/LOG.old new file mode 100644 index 00000000..41718a0e --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/LOG.old @@ -0,0 +1,3 @@ +2024/09/23-08:48:46.763 5658 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\shared_proto_db/MANIFEST-000001 +2024/09/23-08:48:46.764 5658 Recovering log #3 +2024/09/23-08:48:46.765 5658 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\shared_proto_db/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/000003.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/000003.log new file mode 100644 index 00000000..13719d7e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/000003.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/CURRENT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/LOCK b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/LOG b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/LOG new file mode 100644 index 00000000..6327e46f --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/LOG @@ -0,0 +1,3 @@ +2024/09/23-08:48:55.921 1914 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\shared_proto_db\metadata/MANIFEST-000001 +2024/09/23-08:48:55.922 1914 Recovering log #3 +2024/09/23-08:48:55.923 1914 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\shared_proto_db\metadata/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/LOG.old b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/LOG.old new file mode 100644 index 00000000..1839167c --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/LOG.old @@ -0,0 +1,3 @@ +2024/09/23-08:48:46.756 5658 Reusing MANIFEST C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\shared_proto_db\metadata/MANIFEST-000001 +2024/09/23-08:48:46.757 5658 Recovering log #3 +2024/09/23-08:48:46.758 5658 Reusing old log C:\Users\Beercow\AppData\Local\Microsoft\OneDrive\EBWebView\Default\shared_proto_db\metadata/000003.log diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/MANIFEST-000001 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/MANIFEST-000001 new file mode 100644 index 00000000..18e5cab7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Default/shared_proto_db/metadata/MANIFEST-000001 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_0 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_0 new file mode 100644 index 00000000..d76fb77e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_0 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_1 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_1 new file mode 100644 index 00000000..dcaafa97 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_1 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_2 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_2 new file mode 100644 index 00000000..c7e2eb9a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_2 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_3 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_3 new file mode 100644 index 00000000..5eec9735 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/data_3 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/index new file mode 100644 index 00000000..5e253444 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GrShaderCache/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_0 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_0 new file mode 100644 index 00000000..d76fb77e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_0 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_1 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_1 new file mode 100644 index 00000000..dcaafa97 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_1 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_2 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_2 new file mode 100644 index 00000000..c7e2eb9a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_2 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_3 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_3 new file mode 100644 index 00000000..5eec9735 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/data_3 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/index new file mode 100644 index 00000000..c4b659ec Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/GraphiteDawnCache/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Last Version b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Last Version new file mode 100644 index 00000000..e38a80e7 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Last Version @@ -0,0 +1 @@ +128.0.2739.79 \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Local State b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Local State new file mode 100644 index 00000000..2d07f936 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Local State @@ -0,0 +1 @@ +{"accessibility":{"captions":{"common_models_path":"","soda_binary_path":""}},"autofill":{"ablation_seed":"5o/YPX06yS4="},"background_tracing":{"session_state":{"privacy_filter":true,"state":0}},"breadcrumbs":{"enabled":true,"enabled_time":"13371572914387106"},"edge":{"mitigation_manager":{"renderer_code_integrity_compatible_count":2},"tab_stabs":{"closed_without_unfreeze_never_unfrozen":0,"closed_without_unfreeze_previously_unfrozen":0,"discard_without_unfreeze_never_unfrozen":0,"discard_without_unfreeze_previously_unfrozen":0},"tab_stats":{"frozen_daily":0,"unfrozen_daily":0}},"hardware_acceleration_mode_previous":true,"legacy":{"profile":{"name":{"migrated":true}}},"network_time":{"network_time_mapping":{"local":1.727099338201013e+12,"network":1.727099337e+12,"ticks":1.091328212314e+12,"uncertainty":1190519.0}},"optimization_guide":{"model_store_metadata":{}},"os_crypt":{"audit_enabled":true,"encrypted_key":"RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAABQ4OVZE9JhSZ9uf0R27w8+EAAAAB4AAABNAGkAYwByAG8AcwBvAGYAdAAgAEUAZABnAGUAAAAQZgAAAAEAACAAAADHpgpPa+94Marme+9kAFBjVIoeHn68zhvnM29W2PqthQAAAAAOgAAAAAIAACAAAAB6/TaFZDJQpupOa8BkRJS0ZGsfx4Ex6+rUbQPgu6NR8jAAAAD29KMQPlcMPKqaeD3QzGndoAJQVJnm0+CQ0avgI7MldPEW3eVHWLwj0l65SERzjzhAAAAA+wzUQ1/knAYN2ST5835fwnOX5edaxzZhj/qsfq5Qv0z9N0HORdQeN5hKYQBrApaU84MiT0WR2s2aRxJOMLNRlw=="},"policy":{"last_statistics_update":"13371572914383697"},"profile":{"info_cache":{"Default":{"avatar_icon":"chrome://theme/IDR_PROFILE_AVATAR_20","background_apps":false,"edge_account_cid":"","edge_account_environment":0,"edge_account_first_name":"","edge_account_last_name":"","edge_account_oid":"","edge_account_sovereignty":0,"edge_account_tenant_id":"","edge_account_type":0,"edge_profile_can_be_deleted":true,"edge_test_on_premises":false,"edge_wam_aad_for_app_account_type":0,"force_signin_profile_locked":false,"gaia_given_name":"","gaia_id":"","gaia_name":"","hosted_domain":"","is_consented_primary_account":false,"is_ephemeral":false,"is_using_default_avatar":true,"is_using_default_name":true,"managed_user_id":"","name":"Profile 1","signin.with_credential_provider":false,"user_name":""}},"last_active_profiles":[],"profile_counts_reported":"13371572914150159","profiles_order":["Default"]},"profile_network_context_service":{"http_cache_finch_experiment_groups":"None None None None"},"profiles":{"edge":{"multiple_profiles_with_same_account":false},"edge_sso_info":{"msa_first_profile_key":"Default","msa_sso_algo_state":1},"signin_last_seen_version":"128.0.2739.79","signin_last_updated_time":1727099314.505019},"sentinel_creation_time":"0","session_id_generator_last_value":"600520457","startup_boost":{"last_browser_open_time":"13371572939129418"},"subresource_filter":{"ruleset_version":{"checksum":0,"content":"","format":0}},"tab_stats":{"discards_external":0,"discards_proactive":0,"discards_urgent":0,"last_daily_sample":"13371572914291671","max_tabs_per_window":1,"reloads_external":0,"reloads_urgent":0,"total_tab_count_max":1,"window_count_max":1},"telemetry_client":{"governance":{"last_dma_change_date":"13371572914233590","last_known_cps":0},"host_telclient_path":"QzpcUHJvZ3JhbSBGaWxlcyAoeDg2KVxNaWNyb3NvZnRcRWRnZVdlYlZpZXdcQXBwbGljYXRpb25cMTI4LjAuMjczOS43OVx0ZWxjbGllbnQuZGxs","sample_id":84579875},"uninstall_metrics":{"installation_date2":"1727099314"},"user_experience_metrics":{"client_id2":"{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}C:\\Users\\Beercow0s:24C7BF18-CF76-43F8-AE3B-7C265ED30E66","diagnostics":{"last_data_collection_level_on_launch":1},"limited_entropy_randomization_source":"0EAC3B0EC55DB578C4463ADE21CCF69A","low_entropy_source3":6143,"payload_counter":1,"pseudo_low_entropy_source":5722,"reset_client_id_deterministic":true,"session_id":2,"stability":{"browser_last_live_timestamp":"13371572939218874","exited_cleanly":true,"stats_buildtime":"1726097469","stats_version":"128.0.2739.79-64","system_crash_count":0}},"variations_failed_to_fetch_seed_streak":4,"variations_google_groups":{"Default":[]},"variations_limited_entropy_synthetic_trial_seed_v2":"92","was":{"restarted":false}} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_0 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_0 new file mode 100644 index 00000000..d76fb77e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_0 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_1 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_1 new file mode 100644 index 00000000..dcaafa97 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_1 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_2 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_2 new file mode 100644 index 00000000..c7e2eb9a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_2 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_3 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_3 new file mode 100644 index 00000000..5eec9735 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/data_3 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/index b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/index new file mode 100644 index 00000000..b2c8d01f Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/ShaderCache/index differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/customSettings b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/customSettings new file mode 100644 index 00000000..997f02da --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/customSettings @@ -0,0 +1 @@ +customSettings_F95BA787499AB4FA9EFFF472CE383A14 \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/customSettings_F95BA787499AB4FA9EFFF472CE383A14 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/customSettings_F95BA787499AB4FA9EFFF472CE383A14 new file mode 100644 index 00000000..ae2fefae --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/customSettings_F95BA787499AB4FA9EFFF472CE383A14 @@ -0,0 +1 @@ +{"forceServiceDetermination":false} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/edgeSettings b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/edgeSettings new file mode 100644 index 00000000..a89ca1f4 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/edgeSettings @@ -0,0 +1 @@ +edgeSettings_2.0-0 \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/edgeSettings_2.0-0 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/edgeSettings_2.0-0 new file mode 100644 index 00000000..9c342469 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/edgeSettings_2.0-0 @@ -0,0 +1 @@ +{"models":[],"geoidMaps":{"gw_my":"https://malaysia.smartscreen.microsoft.com/","gw_tw":"https://taiwan.smartscreen.microsoft.com/","gw_at":"https://austria.smartscreen.microsoft.com/","gw_es":"https://spain.smartscreen.microsoft.com/","gw_pl":"https://poland.smartscreen.microsoft.com/","gw_se":"https://sweden.smartscreen.microsoft.com/","gw_kr":"https://southkorea.smartscreen.microsoft.com/","gw_br":"https://brazil.smartscreen.microsoft.com/","au":"https://australia.smartscreen.microsoft.com/","dk":"https://denmark.smartscreen.microsoft.com/","gw_sg":"https://singapore.smartscreen.microsoft.com/","gw_fr":"https://france.smartscreen.microsoft.com/","gw_ca":"https://canada.smartscreen.microsoft.com/","test":"https://eu-9.smartscreen.microsoft.com/","gw_il":"https://israel.smartscreen.microsoft.com/","gw_au":"https://australia.smartscreen.microsoft.com/","gw_ffl4mod":"https://unitedstates4.ss.wd.microsoft.us/","gw_ffl4":"https://unitedstates1.ss.wd.microsoft.us/","gw_eu":"https://europe.smartscreen.microsoft.com/","gw_gr":"https://greece.smartscreen.microsoft.com/","gw_de":"https://germany.smartscreen.microsoft.com/","br":"https://brazil.smartscreen.microsoft.com/","gw_uk":"https://unitedkingdom.smartscreen.microsoft.com/","gw_it":"https://italy.smartscreen.microsoft.com/","gw_us":"https://unitedstates.smartscreen.microsoft.com/","il":"https://israel.smartscreen.microsoft.com/","es":"https://spain.smartscreen.microsoft.com/","ch":"https://switzerland.smartscreen.microsoft.com/","at":"https://austria.smartscreen.microsoft.com/","jp":"https://japan.smartscreen.microsoft.com/","kr":"https://southkorea.smartscreen.microsoft.com/","nz":"https://newzealand.smartscreen.microsoft.com/","gw_cl":"https://chile.smartscreen.microsoft.com/","pl":"https://poland.smartscreen.microsoft.com/","eu":"https://europe.smartscreen.microsoft.com/","de":"https://germany.smartscreen.microsoft.com/","gw_no":"https://norway.smartscreen.microsoft.com/","ffl4mod":"https://unitedstates4.ss.wd.microsoft.us/","gw_jp":"https://japan.smartscreen.microsoft.com/","mx":"https://mexico.smartscreen.microsoft.com/","gw_ffl5":"https://unitedstates2.ss.wd.microsoft.us/","se":"https://sweden.smartscreen.microsoft.com/","gw_ch":"https://switzerland.smartscreen.microsoft.com/","gw_ae":"https://uae.smartscreen.microsoft.com/","my":"https://malaysia.smartscreen.microsoft.com/","gw_nz":"https://newzealand.smartscreen.microsoft.com/","ca":"https://canada.smartscreen.microsoft.com/","fr":"https://france.smartscreen.microsoft.com/","gw_mx":"https://mexico.smartscreen.microsoft.com/","no":"https://norway.smartscreen.microsoft.com/","gr":"https://greece.smartscreen.microsoft.com/","gw_qa":"https://qatar.smartscreen.microsoft.com/","gw_in":"https://india.smartscreen.microsoft.com/","in":"https://india.smartscreen.microsoft.com/","tw":"https://taiwan.smartscreen.microsoft.com/","sg":"https://singapore.smartscreen.microsoft.com/","ffl5":"https://unitedstates2.ss.wd.microsoft.us/","ae":"https://uae.smartscreen.microsoft.com/","gw_dk":"https://denmark.smartscreen.microsoft.com/","gw_za":"https://southafrica.smartscreen.microsoft.com/","uk":"https://unitedkingdom.smartscreen.microsoft.com/","cl":"https://chile.smartscreen.microsoft.com/","us":"https://unitedstates.smartscreen.microsoft.com/","qa":"https://qatar.smartscreen.microsoft.com/","za":"https://southafrica.smartscreen.microsoft.com/","ffl4":"https://unitedstates1.ss.wd.microsoft.us/","it":"https://italy.smartscreen.microsoft.com/"},"sampleBuckets":{"error":1.0,"uriLookup":0.01,"userAction":1.0,"topTrafficHit":0.00007}} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/topTraffic b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/topTraffic new file mode 100644 index 00000000..b19c2f42 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/topTraffic @@ -0,0 +1 @@ +topTraffic_170540185939602997400506234197983529371 \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/topTraffic_170540185939602997400506234197983529371 b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/topTraffic_170540185939602997400506234197983529371 new file mode 100644 index 00000000..9ba0f3ba Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/SmartScreen/RemoteData/topTraffic_170540185939602997400506234197983529371 differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Variations b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Variations new file mode 100644 index 00000000..18056c3f --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/EBWebView/Variations @@ -0,0 +1 @@ +{"user_experience_metrics.stability.exited_cleanly":true,"variations_crash_streak":0} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/Business1/settings/Microsoft.ListSync.Settings.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/Business1/settings/Microsoft.ListSync.Settings.db new file mode 100644 index 00000000..5c7385a5 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/Business1/settings/Microsoft.ListSync.Settings.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/Business1/settings/Microsoft.ListSync.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/Business1/settings/Microsoft.ListSync.db new file mode 100644 index 00000000..630be88b Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/Business1/settings/Microsoft.ListSync.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/settings/NucleusUpdateRingConfig.json b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/settings/NucleusUpdateRingConfig.json new file mode 100644 index 00000000..f5c8f79a --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/ListSync/settings/NucleusUpdateRingConfig.json @@ -0,0 +1 @@ +{"ramps":[{"id":3,"offset":0,"share":100},{"id":4,"offset":0,"share":100},{"id":5,"offset":0,"share":100},{"id":6,"offset":0,"share":100},{"id":7,"offset":0,"share":1},{"id":8,"offset":0,"share":1},{"id":9,"offset":0,"share":1},{"id":10,"offset":0,"share":1},{"id":14,"offset":0,"share":1},{"id":17,"offset":0,"share":100},{"id":18,"offset":0,"share":100},{"id":21,"offset":0,"share":1},{"id":22,"offset":0,"share":1},{"id":24,"offset":0,"share":100},{"id":25,"offset":0,"share":100},{"id":26,"offset":0,"share":100},{"id":27,"offset":0,"share":100},{"id":29,"offset":0,"share":100},{"id":30,"offset":0,"share":100},{"id":31,"offset":31,"share":100},{"id":34,"offset":0,"share":100},{"id":35,"offset":0,"share":100},{"id":36,"offset":0,"share":100},{"id":37,"offset":0,"share":100},{"id":39,"offset":0,"share":100},{"id":41,"offset":0,"share":100},{"id":43,"offset":0,"share":100},{"id":44,"offset":0,"share":100},{"id":45,"offset":0,"share":50},{"id":46,"offset":0,"share":50},{"id":53,"offset":0,"share":1},{"id":54,"offset":0,"share":100},{"id":55,"offset":0,"share":100},{"id":56,"offset":0,"share":100},{"id":58,"offset":0,"share":100},{"id":61,"offset":0,"share":100},{"id":63,"offset":0,"share":100},{"id":66,"offset":0,"share":100},{"id":67,"offset":0,"share":10},{"id":70,"offset":0,"share":100},{"id":71,"offset":0,"share":100},{"id":73,"offset":0,"share":100},{"id":77,"offset":0,"share":100},{"id":78,"offset":0,"share":100},{"id":80,"offset":0,"share":100},{"id":82,"offset":0,"share":100},{"id":83,"offset":0,"share":100},{"id":84,"offset":0,"share":100},{"id":85,"offset":0,"share":100},{"id":86,"offset":0,"share":100},{"id":87,"offset":0,"share":100},{"id":88,"offset":0,"share":100},{"id":92,"offset":0,"share":100},{"id":94,"offset":0,"share":100},{"id":98,"offset":0,"share":100},{"id":100,"offset":0,"share":100},{"id":103,"offset":0,"share":100},{"id":105,"offset":100,"share":100},{"id":107,"offset":23,"share":100},{"id":108,"offset":0,"share":100},{"id":109,"offset":0,"share":100},{"id":112,"offset":0,"share":100},{"id":114,"offset":0,"share":100},{"id":117,"offset":0,"share":100},{"id":118,"offset":0,"share":100},{"id":120,"offset":0,"share":100},{"id":121,"offset":0,"share":100},{"id":122,"offset":50,"share":100},{"id":123,"offset":0,"share":10},{"id":124,"offset":0,"share":100},{"id":125,"offset":0,"share":100},{"id":127,"offset":0,"share":100},{"id":129,"offset":0,"share":100},{"id":131,"offset":0,"share":10},{"id":133,"offset":0,"share":100},{"id":135,"offset":0,"share":100},{"id":136,"offset":0,"share":100},{"id":138,"offset":0,"share":100},{"id":141,"offset":0,"share":100},{"id":144,"offset":0,"share":100},{"id":146,"offset":0,"share":100},{"id":151,"offset":0,"share":100},{"id":153,"offset":0,"share":100},{"id":155,"offset":0,"share":100},{"id":156,"offset":0,"share":100},{"id":157,"offset":0,"share":100},{"id":158,"offset":0,"share":100},{"id":159,"offset":0,"share":100},{"id":165,"offset":0,"share":100},{"id":167,"offset":0,"share":100},{"id":168,"offset":0,"share":100},{"id":172,"offset":0,"share":100},{"id":173,"offset":0,"share":100},{"id":174,"offset":0,"share":100},{"id":175,"offset":0,"share":100},{"id":176,"offset":0,"share":100},{"id":177,"offset":0,"share":100},{"id":178,"offset":0,"share":100},{"id":179,"offset":0,"share":5},{"id":182,"offset":0,"share":100},{"id":183,"offset":0,"share":100},{"id":191,"offset":0,"share":100},{"id":194,"offset":0,"share":100},{"id":195,"offset":0,"share":100},{"id":196,"offset":0,"share":100},{"id":197,"offset":0,"share":100},{"id":198,"offset":0,"share":100},{"id":200,"offset":0,"share":100},{"id":201,"offset":0,"share":100},{"id":204,"offset":0,"share":100},{"id":205,"offset":0,"share":100},{"id":206,"offset":0,"share":100},{"id":207,"offset":0,"share":100},{"id":208,"offset":0,"share":100},{"id":210,"offset":0,"share":100},{"id":211,"offset":0,"share":100},{"id":216,"offset":0,"share":100},{"id":217,"offset":0,"share":100},{"id":218,"offset":0,"share":100},{"id":219,"offset":0,"share":100},{"id":221,"offset":0,"share":100},{"id":224,"offset":0,"share":100},{"id":226,"offset":0,"share":100},{"id":228,"offset":0,"share":100},{"id":231,"offset":0,"share":100},{"id":232,"offset":0,"share":100},{"id":234,"offset":0,"share":100},{"id":239,"offset":0,"share":100},{"id":240,"offset":0,"share":100},{"id":241,"offset":0,"share":100},{"id":242,"offset":0,"share":100},{"id":248,"offset":0,"share":100},{"id":249,"offset":0,"share":100},{"id":251,"offset":0,"share":100},{"id":252,"offset":0,"share":100},{"id":253,"offset":0,"share":100},{"id":254,"offset":0,"share":100},{"id":256,"offset":0,"share":100},{"id":260,"offset":0,"share":100},{"id":262,"offset":0,"share":100},{"id":265,"offset":0,"share":100},{"id":271,"offset":0,"share":100},{"id":274,"offset":0,"share":100},{"id":276,"offset":0,"share":100},{"id":277,"offset":0,"share":100},{"id":281,"offset":0,"share":100},{"id":282,"offset":0,"share":100},{"id":289,"offset":0,"share":100},{"id":290,"offset":0,"share":100},{"id":293,"offset":0,"share":100},{"id":299,"offset":0,"share":100},{"id":300,"offset":0,"share":100},{"id":301,"offset":0,"share":100},{"id":303,"offset":0,"share":100},{"id":304,"offset":0,"share":100},{"id":306,"offset":0,"share":100},{"id":307,"offset":0,"share":100},{"id":315,"offset":0,"share":100},{"id":316,"offset":0,"share":100},{"id":317,"offset":0,"share":100},{"id":318,"offset":0,"share":100},{"id":319,"offset":0,"share":100},{"id":320,"offset":0,"share":100},{"id":322,"offset":0,"share":100},{"id":323,"offset":0,"share":100},{"id":326,"offset":0,"share":100},{"id":327,"offset":0,"share":100},{"id":330,"offset":0,"share":100},{"id":331,"offset":0,"share":100},{"id":332,"offset":0,"share":100},{"id":334,"offset":0,"share":100},{"id":335,"offset":0,"share":100},{"id":336,"offset":0,"share":100},{"id":337,"offset":0,"share":100},{"id":338,"offset":0,"share":100},{"id":339,"offset":0,"share":100},{"id":346,"offset":0,"share":100},{"id":352,"offset":0,"share":100},{"id":358,"offset":0,"share":100},{"id":360,"offset":0,"share":100},{"id":362,"offset":0,"share":100},{"id":364,"offset":0,"share":100},{"id":370,"offset":0,"share":100},{"id":373,"offset":0,"share":100},{"id":374,"offset":17,"share":100},{"id":379,"offset":0,"share":100},{"id":380,"offset":0,"share":100},{"id":381,"offset":0,"share":100},{"id":382,"offset":0,"share":100},{"id":383,"offset":0,"share":100},{"id":384,"offset":0,"share":100},{"id":385,"offset":0,"share":100},{"id":386,"offset":0,"share":100},{"id":388,"offset":0,"share":100},{"id":389,"offset":0,"share":100},{"id":392,"offset":0,"share":100},{"id":393,"offset":0,"share":100},{"id":396,"offset":0,"share":100},{"id":398,"offset":0,"share":100},{"id":401,"offset":0,"share":100},{"id":402,"offset":0,"share":100},{"id":404,"offset":0,"share":100},{"id":405,"offset":0,"share":100},{"id":406,"offset":0,"share":100},{"id":407,"offset":0,"share":100},{"id":408,"offset":0,"share":100},{"id":414,"offset":0,"share":100},{"id":416,"offset":0,"share":100},{"id":421,"offset":0,"share":100},{"id":422,"offset":0,"share":100},{"id":426,"offset":0,"share":100},{"id":430,"offset":0,"share":100},{"id":434,"offset":0,"share":100},{"id":435,"offset":0,"share":100},{"id":436,"offset":0,"share":100},{"id":438,"offset":0,"share":100},{"id":440,"offset":0,"share":100},{"id":443,"offset":0,"share":100},{"id":444,"offset":0,"share":100},{"id":445,"offset":0,"share":100},{"id":446,"offset":0,"share":100},{"id":447,"offset":0,"share":100},{"id":448,"offset":0,"share":100},{"id":449,"offset":0,"share":100},{"id":450,"offset":0,"share":100},{"id":455,"offset":0,"share":100},{"id":456,"offset":0,"share":100},{"id":459,"offset":0,"share":25},{"id":460,"offset":0,"share":100},{"id":462,"offset":0,"share":100},{"id":471,"offset":0,"share":100},{"id":474,"offset":0,"share":100},{"id":475,"offset":0,"share":100},{"id":477,"offset":0,"share":50},{"id":478,"offset":0,"share":100},{"id":479,"offset":0,"share":100},{"id":480,"offset":0,"share":100},{"id":485,"offset":0,"share":100},{"id":486,"offset":0,"share":100},{"id":490,"offset":0,"share":100},{"id":491,"offset":0,"share":100},{"id":493,"offset":0,"share":100},{"id":495,"offset":0,"share":100},{"id":501,"offset":0,"share":100},{"id":502,"offset":0,"share":100},{"id":503,"offset":0,"share":100},{"id":504,"offset":0,"share":100},{"id":506,"offset":0,"share":100},{"id":509,"offset":0,"share":100},{"id":511,"offset":0,"share":100},{"id":515,"offset":0,"share":100},{"id":516,"offset":0,"share":100},{"id":517,"offset":0,"share":100},{"id":518,"offset":23,"share":100},{"id":519,"offset":0,"share":100},{"id":520,"offset":0,"share":100},{"id":521,"offset":0,"share":100},{"id":522,"offset":0,"share":100},{"id":523,"offset":23,"share":100},{"id":526,"offset":0,"share":100},{"id":528,"offset":0,"share":100},{"id":531,"offset":0,"share":100},{"id":532,"offset":23,"share":100},{"id":533,"offset":0,"share":100},{"id":534,"offset":0,"share":100},{"id":535,"offset":0,"share":100},{"id":536,"offset":0,"share":100},{"id":537,"offset":0,"share":100},{"id":539,"offset":0,"share":100},{"id":540,"offset":0,"share":100},{"id":543,"offset":0,"share":100},{"id":544,"offset":0,"share":100},{"id":545,"offset":0,"share":100},{"id":546,"offset":0,"share":100},{"id":547,"offset":0,"share":100},{"id":548,"offset":0,"share":100},{"id":549,"offset":0,"share":100},{"id":550,"offset":0,"share":100},{"id":552,"offset":0,"share":100},{"id":555,"offset":0,"share":100},{"id":556,"offset":0,"share":100},{"id":558,"offset":0,"share":100},{"id":559,"offset":0,"share":100},{"id":561,"offset":0,"share":100},{"id":565,"offset":23,"share":100},{"id":566,"offset":0,"share":100},{"id":568,"offset":0,"share":100},{"id":569,"offset":0,"share":100},{"id":570,"offset":0,"share":100},{"id":572,"offset":0,"share":100},{"id":574,"offset":0,"share":100},{"id":575,"offset":0,"share":100},{"id":577,"offset":0,"share":100},{"id":578,"offset":0,"share":100},{"id":579,"offset":0,"share":100},{"id":580,"offset":0,"share":100},{"id":582,"offset":0,"share":100},{"id":584,"offset":23,"share":60},{"id":586,"offset":0,"share":100},{"id":590,"offset":0,"share":100},{"id":594,"offset":0,"share":100},{"id":596,"offset":0,"share":100},{"id":598,"offset":0,"share":1},{"id":600,"offset":0,"share":100},{"id":604,"offset":0,"share":100},{"id":605,"offset":0,"share":100},{"id":606,"offset":0,"share":100},{"id":612,"offset":0,"share":100},{"id":614,"offset":0,"share":100},{"id":615,"offset":17,"share":100},{"id":616,"offset":0,"share":100},{"id":618,"offset":0,"share":100},{"id":621,"offset":0,"share":100},{"id":622,"offset":0,"share":100},{"id":625,"offset":0,"share":100},{"id":626,"offset":0,"share":100},{"id":627,"offset":0,"share":100},{"id":628,"offset":0,"share":100},{"id":629,"offset":0,"share":100},{"id":630,"offset":0,"share":100},{"id":634,"offset":0,"share":100},{"id":637,"offset":0,"share":100},{"id":640,"offset":0,"share":100},{"id":643,"offset":0,"share":100},{"id":644,"offset":0,"share":100},{"id":646,"offset":0,"share":100},{"id":651,"offset":0,"share":100},{"id":653,"offset":0,"share":100},{"id":655,"offset":0,"share":100},{"id":657,"offset":0,"share":100},{"id":658,"offset":0,"share":100},{"id":662,"offset":0,"share":100},{"id":667,"offset":0,"share":100},{"id":668,"offset":0,"share":100},{"id":671,"offset":0,"share":100},{"id":672,"offset":0,"share":100},{"id":674,"offset":0,"share":100},{"id":679,"offset":0,"share":100},{"id":680,"offset":0,"share":100},{"id":684,"offset":0,"share":25},{"id":686,"offset":0,"share":100},{"id":689,"offset":0,"share":100},{"id":692,"offset":0,"share":100},{"id":693,"offset":0,"share":100},{"id":694,"offset":0,"share":100},{"id":695,"offset":0,"share":100},{"id":697,"offset":0,"share":100},{"id":700,"offset":0,"share":100},{"id":701,"offset":0,"share":100},{"id":703,"offset":23,"share":100},{"id":704,"offset":0,"share":100},{"id":706,"offset":0,"share":100},{"id":709,"offset":0,"share":50},{"id":710,"offset":0,"share":100},{"id":715,"offset":0,"share":100},{"id":716,"offset":0,"share":100},{"id":718,"offset":23,"share":100},{"id":719,"offset":0,"share":100},{"id":720,"offset":0,"share":100},{"id":722,"offset":0,"share":100},{"id":723,"offset":0,"share":100},{"id":724,"offset":0,"share":100},{"id":726,"offset":0,"share":100},{"id":727,"offset":0,"share":100},{"id":728,"offset":0,"share":100},{"id":729,"offset":0,"share":100},{"id":730,"offset":0,"share":100},{"id":732,"offset":0,"share":100},{"id":739,"offset":0,"share":100},{"id":741,"offset":0,"share":100},{"id":745,"offset":0,"share":100},{"id":746,"offset":23,"share":100},{"id":747,"offset":23,"share":100},{"id":748,"offset":0,"share":1},{"id":752,"offset":0,"share":100},{"id":753,"offset":0,"share":100},{"id":755,"offset":0,"share":100},{"id":762,"offset":0,"share":100},{"id":763,"offset":23,"share":100},{"id":764,"offset":23,"share":100},{"id":767,"offset":0,"share":100},{"id":768,"offset":0,"share":100},{"id":770,"offset":0,"share":100},{"id":771,"offset":0,"share":100},{"id":773,"offset":0,"share":100},{"id":774,"offset":0,"share":100},{"id":775,"offset":0,"share":100},{"id":779,"offset":0,"share":100},{"id":783,"offset":0,"share":100},{"id":784,"offset":0,"share":100},{"id":786,"offset":0,"share":100},{"id":793,"offset":0,"share":100},{"id":796,"offset":0,"share":100},{"id":800,"offset":0,"share":100},{"id":801,"offset":0,"share":100},{"id":804,"offset":0,"share":100},{"id":806,"offset":0,"share":100},{"id":812,"offset":0,"share":100},{"id":813,"offset":0,"share":100},{"id":814,"offset":0,"share":100},{"id":817,"offset":0,"share":100},{"id":818,"offset":0,"share":100},{"id":820,"offset":0,"share":100},{"id":821,"offset":0,"share":100},{"id":822,"offset":0,"share":100},{"id":823,"offset":0,"share":100},{"id":824,"offset":0,"share":100},{"id":825,"offset":0,"share":100},{"id":829,"offset":0,"share":100},{"id":831,"offset":0,"share":100},{"id":833,"offset":0,"share":100},{"id":836,"offset":0,"share":100},{"id":837,"offset":0,"share":100},{"id":838,"offset":0,"share":100},{"id":839,"offset":0,"share":100},{"id":840,"offset":0,"share":100},{"id":842,"offset":23,"share":100},{"id":843,"offset":0,"share":100},{"id":845,"offset":0,"share":100},{"id":846,"offset":0,"share":100},{"id":847,"offset":0,"share":100},{"id":851,"offset":0,"share":100},{"id":854,"offset":0,"share":100},{"id":856,"offset":0,"share":100},{"id":857,"offset":0,"share":100},{"id":859,"offset":0,"share":100},{"id":860,"offset":0,"share":100},{"id":863,"offset":0,"share":100},{"id":864,"offset":0,"share":100},{"id":865,"offset":0,"share":100},{"id":866,"offset":0,"share":100},{"id":867,"offset":0,"share":100},{"id":871,"offset":0,"share":100},{"id":874,"offset":0,"share":100},{"id":875,"offset":0,"share":100},{"id":876,"offset":0,"share":100},{"id":878,"offset":0,"share":100},{"id":879,"offset":0,"share":10},{"id":880,"offset":0,"share":100},{"id":882,"offset":0,"share":50},{"id":886,"offset":0,"share":50},{"id":888,"offset":0,"share":100},{"id":893,"offset":0,"share":100},{"id":896,"offset":0,"share":100},{"id":897,"offset":0,"share":100},{"id":898,"offset":0,"share":100},{"id":900,"offset":0,"share":100},{"id":901,"offset":0,"share":100},{"id":902,"offset":0,"share":100},{"id":904,"offset":0,"share":100},{"id":908,"offset":0,"share":100},{"id":909,"offset":0,"share":100},{"id":910,"offset":0,"share":100},{"id":911,"offset":23,"share":100},{"id":912,"offset":0,"share":100},{"id":915,"offset":0,"share":100},{"id":916,"offset":0,"share":100},{"id":918,"offset":0,"share":100},{"id":919,"offset":0,"share":100},{"id":921,"offset":0,"share":100},{"id":922,"offset":0,"share":100},{"id":923,"offset":0,"share":100},{"id":925,"offset":0,"share":100},{"id":926,"offset":0,"share":100},{"id":927,"offset":0,"share":100},{"id":928,"offset":0,"share":100},{"id":929,"offset":0,"share":100},{"id":932,"offset":0,"share":100},{"id":933,"offset":0,"share":100},{"id":935,"offset":0,"share":100},{"id":941,"offset":0,"share":100},{"id":942,"offset":0,"share":100},{"id":944,"offset":0,"share":100},{"id":948,"offset":0,"share":100},{"id":949,"offset":0,"share":100},{"id":953,"offset":0,"share":100},{"id":954,"offset":0,"share":100},{"id":955,"offset":0,"share":100},{"id":957,"offset":0,"share":100},{"id":959,"offset":0,"share":100},{"id":960,"offset":0,"share":100},{"id":961,"offset":0,"share":100},{"id":963,"offset":0,"share":100},{"id":964,"offset":0,"share":100},{"id":966,"offset":0,"share":100},{"id":968,"offset":0,"share":100},{"id":969,"offset":0,"share":100},{"id":971,"offset":0,"share":100},{"id":972,"offset":0,"share":100},{"id":973,"offset":0,"share":100},{"id":977,"offset":0,"share":100},{"id":979,"offset":0,"share":100},{"id":987,"offset":0,"share":100},{"id":989,"offset":0,"share":100},{"id":993,"offset":0,"share":100},{"id":995,"offset":0,"share":100},{"id":997,"offset":0,"share":100},{"id":999,"offset":0,"share":100},{"id":1000,"offset":0,"share":100},{"id":1003,"offset":0,"share":100},{"id":1006,"offset":0,"share":100},{"id":1007,"offset":0,"share":100},{"id":1014,"offset":0,"share":100},{"id":1015,"offset":0,"share":100},{"id":1016,"offset":0,"share":100},{"id":1020,"offset":0,"share":100},{"id":1021,"offset":0,"share":100},{"id":1022,"offset":0,"share":100},{"id":1024,"offset":0,"share":100},{"id":1031,"offset":0,"share":100},{"id":1032,"offset":0,"share":100},{"id":1034,"offset":0,"share":100},{"id":1035,"offset":0,"share":100},{"id":1037,"offset":0,"share":100},{"id":1038,"offset":0,"share":100},{"id":1045,"offset":0,"share":100},{"id":1046,"offset":0,"share":100},{"id":1048,"offset":0,"share":100},{"id":1058,"offset":0,"share":100},{"id":1059,"offset":0,"share":100},{"id":1062,"offset":0,"share":100},{"id":1064,"offset":0,"share":100},{"id":1068,"offset":0,"share":100},{"id":1069,"offset":0,"share":100},{"id":1070,"offset":0,"share":100},{"id":1072,"offset":0,"share":100},{"id":1073,"offset":0,"share":100},{"id":1075,"offset":0,"share":100},{"id":1076,"offset":0,"share":100},{"id":1079,"offset":0,"share":100},{"id":1080,"offset":0,"share":100},{"id":1082,"offset":0,"share":100},{"id":1083,"offset":0,"share":100},{"id":1084,"offset":0,"share":100},{"id":1085,"offset":0,"share":100},{"id":1086,"offset":0,"share":100},{"id":1087,"offset":0,"share":100},{"id":1088,"offset":0,"share":100},{"id":1093,"offset":0,"share":100},{"id":1094,"offset":0,"share":100},{"id":1097,"offset":0,"share":100},{"id":1104,"offset":0,"share":100},{"id":1105,"offset":0,"share":100},{"id":1106,"offset":0,"share":100},{"id":1107,"offset":0,"share":100},{"id":1108,"offset":0,"share":100},{"id":1109,"offset":0,"share":100},{"id":1111,"offset":0,"share":100},{"id":1114,"offset":0,"share":100},{"id":1115,"offset":0,"share":100},{"id":1122,"offset":0,"share":100},{"id":1123,"offset":0,"share":100},{"id":1124,"offset":0,"share":100},{"id":1126,"offset":0,"share":100},{"id":1130,"offset":0,"share":100},{"id":1138,"offset":0,"share":100},{"id":1145,"offset":0,"share":100},{"id":1148,"offset":0,"share":100},{"id":1149,"offset":0,"share":100},{"id":1150,"offset":0,"share":100},{"id":1151,"offset":0,"share":100},{"id":1152,"offset":0,"share":100},{"id":1153,"offset":0,"share":100},{"id":1154,"offset":0,"share":100},{"id":1155,"offset":0,"share":100},{"id":1158,"offset":0,"share":100},{"id":1163,"offset":0,"share":100},{"id":1165,"offset":0,"share":100},{"id":1168,"offset":0,"share":100},{"id":1172,"offset":0,"share":100},{"id":1176,"offset":0,"share":100},{"id":1180,"offset":0,"share":100},{"id":1181,"offset":0,"share":100},{"id":1182,"offset":0,"share":100},{"id":1184,"offset":0,"share":100},{"id":1188,"offset":0,"share":100},{"id":1189,"offset":0,"share":100},{"id":1190,"offset":0,"share":100},{"id":1191,"offset":0,"share":100},{"id":1192,"offset":0,"share":100},{"id":1193,"offset":0,"share":100},{"id":1194,"offset":0,"share":100},{"id":1195,"offset":0,"share":100},{"id":1197,"offset":0,"share":100},{"id":1198,"offset":0,"share":100},{"id":1201,"offset":0,"share":100},{"id":1202,"offset":0,"share":100},{"id":1206,"offset":0,"share":100},{"id":1210,"offset":0,"share":100},{"id":1211,"offset":0,"share":100},{"id":1213,"offset":0,"share":100},{"id":1215,"offset":0,"share":100},{"id":1216,"offset":0,"share":100},{"id":1217,"offset":0,"share":100},{"id":1218,"offset":0,"share":100},{"id":1219,"offset":0,"share":100},{"id":1220,"offset":0,"share":100},{"id":1223,"offset":0,"share":100},{"id":1224,"offset":0,"share":100},{"id":1227,"offset":0,"share":100},{"id":1230,"offset":0,"share":100},{"id":1231,"offset":0,"share":100},{"id":1233,"offset":0,"share":100},{"id":1234,"offset":0,"share":100},{"id":1235,"offset":0,"share":100},{"id":1236,"offset":0,"share":100},{"id":1237,"offset":0,"share":100},{"id":1239,"offset":0,"share":100},{"id":1241,"offset":0,"share":100},{"id":1245,"offset":0,"share":100},{"id":1246,"offset":0,"share":100},{"id":1248,"offset":0,"share":100},{"id":1249,"offset":0,"share":100},{"id":1252,"offset":0,"share":100},{"id":1253,"offset":0,"share":100},{"id":1254,"offset":0,"share":100},{"id":1255,"offset":0,"share":100},{"id":1257,"offset":0,"share":100},{"id":1258,"offset":0,"share":100},{"id":1259,"offset":0,"share":100},{"id":1260,"offset":0,"share":100},{"id":1261,"offset":0,"share":100},{"id":1262,"offset":0,"share":100},{"id":1263,"offset":0,"share":100},{"id":1264,"offset":0,"share":100},{"id":1266,"offset":0,"share":100},{"id":1267,"offset":0,"share":100},{"id":1271,"offset":0,"share":100},{"id":1272,"offset":0,"share":100},{"id":1273,"offset":0,"share":100},{"id":1274,"offset":0,"share":4},{"id":1275,"offset":0,"share":100},{"id":1276,"offset":0,"share":100},{"id":1277,"offset":0,"share":100},{"id":1280,"offset":0,"share":100},{"id":1281,"offset":0,"share":100},{"id":1282,"offset":0,"share":100},{"id":1288,"offset":0,"share":100},{"id":1292,"offset":0,"share":100},{"id":1293,"offset":0,"share":1},{"id":1294,"offset":0,"share":100},{"id":1296,"offset":0,"share":100},{"id":1297,"offset":0,"share":100},{"id":1301,"offset":0,"share":100},{"id":1302,"offset":0,"share":100},{"id":1304,"offset":0,"share":100},{"id":1305,"offset":0,"share":1},{"id":1306,"offset":0,"share":100},{"id":1309,"offset":0,"share":100},{"id":1315,"offset":0,"share":1},{"id":1323,"offset":0,"share":100},{"id":1331,"offset":0,"share":100},{"id":1332,"offset":0,"share":100},{"id":1336,"offset":0,"share":100},{"id":1338,"offset":0,"share":100},{"id":1346,"offset":0,"share":100},{"id":1348,"offset":0,"share":100},{"id":1354,"offset":0,"share":100},{"id":1356,"offset":0,"share":100},{"id":1357,"offset":0,"share":100},{"id":1358,"offset":0,"share":100},{"id":1359,"offset":0,"share":100},{"id":1360,"offset":0,"share":100},{"id":1361,"offset":0,"share":100},{"id":1362,"offset":0,"share":100},{"id":1365,"offset":0,"share":100},{"id":1369,"offset":0,"share":100},{"id":1370,"offset":0,"share":100},{"id":1371,"offset":0,"share":100},{"id":1372,"offset":0,"share":100},{"id":1376,"offset":0,"share":100},{"id":1379,"offset":0,"share":100},{"id":1384,"offset":0,"share":100},{"id":1386,"offset":0,"share":100},{"id":1387,"offset":0,"share":1},{"id":1390,"offset":0,"share":100},{"id":1391,"offset":0,"share":100},{"id":1392,"offset":0,"share":100},{"id":1393,"offset":0,"share":100},{"id":1398,"offset":0,"share":100},{"id":1400,"offset":0,"share":100},{"id":1401,"offset":0,"share":100},{"id":1402,"offset":0,"share":100},{"id":1405,"offset":0,"share":100},{"id":1406,"offset":0,"share":100},{"id":1408,"offset":0,"share":100},{"id":1409,"offset":0,"share":100},{"id":1410,"offset":0,"share":100},{"id":1411,"offset":0,"share":100},{"id":1413,"offset":0,"share":100},{"id":1420,"offset":0,"share":1},{"id":1426,"offset":0,"share":100},{"id":1428,"offset":0,"share":100},{"id":1429,"offset":0,"share":100},{"id":1430,"offset":0,"share":100},{"id":1431,"offset":0,"share":100},{"id":1432,"offset":0,"share":100},{"id":1433,"offset":0,"share":100},{"id":1434,"offset":0,"share":100},{"id":1435,"offset":0,"share":100},{"id":1436,"offset":0,"share":10},{"id":1441,"offset":0,"share":50},{"id":1442,"offset":0,"share":100},{"id":1447,"offset":0,"share":100},{"id":1448,"offset":0,"share":100},{"id":1449,"offset":0,"share":100},{"id":1452,"offset":0,"share":100},{"id":1453,"offset":0,"share":100},{"id":1454,"offset":0,"share":100},{"id":1456,"offset":0,"share":100},{"id":1458,"offset":0,"share":100},{"id":1459,"offset":0,"share":100},{"id":1460,"offset":0,"share":100},{"id":1465,"offset":0,"share":100},{"id":1466,"offset":0,"share":100},{"id":1467,"offset":0,"share":50},{"id":1468,"offset":0,"share":100},{"id":1469,"offset":0,"share":100},{"id":1470,"offset":0,"share":100},{"id":1473,"offset":0,"share":100},{"id":1474,"offset":0,"share":100},{"id":1475,"offset":0,"share":100},{"id":1480,"offset":0,"share":100},{"id":1483,"offset":0,"share":100},{"id":1486,"offset":0,"share":100},{"id":1489,"offset":0,"share":100},{"id":1490,"offset":0,"share":100},{"id":1494,"offset":0,"share":100},{"id":1495,"offset":0,"share":100},{"id":1496,"offset":0,"share":100},{"id":1497,"offset":0,"share":100},{"id":1498,"offset":0,"share":100},{"id":1505,"offset":0,"share":100},{"id":1506,"offset":0,"share":100},{"id":1513,"offset":0,"share":100},{"id":1515,"offset":0,"share":100},{"id":1517,"offset":0,"share":100},{"id":1518,"offset":0,"share":100},{"id":1519,"offset":0,"share":100},{"id":1520,"offset":0,"share":100},{"id":1522,"offset":0,"share":100},{"id":1523,"offset":0,"share":100},{"id":1524,"offset":0,"share":100},{"id":1530,"offset":0,"share":100},{"id":1531,"offset":0,"share":100},{"id":1532,"offset":0,"share":100},{"id":1533,"offset":0,"share":100},{"id":1535,"offset":0,"share":100},{"id":1537,"offset":0,"share":100},{"id":1539,"offset":0,"share":100},{"id":1540,"offset":0,"share":100},{"id":1543,"offset":0,"share":100},{"id":1544,"offset":0,"share":100},{"id":1545,"offset":0,"share":100},{"id":1546,"offset":0,"share":100},{"id":1547,"offset":0,"share":100},{"id":1548,"offset":0,"share":100},{"id":1549,"offset":0,"share":100},{"id":1555,"offset":0,"share":100},{"id":1558,"offset":0,"share":100},{"id":1559,"offset":0,"share":100},{"id":1561,"offset":0,"share":100},{"id":1562,"offset":0,"share":100},{"id":1567,"offset":0,"share":100},{"id":1570,"offset":0,"share":100},{"id":1571,"offset":0,"share":100},{"id":1572,"offset":0,"share":100},{"id":1573,"offset":0,"share":100},{"id":1574,"offset":0,"share":100},{"id":1575,"offset":0,"share":100},{"id":1577,"offset":0,"share":100},{"id":1588,"offset":0,"share":100},{"id":1589,"offset":0,"share":100},{"id":1596,"offset":0,"share":100},{"id":1598,"offset":0,"share":100},{"id":1600,"offset":0,"share":100},{"id":1601,"offset":0,"share":100},{"id":1609,"offset":0,"share":100},{"id":1610,"offset":0,"share":10},{"id":1613,"offset":0,"share":100},{"id":1615,"offset":0,"share":100},{"id":1618,"offset":0,"share":100},{"id":1620,"offset":0,"share":100},{"id":1621,"offset":0,"share":100},{"id":1624,"offset":0,"share":100},{"id":1626,"offset":0,"share":100},{"id":1627,"offset":0,"share":100},{"id":1628,"offset":0,"share":100},{"id":1636,"offset":0,"share":100},{"id":1640,"offset":0,"share":10},{"id":1641,"offset":0,"share":100},{"id":1643,"offset":0,"share":100},{"id":1646,"offset":0,"share":100},{"id":1649,"offset":0,"share":100},{"id":1650,"offset":0,"share":100},{"id":1652,"offset":0,"share":100},{"id":1654,"offset":0,"share":100},{"id":1661,"offset":0,"share":100},{"id":1664,"offset":0,"share":100},{"id":1665,"offset":0,"share":100},{"id":1666,"offset":0,"share":100},{"id":1668,"offset":0,"share":100},{"id":1669,"offset":0,"share":100},{"id":1670,"offset":0,"share":100},{"id":1673,"offset":0,"share":100},{"id":1678,"offset":0,"share":100},{"id":1681,"offset":0,"share":100},{"id":1682,"offset":0,"share":100},{"id":1684,"offset":0,"share":100},{"id":1690,"offset":0,"share":100},{"id":1693,"offset":0,"share":100},{"id":1694,"offset":0,"share":100},{"id":1695,"offset":0,"share":100},{"id":1696,"offset":0,"share":100},{"id":1698,"offset":0,"share":1},{"id":1699,"offset":0,"share":1},{"id":1703,"offset":0,"share":100},{"id":1704,"offset":0,"share":100},{"id":1707,"offset":0,"share":100},{"id":1710,"offset":0,"share":100},{"id":1711,"offset":0,"share":100},{"id":1712,"offset":0,"share":100},{"id":1716,"offset":0,"share":100},{"id":1718,"offset":0,"share":100},{"id":1720,"offset":0,"share":100},{"id":1721,"offset":0,"share":100},{"id":1722,"offset":0,"share":100},{"id":1723,"offset":0,"share":100},{"id":1724,"offset":0,"share":100},{"id":1731,"offset":0,"share":100},{"id":1732,"offset":0,"share":100},{"id":1734,"offset":0,"share":100},{"id":1739,"offset":0,"share":100},{"id":1741,"offset":0,"share":1},{"id":1742,"offset":0,"share":1},{"id":1748,"offset":0,"share":100},{"id":1749,"offset":0,"share":100},{"id":1755,"offset":0,"share":100},{"id":1756,"offset":0,"share":100},{"id":1757,"offset":0,"share":100},{"id":1762,"offset":0,"share":100},{"id":1763,"offset":0,"share":100},{"id":1765,"offset":0,"share":1},{"id":1766,"offset":0,"share":1},{"id":1767,"offset":0,"share":100},{"id":1768,"offset":0,"share":100},{"id":1769,"offset":0,"share":100},{"id":1770,"offset":0,"share":100},{"id":1772,"offset":0,"share":1},{"id":1773,"offset":0,"share":1},{"id":1779,"offset":0,"share":100},{"id":1780,"offset":0,"share":100},{"id":1782,"offset":0,"share":100},{"id":1784,"offset":0,"share":100},{"id":1785,"offset":0,"share":100},{"id":1786,"offset":0,"share":100},{"id":1787,"offset":0,"share":100},{"id":1790,"offset":0,"share":100},{"id":1795,"offset":0,"share":100},{"id":1797,"offset":0,"share":100},{"id":1798,"offset":0,"share":10},{"id":1800,"offset":0,"share":100},{"id":1801,"offset":0,"share":100},{"id":1802,"offset":0,"share":100},{"id":1803,"offset":0,"share":100},{"id":1804,"offset":0,"share":100},{"id":1805,"offset":0,"share":100},{"id":1806,"offset":0,"share":100},{"id":1807,"offset":0,"share":100},{"id":1811,"offset":0,"share":100},{"id":1814,"offset":0,"share":100},{"id":1815,"offset":0,"share":100},{"id":1821,"offset":0,"share":100},{"id":1825,"offset":0,"share":100},{"id":1830,"offset":0,"share":100},{"id":1831,"offset":0,"share":100},{"id":1833,"offset":0,"share":100},{"id":1834,"offset":0,"share":100},{"id":1835,"offset":0,"share":100},{"id":1836,"offset":0,"share":100},{"id":1847,"offset":0,"share":100},{"id":1850,"offset":0,"share":100},{"id":1851,"offset":0,"share":100},{"id":1853,"offset":0,"share":100},{"id":1854,"offset":0,"share":100},{"id":1855,"offset":0,"share":100},{"id":1856,"offset":0,"share":100},{"id":1861,"offset":0,"share":100},{"id":1863,"offset":0,"share":100},{"id":1864,"offset":0,"share":100},{"id":1867,"offset":0,"share":100},{"id":1868,"offset":0,"share":100},{"id":1871,"offset":0,"share":100},{"id":1876,"offset":0,"share":100},{"id":1878,"offset":0,"share":100},{"id":1879,"offset":0,"share":100},{"id":1880,"offset":0,"share":100},{"id":1882,"offset":0,"share":100},{"id":1885,"offset":0,"share":100},{"id":1886,"offset":0,"share":100},{"id":1887,"offset":0,"share":100},{"id":1892,"offset":0,"share":100},{"id":1893,"offset":0,"share":100},{"id":1894,"offset":0,"share":100},{"id":1895,"offset":0,"share":100},{"id":1899,"offset":0,"share":100},{"id":1900,"offset":0,"share":100},{"id":1902,"offset":0,"share":100},{"id":1904,"offset":0,"share":100},{"id":1906,"offset":0,"share":100},{"id":1907,"offset":0,"share":100},{"id":1908,"offset":0,"share":1},{"id":1909,"offset":0,"share":100},{"id":1910,"offset":0,"share":100},{"id":1911,"offset":0,"share":100},{"id":1912,"offset":0,"share":100},{"id":1913,"offset":0,"share":100},{"id":1919,"offset":0,"share":100},{"id":1922,"offset":0,"share":100},{"id":1925,"offset":0,"share":100},{"id":1932,"offset":0,"share":100},{"id":1934,"offset":0,"share":100},{"id":1937,"offset":0,"share":100},{"id":1943,"offset":0,"share":100},{"id":1945,"offset":0,"share":100},{"id":1946,"offset":0,"share":100},{"id":1951,"offset":0,"share":100},{"id":1952,"offset":0,"share":100},{"id":1953,"offset":0,"share":100},{"id":1955,"offset":0,"share":100},{"id":1959,"offset":0,"share":100},{"id":1960,"offset":0,"share":100},{"id":1963,"offset":0,"share":100},{"id":1967,"offset":0,"share":100},{"id":1969,"offset":0,"share":100},{"id":1975,"offset":0,"share":100},{"id":1977,"offset":0,"share":100},{"id":1979,"offset":0,"share":100},{"id":1984,"offset":0,"share":100},{"id":1989,"offset":0,"share":100},{"id":1990,"offset":0,"share":100},{"id":1992,"offset":0,"share":100},{"id":1995,"offset":0,"share":100},{"id":1996,"offset":0,"share":100},{"id":1997,"offset":0,"share":100},{"id":1998,"offset":0,"share":100},{"id":2000,"offset":0,"share":100},{"id":2001,"offset":0,"share":100},{"id":2009,"offset":0,"share":100},{"id":2010,"offset":0,"share":100},{"id":2013,"offset":0,"share":100},{"id":2014,"offset":0,"share":100},{"id":2015,"offset":0,"share":100},{"id":2019,"offset":0,"share":100},{"id":2022,"offset":0,"share":100},{"id":2026,"offset":0,"share":1},{"id":2027,"offset":0,"share":100},{"id":2029,"offset":0,"share":100},{"id":2031,"offset":0,"share":100},{"id":2032,"offset":0,"share":100},{"id":2035,"offset":0,"share":100},{"id":2038,"offset":0,"share":100},{"id":2039,"offset":0,"share":100},{"id":2041,"offset":0,"share":100},{"id":2043,"offset":0,"share":100},{"id":2046,"offset":0,"share":100},{"id":2058,"offset":0,"share":100},{"id":2061,"offset":0,"share":100},{"id":2063,"offset":0,"share":100},{"id":2064,"offset":0,"share":100},{"id":2065,"offset":0,"share":100},{"id":2066,"offset":0,"share":100},{"id":2071,"offset":0,"share":100},{"id":2078,"offset":0,"share":100},{"id":2079,"offset":0,"share":100},{"id":2080,"offset":0,"share":100},{"id":2081,"offset":0,"share":100},{"id":2084,"offset":0,"share":100},{"id":2089,"offset":0,"share":100},{"id":2092,"offset":0,"share":100},{"id":2095,"offset":0,"share":100},{"id":2100,"offset":0,"share":50},{"id":2102,"offset":0,"share":100},{"id":2105,"offset":0,"share":100},{"id":2107,"offset":0,"share":100},{"id":2108,"offset":0,"share":100},{"id":2109,"offset":0,"share":100},{"id":2111,"offset":0,"share":50},{"id":2113,"offset":0,"share":100},{"id":2118,"offset":0,"share":10},{"id":2119,"offset":0,"share":100},{"id":2124,"offset":0,"share":100},{"id":2125,"offset":0,"share":100},{"id":2126,"offset":0,"share":100},{"id":2128,"offset":0,"share":100},{"id":2133,"offset":0,"share":100},{"id":2137,"offset":0,"share":100},{"id":2139,"offset":0,"share":100},{"id":2142,"offset":0,"share":100},{"id":2144,"offset":0,"share":100},{"id":2147,"offset":0,"share":100},{"id":2148,"offset":0,"share":100},{"id":2152,"offset":0,"share":100},{"id":2155,"offset":0,"share":1},{"id":2162,"offset":0,"share":100},{"id":2163,"offset":0,"share":100},{"id":2164,"offset":0,"share":1},{"id":2169,"offset":0,"share":100},{"id":2174,"offset":0,"share":100},{"id":2177,"offset":0,"share":100},{"id":2178,"offset":0,"share":100},{"id":2179,"offset":0,"share":100},{"id":2180,"offset":0,"share":100},{"id":2181,"offset":0,"share":100},{"id":2182,"offset":0,"share":100},{"id":2183,"offset":0,"share":100},{"id":2185,"offset":0,"share":10},{"id":2190,"offset":0,"share":100},{"id":2192,"offset":0,"share":100},{"id":2195,"offset":0,"share":100},{"id":2199,"offset":0,"share":100},{"id":2202,"offset":0,"share":100},{"id":2205,"offset":0,"share":100},{"id":2206,"offset":0,"share":100},{"id":2208,"offset":0,"share":100},{"id":2210,"offset":0,"share":100},{"id":2212,"offset":0,"share":100},{"id":2214,"offset":0,"share":100},{"id":2217,"offset":0,"share":100},{"id":2219,"offset":0,"share":100},{"id":2221,"offset":0,"share":100},{"id":2226,"offset":0,"share":100},{"id":2234,"offset":0,"share":100},{"id":2235,"offset":0,"share":100},{"id":2236,"offset":0,"share":100},{"id":2239,"offset":0,"share":100},{"id":2243,"offset":0,"share":100},{"id":2248,"offset":0,"share":100},{"id":2254,"offset":0,"share":1},{"id":2258,"offset":0,"share":100},{"id":2263,"offset":0,"share":100},{"id":2268,"offset":0,"share":100},{"id":2271,"offset":0,"share":100},{"id":2274,"offset":0,"share":100},{"id":2281,"offset":0,"share":100},{"id":2290,"offset":0,"share":100},{"id":2293,"offset":0,"share":100},{"id":2294,"offset":0,"share":100},{"id":2298,"offset":0,"share":100},{"id":2305,"offset":0,"share":100},{"id":2307,"offset":0,"share":100},{"id":2308,"offset":0,"share":100},{"id":2311,"offset":0,"share":100},{"id":2317,"offset":0,"share":100},{"id":2318,"offset":0,"share":100},{"id":2319,"offset":0,"share":100},{"id":2322,"offset":0,"share":100},{"id":2325,"offset":0,"share":100},{"id":2327,"offset":0,"share":100},{"id":2332,"offset":0,"share":100},{"id":2335,"offset":0,"share":25},{"id":2337,"offset":0,"share":100},{"id":2340,"offset":0,"share":100},{"id":2342,"offset":0,"share":100},{"id":2346,"offset":0,"share":100},{"id":2348,"offset":0,"share":100},{"id":2349,"offset":0,"share":100},{"id":2350,"offset":0,"share":100},{"id":2351,"offset":0,"share":100},{"id":2354,"offset":0,"share":100},{"id":2355,"offset":0,"share":100},{"id":2357,"offset":0,"share":100},{"id":2362,"offset":0,"share":100},{"id":2363,"offset":0,"share":100},{"id":2366,"offset":0,"share":100},{"id":2367,"offset":0,"share":100},{"id":2371,"offset":0,"share":100},{"id":2372,"offset":0,"share":100},{"id":2374,"offset":0,"share":100},{"id":2376,"offset":0,"share":100},{"id":2377,"offset":0,"share":10},{"id":2378,"offset":0,"share":100},{"id":2383,"offset":0,"share":100},{"id":2389,"offset":0,"share":100},{"id":2391,"offset":0,"share":100},{"id":2393,"offset":0,"share":100},{"id":2394,"offset":0,"share":25},{"id":2395,"offset":0,"share":100},{"id":2397,"offset":0,"share":100},{"id":2398,"offset":0,"share":100},{"id":2399,"offset":0,"share":100},{"id":2401,"offset":0,"share":100},{"id":2404,"offset":0,"share":100},{"id":2406,"offset":0,"share":100},{"id":2409,"offset":0,"share":100},{"id":2410,"offset":0,"share":100},{"id":2411,"offset":0,"share":100},{"id":2412,"offset":0,"share":100},{"id":2415,"offset":0,"share":100},{"id":2416,"offset":0,"share":100},{"id":2419,"offset":0,"share":100},{"id":2422,"offset":0,"share":100},{"id":2423,"offset":0,"share":10},{"id":2424,"offset":0,"share":100},{"id":2425,"offset":0,"share":100},{"id":2427,"offset":0,"share":100},{"id":2430,"offset":0,"share":100},{"id":2434,"offset":0,"share":100},{"id":2439,"offset":0,"share":100},{"id":2440,"offset":0,"share":100},{"id":2441,"offset":0,"share":100},{"id":2444,"offset":0,"share":100},{"id":2446,"offset":0,"share":100},{"id":2447,"offset":0,"share":10},{"id":2448,"offset":0,"share":100},{"id":2449,"offset":0,"share":100},{"id":2450,"offset":0,"share":100},{"id":2451,"offset":0,"share":100},{"id":2454,"offset":0,"share":100},{"id":2456,"offset":0,"share":100},{"id":2458,"offset":0,"share":100},{"id":2461,"offset":0,"share":100},{"id":2463,"offset":0,"share":100},{"id":2466,"offset":0,"share":100},{"id":2467,"offset":0,"share":100},{"id":2474,"offset":0,"share":1},{"id":2476,"offset":0,"share":100},{"id":2480,"offset":0,"share":100},{"id":2482,"offset":0,"share":100},{"id":2485,"offset":0,"share":100},{"id":2488,"offset":0,"share":100},{"id":2497,"offset":0,"share":100},{"id":2498,"offset":0,"share":100},{"id":2500,"offset":0,"share":100},{"id":2502,"offset":0,"share":100},{"id":2505,"offset":0,"share":100},{"id":2506,"offset":0,"share":100},{"id":2507,"offset":0,"share":100},{"id":2508,"offset":0,"share":60},{"id":2509,"offset":0,"share":100},{"id":2517,"offset":0,"share":100},{"id":2520,"offset":0,"share":100},{"id":2521,"offset":0,"share":100},{"id":2522,"offset":0,"share":100},{"id":2524,"offset":0,"share":100},{"id":2525,"offset":0,"share":100},{"id":2526,"offset":0,"share":100},{"id":2532,"offset":0,"share":1},{"id":2535,"offset":0,"share":100},{"id":2536,"offset":0,"share":100},{"id":2538,"offset":0,"share":100},{"id":2546,"offset":0,"share":100},{"id":2547,"offset":0,"share":100},{"id":2550,"offset":0,"share":100},{"id":2552,"offset":0,"share":100},{"id":2555,"offset":0,"share":100},{"id":2557,"offset":0,"share":100},{"id":2559,"offset":0,"share":100},{"id":2561,"offset":0,"share":100},{"id":2563,"offset":0,"share":100},{"id":2578,"offset":0,"share":100},{"id":2579,"offset":0,"share":100},{"id":2582,"offset":0,"share":100},{"id":2584,"offset":0,"share":100},{"id":2587,"offset":0,"share":100},{"id":2588,"offset":0,"share":100},{"id":2591,"offset":0,"share":100},{"id":2592,"offset":0,"share":100},{"id":2595,"offset":0,"share":100},{"id":2601,"offset":0,"share":100},{"id":2602,"offset":0,"share":100},{"id":2606,"offset":0,"share":10},{"id":2612,"offset":0,"share":50},{"id":2617,"offset":0,"share":5},{"id":2620,"offset":0,"share":25},{"id":2623,"offset":0,"share":100},{"id":2641,"offset":0,"share":100},{"id":2650,"offset":0,"share":100},{"id":2655,"offset":0,"share":1},{"id":2656,"offset":0,"share":100},{"id":2657,"offset":0,"share":50},{"id":2659,"offset":0,"share":50},{"id":2662,"offset":0,"share":25},{"id":2663,"offset":0,"share":50}],"settings":[{"id":0,"value":"VRR1TASCLT*|odsp35*|VNBP101*|*\\Abby|*\\moeuser|moeuser|*\\drxaccount|drxaccount|*\\TASClient|TASClient|PYXIDIS\\pulsar|PYXIDIS\\tank|LocalAdminUser|AdminUAC|*\\cloudtest|cloudtest|NTDEV\\ntlab"},{"id":1,"value":"0x8004de25|0x0000de2a|0x8004de40|0x8004de42|0x8004de43|0x8004de44|0x8004de85|0x8004de8b|0x8004deb2|0x8004deb6|0x8004dea0|0x8004deaa|0x8004deac|0x8004deae|0x8004deaf|0x8004dea3|0x8004dea9"},{"id":10,"value":"0"},{"id":105,"value":"-1071316797|-1071316963|-2147164539"},{"id":108,"value":"0x8004de40|0x8004de81|0x00000001"},{"id":109,"value":"350000"},{"id":11,"value":"desktop.ini|thumbs.db|Microsoft Edge.lnk"},{"id":110,"value":"3600"},{"id":111,"value":"604800"},{"id":114,"value":"2"},{"id":117,"value":"7200000 "},{"id":118,"value":"300"},{"id":119,"value":"2048"},{"id":120,"value":"2048"},{"id":121,"value":"fpc.msedge.net\/conf\/v2\/odsync\/fpconfig.min.json"},{"id":122,"value":"100"},{"id":123,"value":"127116"},{"id":124,"value":"6"},{"id":125,"value":"Other"},{"id":127,"value":"1"},{"id":128,"value":"10"},{"id":129,"value":"6300000 "},{"id":130,"value":"120"},{"id":131,"value":"clients.config.office.net\/user\/v1.0\/windows\/ack"},{"id":132,"value":"roaming.officeapps.live.com\/rs\/RoamingSoapService.svc"},{"id":133,"value":"clients.config.office.net\/user\/v1.0\/windows\/policies"},{"id":134,"value":"roaming.officeapps.live.com\/rs\/RoamingSoapService.svc"},{"id":137,"value":"30"},{"id":138,"value":"600"},{"id":139,"value":"3"},{"id":14,"value":"600 "},{"id":140,"value":"14400"},{"id":143,"value":"604800"},{"id":144,"value":"14400"},{"id":145,"value":"10"},{"id":149,"value":"[{\n \"name\": \"OD_CUSTOM_PROFILE\",\n \"rules\": [\n { \"netCost\": \"restricted\", \"timers\": [ -1, -1, -1 ] },\n { \"netCost\": \"high\", \"powerState\": \"unknown\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"high\", \"powerState\": \"battery\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"high\", \"powerState\": \"charging\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"low\", \"powerState\": \"unknown\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"low\", \"powerState\": \"battery\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"low\", \"powerState\": \"charging\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"unknown\", \"powerState\": \"unknown\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"unknown\", \"powerState\": \"battery\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"unknown\", \"powerState\": \"charging\", \"timers\": [ 300, 30, 10 ] },\n { \"timers\": [ -1, -1, -1 ] }\n ]\n}]"},{"id":15,"value":"1209600"},{"id":150,"value":"fpc.msedge.net\/conf\/v2\/odsync2\/fpconfig.min.json"},{"id":151,"value":"pst,nst,ost"},{"id":152,"value":"*.laccdb|*.tpm|thumbs.db|EhThumbs.db|Desktop.ini|.DS_Store|Icon\\r|.lock|.849C9593-D756-4E56-8D6E-42412F2A707B"},{"id":155,"value":"pst,nst,ost"},{"id":158,"value":"1"},{"id":159,"value":"604800"},{"id":16,"value":"|one|onepkg|onetoc|onetoc2|"},{"id":160,"value":"604800"},{"id":161,"value":"1"},{"id":162,"value":"43200"},{"id":163,"value":"21600"},{"id":164,"value":"3"},{"id":165,"value":"90"},{"id":166,"value":"120"},{"id":167,"value":"15"},{"id":168,"value":"120000"},{"id":169,"value":"1.2.0.9"},{"id":17,"value":"|doc|docm|docx|odt|odp|pps|ppsm|ppsx|ppt|pptm|pptx|vsd|vsdx|ods|xls|xlsb|xlsm|xlsx|"},{"id":170,"value":"https:\/\/clients.config.office.net\/collector\/v1.0\/inventoryodb"},{"id":178,"value":"-895221759|-2147024809|-2147023508|-2147023579|-2147164433|-2147164592|-2147162950"},{"id":179,"value":"0"},{"id":18,"value":"|pst|"},{"id":180,"value":"0.01"},{"id":181,"value":"0.03"},{"id":182,"value":"3"},{"id":183,"value":"30"},{"id":184,"value":"10"},{"id":185,"value":"ar;bg;ca;cs;da;de;el;en;en-GB;en-US;es;et;eu;fi;fr;gl;he;hi;hr;hu;id;it;ja;kk;ko;lt;lv;ms;nb-NO;nl;pl;pt-BR;pt-PT;ro;ru;sk;sl;sr-Cyrl-RS;sr-Latn-RS;sv;th;tr;uk;vi;zh-CN;zh-TW;"},{"id":187,"value":"lnk|xlsx|xls|url|exe|zip|rar|rdp|appref-ms|msi|website|xlsm|xml|xlsb|pub|mht|accdb|bak|reg|mpp|ini|pbix|mdb|indd|nal|dwg|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|mov|oxps|stp|dpk"},{"id":188,"value":"1440"},{"id":189,"value":"7200000"},{"id":19,"value":"22528"},{"id":190,"value":"1800000"},{"id":191,"value":"0.05"},{"id":192,"value":"|pdf:20|accdb:20|exe:20|mp4:60|mdb:20|pst:1200|myox:15|"},{"id":195,"value":"900 "},{"id":2,"value":"0x8004de40|0x8004de42|0x8004de85|0x8004de8b|0x8004deb6|0x8004de9b|0x8004ded0|0x8004ded2|0x8004de45|0x8004de8a|0x8004ded5"},{"id":20,"value":"133120"},{"id":201,"value":"lnk|xlsx|xls|xlsb|xlsm|docx|doc|docm|pptx|pub|url|exe|zip|rar|rdp|appref-ms|msi|website|txt|msg|xml|mht|accdb|csv|wav|bak|reg|mpp|html|pst|ini|pbix|mdb|indd|nal|dwg|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|one|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|oxps|stp|dpk"},{"id":204,"value":"6|37|78|79|80|106|107|146|151|155|178|179|182|193|208|232|256|283|300|349|372|376|379|406|417|420|428|432|466|479|484|522|532|533|541|550|584|588|591|592|616|618|629|653|655|685|688|707|715|729|733|758|766|767|797|804|835|848|854|872|875|882|885|895|903|910|923|938|969|990|998|1006|1007|1009|1011|1012|1030|1040|1045|1049|1050|1087|1096|1099|1142|1147|1149|1154|1171|1194|1197|1207|1208|1209|1214|1273|1280|1288|1303|1313|1349|1366|1387|1423|1466|1507|1514|1533|1551|1602|1650|1654|1704|1708|1709|1722|1734|1741|1761|1762|1785|1787|1802|1811|1834|1835|1839|1845|1846|1856|1857|1858|1865|1867|1868|1871|1883|1892|1897|1898|1908|1910|1914|1922|1929|1937|1945|1946|1949|1984|1999|2043|2047|2052|2053|2062|2083|2094|2103|2107|2121|2125|2140|2160|2177|2180|2186|2195|2206|2216|2232|2233|2240|2251|2253|2268|2290|2303|2312|2313|2317|2328|2339|2363|2373|2395|2419|2433|2440|2447|2455|2456|2507|2553|2559|2579|2597|2601|2607|2630|2635|2648|2665|2678|2698|2705|2713|2729|2742|2760|2761|2765|2770|2772|2785|2847|2875|2887|2908|2921|2950|2992|3009|3013|3034|3054|3055|3069|3085|3097|3108|3139|3164|3171|3179|3189|3202|3210|3246|3254|19999"},{"id":205,"value":"dwg"},{"id":206,"value":"bak"},{"id":208,"value":"14"},{"id":209,"value":"0.0"},{"id":21,"value":"lnk|xlsx|xls|xlsb|xlsm|docx|doc|docm|pptx|pub|url|exe|zip|rar|rdp|appref-ms|msi|website|txt|msg|xml|mht|accdb|csv|wav|bak|reg|mpp|html|pst|ini|pbix|mdb|indd|nal|dwg|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|one|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|oxps|stp|dpk"},{"id":210,"value":"0.0"},{"id":213,"value":"20"},{"id":214,"value":"180"},{"id":216,"value":"VaultUnlockScenario:-2144272294;AddMountedFolderScenario:38;"},{"id":22,"value":"minCountForConsideration:6"},{"id":222,"value":"15"},{"id":223,"value":"Level:Request,Verbose:Rotate:1\/100;\nName:ReportChangeEnumerationTimeDelay:Rotate:1\/30;\nScenario:ThumbnailScenario,StartOCSIScenario,UploadScenario,DownloadScenario,UploadMetadataScenario,UploadMetadataBatchScenario:Rotate:1\/30;\nScenario:Upload,MetadataDownload,Download:Rotate:1\/2;\nApi:ProcessLocalChange*:Random:0.0001;\nApi:UXMacLocalization:Random:0.0001;\nName:ScenarioHeaderMissing:Rotate:1\/20;\nApi:LoggingScenarioReporting:Rotate:1\/30;\nName:StorageProviderUriSourceResult,CrossScopeMoveBytesTransferred,UpdateRingSource,StorageApiScenarioHeaderDiffersInTrace,FALDeleteCompletion,DeviceHealthScore,OOBERequestHandlerClientKFMUpsellState:Rotate:0\/1;\nName:CloudFilesApiResult:Rotate:1\/100;\nApi:SyncPerfScenario:Rotate:0\/1;\nApi:MacboxFPEnumChangesCompleteWorkingSet:Rotate:1\/10;\nApi:MacboxFPExtFALConnectionFetch,MacboxFPExtFetchComplete:Rotate:1\/2;\nApi:ReparentChildrenOfFolderInRecycleBin:Random:0.1;\nName:IdleJobExecutionDelayed:Random:0.0001;\nName:RealizerChangeInterpreterFilterBackfill:Random:0.01;\nName:UploadCxPUnableToResolveToken:Random:0.001;\nApi:MacboxUserVisibleFetch:Random:0.01;\nName:RealizerAwareChangeEnumerationStatsResult:Random:10.0;\nName:ChangeEnumerationMissingQuotaState:Random:10.0;\nFunnel:Infrastructure:Rotate:1%+1\/100;\nFunnel:hiddenRoot:Rotate:1%+1\/100;\nName:OOBERequestHandlerSyncClientSignInState:Random:0.0001;\nApi:WinboxConvertToPlaceholder:Random:1.0;\nApi:UploadCxPGetTokenFromPath:Random:1.0;\nNucleus:FonDSyncInit:Random:0.01;\nNucleus:AutoStartStatus:Random:0.01;\nNucleus:AuthAcquireTokenSilently:Random:0.25;\nStallError:NewStall_*:Random:0.1;\nApi:RetrieveProperties,getonedrivesigninstate,GetPropertyHandlerFromPath,SaveProperties,getkfmupsellstate,GetStatusUI,GetPropertyHandlerFromUri:Random:0.1;"},{"id":226,"value":"1.2.0.16"},{"id":227,"value":"1.2.1.1"},{"id":228,"value":" "},{"id":229,"value":"21.109.0530.0001"},{"id":231,"value":"lnk|xlsx|xls|xlsb|xlsm|pub|url|exe|zip|rar|rdp|appref-ms|msi|website|msg|xml|mht|accdb|csv|wav|bak|reg|mpp|pst|ini|pbix|mdb|indd|nal|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|one|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|oxps|stp|dpk"},{"id":232,"value":"lnk|xlsx|xls|xlsb|xlsm|pub|url|exe|zip|rar|rdp|appref-ms|msi|website|msg|xml|mht|accdb|csv|wav|bak|reg|mpp|pst|ini|pbix|mdb|indd|nal|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|one|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|oxps|stp|dpk"},{"id":233,"value":"2.9.7653.47581"},{"id":237,"value":"50"},{"id":238,"value":"900|300|600|900"},{"id":24,"value":"4"},{"id":240,"value":"3600"},{"id":241,"value":"10000"},{"id":243,"value":"900"},{"id":244,"value":"900"},{"id":245,"value":"P1D"},{"id":246,"value":"200000"},{"id":249,"value":"300000"},{"id":25,"value":"15"},{"id":250,"value":"20"},{"id":251,"value":"180"},{"id":252,"value":"5"},{"id":253,"value":"180"},{"id":254,"value":"1"},{"id":26,"value":"100"},{"id":269,"value":"25|26|27|29|19|10|23|30|35|14,22.235.1109.0001"},{"id":273,"value":"250000"},{"id":274,"value":"100000"},{"id":283,"value":"siteUrl|listId"},{"id":284,"value":"100,siteUrl=https?:\\\/\\\/(www\\.)?laposte\\.sharepoint\\.com\\b(.*),INF,lh-lap|100,siteUrl=.*\\s.*,24.178.0903.0001,lh-sws|100,listId=acc3ba2d-929f-41d1-aee5-4c99be7b0277,INF,ln-lh|100,listId=a0fec449-25ba-4637-97d6-57660475b73b,INF,ln-lo|100,listId=2a7093aa-c228-4672-a093-aa7f86b3e13b,INF,ln-lo"},{"id":285,"value":"ModernListTemplateTypeId|ClientFormCustomFormatter|ContentTypeIdToNameMap|isModerated|listName|FormRenderModes|EnableMinorVersions"},{"id":286,"value":"100,ModernListTemplateTypeId=3a867b4a-7429-0e1a-b02e-bf4b240ff1ce,INF,tm-pl|100,ModernListTemplateTypeId=b117a022-9f8b-002d-bda8-fa266f0ff1ce,22.176.0821.0001,tm-pro|100,ModernListTemplateTypeId=a5126f70-467d-4257-954b-95fba9bb008c,22.176.0821.0001,tm-pro|100,ModernListTemplateTypeId=3a7c53be-a128-0ff9-9f97-7b6f700ff1ce,22.176.0821.0001,tm_rec|100,ModernListTemplateTypeId=92946f48-bed9-4299-825d-dc3768f59d54,22.176.0821.0001,tm_rec|100,ModernListTemplateTypeId=9a429811-2ab5-07bc-b5a0-2de9590ff1ce,22.176.0821.0001,tm-co|100,ModernListTemplateTypeId=bd8bdab7-5730-4f57-9050-0bd66c988b15,22.176.0821.0001,tm-co|100,ContentTypeIdToNameMap=.*:.*:.*,22.055.0313.0001,ct|100,listName=.ACC3BA2D-929F-41D1-AEE5-4C99BE7B0277.,INF,ln-la|100,FormRenderModes=.*:.*:.*\"RenderType\" : 3.*,INF,frn|100,EnableMinorVersions=true,INF,emv"},{"id":287,"value":"ClientSideComponentProperties|SchemaXml|Formula|TypeAsString|InternalName"},{"id":288,"value":"100,ClientSideComponentProperties=^(?!null).*,22.002.0103.0004|100,SchemaXml=.*AppendOnly.\\\"TRUE\\\".*Type.\\\"Note\\\".*,22.222.1023.0001,notes|100,SchemaXml=.*Type.\\\"Note\\\".*AppendOnly.\\\"TRUE\\\".*,22.222.1023.0001,notes|100,Formula=.+,22.025.0202.0001,frml|100,TypeAsString=TaxonomyFieldTypeMulti,INF,tax-mlt|100,InternalName=_ApprovalStatus,INF,ap_st|100,TypeAsString=Likes,INF,rtg"},{"id":289,"value":"modernType|viewXml|query"},{"id":290,"value":"100,modernType=KANBAN,21.229.1104.0001,Kanban|100,viewXml=.*.+<\/CustomOrder>.*,INF,cu-ord|100,modernType=TILES,22.045.0227.0001,tiles|100,query=.*.*.+<\/Value><\/Eq>.*<\/Where>.*,INF,ca-fil|100,viewXml=.*.*.*<\/ViewFields>.*,INF,ms-img,ALL,FILES"},{"id":291,"value":"TimeZone_Id|RegionalSetting_Locale"},{"id":292,"value":"100,TimeZone_Id=^5[3-9],21.230.1107.0004,tz|100,TimeZone_Id=^[6-9]\\d,21.230.1107.0004,tz|100,TimeZone_Id=^\\d{3},21.230.1107.0004,tz|100,RegionalSetting_Locale=^1025|100,RegionalSetting_Locale=^1052|100,RegionalSetting_Locale=^1098|100,RegionalSetting_Locale=^1164|100,RegionalSetting_Locale=^2068|100,RegionalSetting_Locale=^6170|100,RegionalSetting_Locale=^7194|100,RegionalSetting_Locale=^8218|100,RegionalSetting_Locale=^12314|100,RegionalSetting_Locale=^102[68],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^103[47],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^104[12467],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^105[2467],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^106[2-68],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1079,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^108[0-36],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^108[89],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^109[0-79],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^110[0-8],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^111[014578],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^112[1-58],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^113[0-6],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^114[468],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^115[02-9],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^116[049],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^2049,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^20[56]8,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^207[07],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^209[24],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^210[78],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^211[057],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^2128,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^214[13],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^2155,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^307[36],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^3131,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^3179,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^4097,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^410[03],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^4106,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^4122,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^4155,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^512[147],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^513[02],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^5146,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^5179,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^6145,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^615[46],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^6170,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^6203,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^7169,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^717[78],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^7194,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^7227,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^8193,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^820[12],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^8218,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^8251,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^9217,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^922[56],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^9242,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^9275,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1024[19],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^10250,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^10266,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^11265,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1127[34],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^11290,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^12289,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1229[78],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^12314,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^13313,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1332[12],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^14337,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^14346,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^15361,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^15370,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^16385,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1639[34],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1741[78],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1844[12],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^19466,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^20490,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^21514,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1026,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1029,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1035,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1036,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1038,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1044,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1045,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1047,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1049,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1051,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1052,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1053,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1058,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1059,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1061,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1062,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1063,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1064,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1074,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1076,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1078,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1079,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1083,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1087,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1088,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1090,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1091,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1092,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1132,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1133,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1134,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1150,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1154,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1155,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1156,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1157,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1160,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2055,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2064,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2068,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2070,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2077,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2092,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2107,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2115,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2143,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^3079,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^3084,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^3131,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^4108,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^4155,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^5127,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^102[6-79],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^103[0-24-68-9],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^104[03-689],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^105[0-357-9],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^106[0-68-9],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^107[0-18-9],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^108[037-8],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^109[0-2],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^1108,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^1110,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^112[2-3],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^113[13-5],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^1146,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^115[04-79],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^116[04],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^206[07-8],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^207[07],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^209[24],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^2107,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^211[05],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^2143,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^2155,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^3079,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^308[24],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^3131,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^410[38],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^4122,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^4155,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^513[02],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^5146,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^5179,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^6156,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^6170,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^6203,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^7177,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^7194,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^7227,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^8202,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^8218,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^8251,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^9226,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^9242,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^9275,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^10266,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^11274,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^11290,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^12298,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^12314,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^13322,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^14346,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^15370,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^16394,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^102[679],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^103[02578],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^104[4-689],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^105[014578],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^106[1-3689],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^1071,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^108[167],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^1106,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^1110,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^1152,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^2049,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^2070,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^2108,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^2110,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^3073,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^4097,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^4122,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^5121,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^5146,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^6145,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^7169,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^8193,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^9217,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^9242,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^10241,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^10266,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^11265,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^11290,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^12289,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^13313,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^14337,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^15361,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^16385,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^16393,22.040.0220.0001,frmt|100,RegionalSetting_Locale=^1029,INF,alt-sep|100,RegionalSetting_Locale=^1042,INF,dis-loc"},{"id":294,"value":"604800"},{"id":297,"value":"ctxId|tick|expirationDateTime|ClientForms|notificationUrl|subscribeID|lastItemModifiedTime|PageContextInfo"},{"id":30,"value":"30"},{"id":302,"value":"60"},{"id":303,"value":"0"},{"id":304,"value":"&CallerScenarioId={Scenario}&CallerId={Caller}"},{"id":305,"value":"8192"},{"id":306,"value":"2"},{"id":309,"value":"Linear"},{"id":310,"value":"2"},{"id":311,"value":"2"},{"id":318,"value":"500"},{"id":320,"value":"65535"},{"id":321,"value":"600000"},{"id":322,"value":"2"},{"id":323,"value":"5"},{"id":324,"value":"30"},{"id":325,"value":"22.012.0116.0001"},{"id":329,"value":"100"},{"id":330,"value":"0x8004da9a|0x8004da12|0x8004da17"},{"id":331,"value":"|db:60|package:60|db-wal:60|accdb:30|log:30|txt:30|"},{"id":334,"value":"RuntimeBroker.exe"},{"id":36,"value":"40"},{"id":37,"value":"4096"},{"id":38,"value":"10240"},{"id":39,"value":"5120"},{"id":40,"value":"133120"},{"id":41,"value":"|pst|"},{"id":42,"value":"|pst|"},{"id":43,"value":"|one|onepkg|onetoc|onetoc2|"},{"id":45,"value":"200"},{"id":46,"value":"18.168.0820.0001"},{"id":47,"value":"18.168.0820.0001"},{"id":48,"value":"100"},{"id":49,"value":"1534956090"},{"id":5,"value":"0"},{"id":51,"value":"7200 "},{"id":52,"value":"7200"},{"id":53,"value":"2 "},{"id":538,"value":"0,Etc\/UTC|1,Etc\/GMT|2,Europe\/London|3,Europe\/Paris|4,Europe\/Berlin|5,Europe\/Bucharest|6,Europe\/Budapest|7,Europe\/Minsk|8,America\/Sao_Paulo|9,America\/Halifax|10,America\/New_York|11,America\/Chicago|12,America\/Denver|13,America\/Los_Angeles|14,America\/Anchorage|15,Pacific\/Honolulu|16,Pacific\/Apia|17,Pacific\/Auckland|18,Australia\/Brisbane|19,Australia\/Adelaide|20,Asia\/Tokyo|21,Asia\/Singapore|22,Asia\/Bangkok|23,Asia\/Calcutta|24,Asia\/Dubai|25,Asia\/Tehran|26,Asia\/Baghdad|27,Asia\/Jerusalem|28,America\/St_Johns|29,Atlantic\/Azores|30,Etc\/GMT+2|31,Atlantic\/Reykjavik|32,America\/Cayenne|33,America\/La_Paz|34,America\/Indianapolis|35,America\/Bogota|36,America\/Regina|37,America\/Mexico_City|38,America\/Phoenix|39,Etc\/GMT+12|40,Pacific\/Fiji|41,Pacific\/Guadalcanal|42,Australia\/Hobart|43,Pacific\/Port_Moresby|44,Australia\/Darwin|45,Asia\/Shanghai|46,Asia\/Novosibirsk|47,Asia\/Tashkent|48,Asia\/Kabul|49,Africa\/Cairo|50,Africa\/Johannesburg|51,Europe\/Moscow|53,Atlantic\/Cape_Verde|54,Asia\/Baku|55,America\/Guatemala|56,Africa\/Nairobi|57,Europe\/Warsaw|58,Asia\/Yekaterinburg|59,Europe\/Kiev|60,America\/Godthab|61,Asia\/Rangoon|62,Asia\/Katmandu|63,Asia\/Irkutsk|64,Asia\/Krasnoyarsk|65,America\/Santiago|66,Asia\/Colombo|67,Pacific\/Tongatapu|68,Asia\/Vladivostok|69,Africa\/Lagos|70,Asia\/Yakutsk|71,Asia\/Almaty|72,Asia\/Seoul|73,Australia\/Perth|74,Asia\/Riyadh|75,Asia\/Taipei|76,Australia\/Sydney|77,America\/Chihuahua|78,America\/Tijuana|79,Asia\/Amman|80,Asia\/Beirut|81,America\/Cuiaba|82,Asia\/Tbilisi|83,Africa\/Windhoek|84,Asia\/Yerevan|85,America\/Buenos_Aires|86,Africa\/Casablanca|87,Asia\/Karachi|88,America\/Caracas|89,Indian\/Mauritius|90,America\/Montevideo|91,America\/Asuncion|92,Asia\/Kamchatka|93,Etc\/UTC|94,Asia\/Ulaanbaatar|95,Etc\/GMT+11|96,Etc\/GMT+2|97,Etc\/GMT-12|98,Asia\/Damascus|99,Asia\/Magadan|100,Europe\/Kaliningrad|101,Europe\/Istanbul|102,Asia\/Dhaka|103,America\/Bahia|104,Europe\/Chisinau|106,Europe\/Samara|107,Asia\/Srednekolymsk|108,Asia\/Kamchatka|109,Europe\/Minsk|110,Europe\/Astrakhan|111,Asia\/Barnaul|112,Asia\/Tomsk|114,Asia\/Sakhalin|115,Asia\/Omsk"},{"id":539,"value":"5121|15361|3073|2049|11265|13313|12289|4097|6145|8193|16385|1025|10241|7169|14337|9217|1068|1069|8218|5146|1026|1027|2052|3076|5124|4100|1028|4122|1050|1029|1030|1164|2067|1043|3081|10249|4105|9225|16393|6153|8201|17417|5129|13321|18441|7177|11273|2057|1033|12297|1061|1035|2060|3084|1036|5132|6156|4108|1110|3079|1031|5127|4103|2055|1032|1037|1081|1038|1057|2108|1040|2064|1041|1087|1042|1062|1063|1071|1086|2110|1044|2068|1045|1046|2070|1048|1049|7194|12314|10266|6170|11290|9242|1051|11274|16394|13322|9226|5130|7178|12298|17418|4106|18442|2058|19466|6154|15370|10250|20490|1034|3082|21514|14346|8202|1053|2077|1054|1055|1058|1066|1106"},{"id":540,"value":"1093|2052|3076|5124|4100|1028|1095|1081|1041|1099|1111|1102|1096|1103|1097|1098|1152|1042"},{"id":541,"value":"1052|1118|1101|2117|1093|2052|4100|1028|1164|1125|3081|4105|9225|16393|6153|8201|17417|5129|13321|18441|11273|2057|1033|1124|1032|1095|1037|1081|2141|1117|1041|1099|1158|1111|1042|1086|2110|1100|1153|1102|1148|1121|1096|1065|1094|1131|3179|1103|9226|7178|2058|6154|20490|21514|14346|8202|1114|1097|1098|1054|1056|1152|1066|1144|5121|15361|3073|2049|11265|13313|12289|4097|6145|8193|16385|1025|10241|7169|14337|9217"},{"id":543,"value":"2067=%d %B|1043=%d %B|2052=%m月%dę—„|3076=%m月%dę—„|5124=%m月%dę—„|4100=%m月%dę—„|1028=%m月%dę—„|1053=den %d %B|2077=den %d %B|2060=%d %B|3084=%d %B|1036=%d %B|5132=%d %B|6156=%d %B|4108=%d %B|3079=%d. %B|1031=%d. %B|5127=%d. %B|4103=%d. %B|2055=%d. %B|1040=%d %B|2064=%d %B|1041=%m月%dę—„|1042=%B %dģ¼|1049=%d %B|11274=%d de %B|16394=%d de %B|13322=%d de %B|9226=%d de %B|5130=%d de %B|7178=%d de %B|12298=%d de %B|17418=%d de %B|4106=%d de %B|18442=%d de %B|2058=%d de %B|19466=%d de %B|6154=%d de %B|15370=%d de %B|10250=%d de %B|20490=%d de %B|1034=%d de %B|3082=%d de %B|21514=%d de %B|14346=%d de %B|8202=%d de %B|2070=%d de %B|1046=%d de %B|1037=%d %B|1030=%d. %B|1044=%d. %B|1048=%d %B|5121=%d %B|15361=%d %B|3073=%d %B|2049=%d %B|11265=%d %B|13313=%d %B|12289=%d %B|4097=%d %B|6145=%d %B|8193=%d %B|16385=%d %B|10241=%d %B|7169=%d %B|14337=%d %B|9217=%d %B|1068=%d %B|1069=%B %d|8218=%d. %B|5146=%d. %B|1026=%d %B|1027=%d %B|4122=%d. %B|1050=%d. %B|1029=%d. %B|1061=%d. %B|1035=%d. %Bta|1110=%d de %B|1032=%d %B|1081=%d %B|1038=%B %d.|1057=%d %B|2108=%d %B|1062=%d. %B|1071=%d %B|2110=%d %B|1086=%d %B|2068=%d. %B|1045=%d %B|7194=%d. %B|12314=%d. %B|10266=%d. %B|6170=%d. %B|11290=%d. %B|9242=%d. %B|1051=%d. %B|1054=%d %B|1055=%d %B|1058=%d %B|1066=%d %B|1106=%B %d|1087=%d %B|1063=%B %d d."},{"id":544,"value":"2067=%d %B %Y|1043=%d %B %Y|2052=%y幓%m月%dę—„|3076=%y幓%m月%dę—„|5124=%y幓%m月%dę—„|4100=%y幓%m月%dę—„|1028=%y幓%m月%dę—„|1053=den %d %B %Y|2077=den %d %B %Y|2060=%d %B %Y|3084=%d %B %Y|1036=%d %B %Y|5132=%d %B %Y|6156=%d %B %Y|4108=%d %B %Y|3079=%d.%m.%Y|1031=%d.%m.%Y|5127=%d.%m.%Y|4103=%d.%m.%Y|2055=%d.%m.%Y|1040=%d %B %Y|2064=%d %B %Y|1041=%Y幓%Om月%dę—„|1042=%Yė…„ %mģ›” %dģ¼|1049=%d.%m.%Y|11274=%d\/%m\/%Y|16394=%d\/%m\/%Y|13322=%d-%m-%Y|9226=%d\/%m\/%Y|5130=%d\/%m\/%Y|7178=%d\/%m\/%Y|12298=%d\/%m\/%Y|17418=%d\/%m\/%Y|4106=%d\/%m\/%Y|18442=%d\/%m\/%Y|2058=%d\/%m\/%Y|19466=%d\/%m\/%Y|6154=%m\/%d\/%Y|15370=%d\/%m\/%Y|10250=%d\/%m\/%Y|20490=%m\/%d\/%Y|1034=%d\/%m\/%Y|3082=%d\/%m\/%Y|21514=%m\/%d\/%Y|14346=%d\/%m\/%Y|8202=%d\/%m\/%Y|2070=%d\/%m\/%Y|1046=%d de %B de %Y|1037=%d %B %Y|1030=%d. %B %Y|1044=%d. %B %Y|1048=%d %B %Y|5121=%d-%m-%Y|15361=%d\/%m\/%Y|3073=%d\/%m\/%Y|2049=%d\/%m\/%Y|11265=%d\/%m\/%Y|13313=%d\/%m\/%Y|12289=%d\/%m\/%Y|4097=%d\/%m\/%Y|6145=%d-%m-%Y|8193=%d\/%m\/%Y|16385=%d\/%m\/%Y|10241=%d\/%m\/%Y|7169=%d-%m-%Y|14337=%d\/%m\/%Y|9217=%d\/%m\/%Y|1068=%d %B %Y|1069=%Y\/%m\/%d|8218=%d. %B %Y|5146=%d. %B %Y|1026=%d %B %Y г.|1027=%d\/%m\/%Y|4122=%d. %B %Y.|1050=%d. %B %Y.|1029=%d.%m.%Y|1061=%d. %B %Y|1035=%d.%m.%Y|1110=%d\/%m\/%Y|1032=%d %B %Y|1081=%d %B %Y|1038=%B %d., %Y|1057=%d %B %Y|2108=%d %B, %Y|1062=%Y. gada %d. %B|1071=%d %B %Y|2110=%d %B %Y|1086=%d %B %Y|2068=%d. %B %Y|1045=%d %B %Y|7194=%d. %B %Y|12314=%d. %B %Y|10266=%d. %B %Y|6170=%d. %B %Y|11290=%d. %B %Y|9242=%d. %B %Y|1051=%d. %m. %Y|1054=%d %B %Y|1055=%d %B %Y|1058=%d %B %Y р.|1066=%d %B %Y|1106=%B %d %Y|1087=%d %B %Y ж.|1063=%Y m. %B %d d."},{"id":547,"value":"https:\/\/clients.config.office.net\/user\/v1.0\/tenantassociationkey"},{"id":549,"value":"43200"},{"id":550,"value":"3600"},{"id":551,"value":"30"},{"id":552,"value":"25.0"},{"id":553,"value":"600"},{"id":556,"value":"16393=%I.%M %p"},{"id":560,"value":"1045=stycznia;lutego;marca;kwietnia;maja;czerwca;lipca;sierpnia;września;paÅŗdziernika;listopada;grudnia|1049=ŃŠ½Š²Š°Ń€Ń;Ń„ŠµŠ²Ń€Š°Š»Ń;марта;Š°ŠæŃ€ŠµŠ»Ń;Š¼Š°Ń;ŠøŃŽŠ½Ń;ŠøŃŽŠ»Ń;Š°Š²Š³ŃƒŃŃ‚Š°;ŃŠµŠ½Ń‚ŃŠ±Ń€Ń;Š¾ŠŗŃ‚ŃŠ±Ń€Ń;Š½Š¾ŃŠ±Ń€Ń;Š“ŠµŠŗŠ°Š±Ń€Ń|5121=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|2049=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|11265=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|12289=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|6145=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|10241=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|7169=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|1068=yanvar;fevral;mart;aprel;may;iyun;iyul;avqust;sentyabr;oktyabr;noyabr;dekabr|5146=januar;februar;mart;april;maj;juni;juli;avgust;septembar;oktobar;novembar;decembar|1027=de gener;de febrer;de marƧ;d’abril;de maig;de juny;de juliol;d’agost;de setembre;d’octubre;de novembre;de desembre|4122=siječnja;veljače;ožujka;travnja;svibnja;lipnja;srpnja;kolovoza;rujna;listopada;studenoga;prosinca|1050=siječnja;veljače;ožujka;travnja;svibnja;lipnja;srpnja;kolovoza;rujna;listopada;studenog;prosinca|1029=ledna;Ćŗnora;března;dubna;května;června;července;srpna;zÔří;října;listopadu;prosince|1032=Ιανουαρίου;Φεβρουαρίου;ĪœĪ±ĻĻ„ĪÆĪæĻ…;Απριλίου;ĪœĪ±ĪĪæĻ…;Ιουνίου;Ιουλίου;Ī‘Ļ…Ī³ĪæĻĻƒĻ„ĪæĻ…;Σεπτεμβρίου;ĪŸĪŗĻ„Ļ‰Ī²ĻĪÆĪæĻ…;ĪĪæĪµĪ¼Ī²ĻĪÆĪæĻ…;Δεκεμβρίου|1087=қаңтар;ақпан;Š½Š°ŃƒŃ€Ń‹Š·;сәуір;мамыр;Š¼Š°ŃƒŃŃ‹Š¼;ŃˆŃ–Š»Š“Šµ;тамыз;қыркүйек;қазан;Ņ›Š°Ń€Š°ŃˆŠ°;желтоқсан|1063=sausio;vasario;kovo;balandžio;gegužės;birželio;liepos;rugpjūčio;rugsėjo;spalio;lapkričio;gruodžio|1051=januĆ”ra;februĆ”ra;marca;aprĆ­la;mĆ”ja;jĆŗna;jĆŗla;augusta;septembra;októbra;novembra;decembra|1058=ŃŃ–Ń‡Š½Ń;Š»ŃŽŃ‚Š¾Š³Š¾;Š±ŠµŃ€ŠµŠ·Š½Ń;ŠŗŠ²Ń–Ń‚Š½Ń;Ń‚Ń€Š°Š²Š½Ń;Ń‡ŠµŃ€Š²Š½Ń;Š»ŠøŠæŠ½Ń;ŃŠµŃ€ŠæŠ½Ń;Š²ŠµŃ€ŠµŃŠ½Ń;Š¶Š¾Š²Ń‚Š½Ń;листопаГа;Š³Ń€ŃƒŠ“Š½Ń|8218=januar;februar;mart;april;maj;juni;juli;avgust;septembar;oktobar;novembar;decembar|1164=January;February;March;April;May;June;July;August;September;October;November;December|7194=Ń˜Š°Š½ŃƒŠ°Ń€;Ń„ŠµŠ±Ń€ŃƒŠ°Ń€;март;април;мај;јун;јул;Š°Š²Š³ŃƒŃŃ‚;септембар;октобар;новембар;Гецембар|12314=Ń˜Š°Š½ŃƒŠ°Ń€;Ń„ŠµŠ±Ń€ŃƒŠ°Ń€;март;април;мај;јун;јул;Š°Š²Š³ŃƒŃŃ‚;септембар;октобар;новембар;Гецембар"},{"id":561,"value":"{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_1193|{A3451E43-72DF-4DEE-BFFF-54DD4F76B889}_2222336362|{5B0C1EDE-DB41-41FE-98F2-17FF342847AD}_10201020|{5B0C1EDE-DB41-41FE-98F2-17FF342847AD}_1097|{A3451E43-72DF-4DEE-BFFF-54DD4F76B889}_2046313181|{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_3165353945|{5B0C1EDE-DB41-41FE-98F2-17FF342847AD}_1063|{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_1839700279"},{"id":562,"value":"0.0"},{"id":563,"value":"1052=e paradites;e pasdites|1098=ą°Ŗą±‚ą°°ą±ą°µą°¾ą°¹ą±ą°Ø;ą°…ą°Ŗą°°ą°¾ą°¹ą±ą°Ø"},{"id":564,"value":"8218=nedjelja;ponedjeljak;utorak;srijeda;četvrtak;petak;subota|1164=Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday|2068=sĆøndag;mandag;tirsdag;onsdag;torsdag;fredag;lĆørdag|7194=неГеља;понеГељак;ŃƒŃ‚Š¾Ń€Š°Šŗ;среГа;четвртак;петак;ŃŃƒŠ±Š¾Ń‚Š°|12314=неГеља;понеГељак;ŃƒŃ‚Š¾Ń€Š°Šŗ;среГа;четвртак;петак;ŃŃƒŠ±Š¾Ń‚Š°|6170=nedelja;ponedeljak;utorak;sreda;četvrtak;petak;subota|11290=nedelja;ponedeljak;utorak;sreda;četvrtak;petak;subota"},{"id":566,"value":"a5b7be8e-ef1e-404f-8930-3e88ea835d61|08485f1b-716b-48da-b475-1fae43ade4e0|2e394c55-0b61-4557-9062-e5a9677a9739"},{"id":567,"value":"8"},{"id":568,"value":"100,2"},{"id":57,"value":"200 "},{"id":572,"value":"RUS|BLR|"},{"id":575,"value":"850:650"},{"id":576,"value":"10"},{"id":577,"value":"0.01"},{"id":578,"value":"100000"},{"id":579,"value":"998"},{"id":58,"value":"5120"},{"id":580,"value":"50000"},{"id":582,"value":"Lists\/GetItemById\/Recycle|GetFolderById\/Recycle|SP.MoveCopyUtil.MoveFolderByPath|SP.MoveCopyUtil.MoveFileByPath|GetCopyJobProgress|GetFileByServerRelativePath\/CheckOut|GetFileByServerRelativePath\/CheckIn|GetFileByServerRelativePath\/UndoCheckOut|GetList\/Items\/ValidateUpdateFetchListItem"},{"id":583,"value":"25.0"},{"id":584,"value":"102400"},{"id":585,"value":"10240"},{"id":586,"value":"51200"},{"id":587,"value":"1.5"},{"id":588,"value":"10240"},{"id":589,"value":"2000"},{"id":59,"value":"64"},{"id":590,"value":"12000"},{"id":591,"value":"3600"},{"id":592,"value":"102400"},{"id":593,"value":"102400"},{"id":594,"value":"102400"},{"id":595,"value":"204800"},{"id":596,"value":"204800"},{"id":599,"value":"120"},{"id":60,"value":"172800"},{"id":601,"value":"10"},{"id":602,"value":"120"},{"id":603,"value":"20"},{"id":604,"value":"2"},{"id":607,"value":"22.217.1016"},{"id":608,"value":"9"},{"id":609,"value":"0"},{"id":61,"value":"350000"},{"id":610,"value":"0.00001"},{"id":611,"value":"0.0000001"},{"id":614,"value":"[\n{\"Req\": 1, \"Len\": 600, \"MC\": 960},\n{\"Req\": 3, \"Len\": 600, \"MC\": 480},\n{\"Req\": 4, \"Len\": 60, \"MC\": 180},\n{\"Req\": 11, \"Len\": 1800, \"MC\": 480},\n{\"Req\": 21, \"Len\": 60, \"MC\": 180}\n]"},{"id":615,"value":"50000"},{"id":616,"value":"50000"},{"id":617,"value":"32"},{"id":62,"value":"403"},{"id":620,"value":"3"},{"id":621,"value":"24"},{"id":625,"value":"7200000"},{"id":628,"value":"0.001"},{"id":635,"value":"2b0b9539-e749-436c-aa61-bd12acc9085d 2b0b9539e749436caa61bd12acc9085d_RNBoolSettingChanged|2b0b9539-e749-436c-aa61-bd12acc9085d 2b0b9539e749436caa61bd12acc9085d_RNNetworkSettingsChanged|2b0b9539-e749-436c-aa61-bd12acc9085d 2b0b9539e749436caa61bd12acc9085d_RNVaultSettingChanged|22bcab81-4b4c-4e52-81ac-cb41e0d8aa72 22bcab814b4c4e5281accb41e0d8aa72_OneDriveStorageProviderHandlerAPI|fa07b02c-55e1-4561-902c-e03204cc93e6 fa07b02c55e14561902ce03204cc93e6_OOBERequestHandlerClientEligibilityState|1d80fd3d-7eea-4a76-85b5-5ed80cd8275f 1d80fd3d7eea4a7685b55ed80cd8275f_KFMSilentFlowLauncherGPOState|fa07b02c-55e1-4561-902c-e03204cc93e6 fa07b02c55e14561902ce03204cc93e6_OOBERequestHandlerSetPreference|1d80fd3d-7eea-4a76-85b5-5ed80cd8275f 1d80fd3d7eea4a7685b55ed80cd8275f_SilentMoveControllerFlowComplete"},{"id":636,"value":"[{\"Req\":1,\"Cap\":8,\"NT\":8,\"P\":5000,\"RP\":300,\"T\":5},\n{\"Req\":3,\"Cap\":8,\"NT\":8,\"P\":10000,\"RP\":300,\"T\":5},\n{\"Req\":4,\"Cap\":3,\"NT\":3,\"P\":1000,\"RP\":300,\"T\":5},\n{\"Req\":11,\"Cap\":4,\"NT\":4,\"P\":15000,\"RP\":300,\"T\":5},\n{\"Req\":21,\"Cap\":3,\"NT\":3,\"P\":1000,\"RP\":300,\"T\":5}]"},{"id":639,"value":"5000"},{"id":643,"value":"168"},{"id":65,"value":"200"},{"id":652,"value":"86400"},{"id":653,"value":"7200"},{"id":656,"value":"300000"},{"id":657,"value":"150000"},{"id":66,"value":"60 "},{"id":67,"value":"60 "},{"id":670,"value":"31614,31617,31610"},{"id":671,"value":"31618,31609,31610"},{"id":672,"value":"1"},{"id":674,"value":"10560"},{"id":676,"value":"TypeG,TypeG,TypeG,false"},{"id":680,"value":"3,60000,300000"},{"id":681,"value":"5.0"},{"id":682,"value":"50000"},{"id":688,"value":"86400"},{"id":69,"value":"401Retry|OfficeConversion_NotSupported|BadArgument_CantGenerateThumbnail|FileTooLarge|OfficeConversion_RegionNotSupported|503Retry"},{"id":690,"value":"86400"},{"id":694,"value":"86400"},{"id":695,"value":"5"},{"id":698,"value":"5"},{"id":7,"value":"0x80080300|0x80070102|0x800704cf|0x00000102|0x80070002|0xcaa20005|0xcaa20008"},{"id":70,"value":"400 "},{"id":701,"value":"86400"},{"id":71,"value":"120 "},{"id":721,"value":"3600000"},{"id":723,"value":"1440"},{"id":726,"value":"5"},{"id":727,"value":"5"},{"id":729,"value":"30"},{"id":730,"value":"2,100"},{"id":731,"value":"2"},{"id":740,"value":"BlueCloudCritical_Win11.svg,1"},{"id":744,"value":"TypeG,TypeG,TypeG,false,RequireNoMSAPresent"},{"id":751,"value":"10080"},{"id":753,"value":"120"},{"id":757,"value":"1"},{"id":759,"value":"120"},{"id":760,"value":"1440"},{"id":761,"value":"2000 "},{"id":769,"value":"30000"},{"id":770,"value":"1,0"},{"id":772,"value":"5000 "},{"id":773,"value":"2621440 "},{"id":774,"value":"2621440 "},{"id":775,"value":"5242880 "},{"id":78,"value":"900"},{"id":780,"value":"3600"},{"id":781,"value":"120"},{"id":782,"value":"60"},{"id":787,"value":"0,1"},{"id":789,"value":"{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_1719712948|{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_2367113984"},{"id":79,"value":"30"},{"id":791,"value":"86400"},{"id":794,"value":"1"},{"id":796,"value":"86400"},{"id":797,"value":"0.03"},{"id":798,"value":"0.03"},{"id":799,"value":"0.09"},{"id":80,"value":"1296000"},{"id":800,"value":"0.09"},{"id":802,"value":"120"},{"id":803,"value":"Survey"},{"id":808,"value":"60"},{"id":81,"value":"10"},{"id":813,"value":"1,0"},{"id":82,"value":"120"},{"id":820,"value":"9000"},{"id":828,"value":"7"},{"id":829,"value":"3"},{"id":83,"value":"21600"},{"id":830,"value":"720"},{"id":832,"value":"300"},{"id":833,"value":"2100"},{"id":84,"value":"19.131.0704.0007"},{"id":844,"value":"50000"},{"id":85,"value":"05a0e69a-418a-47c1-9c25-9387261bf991|"},{"id":86,"value":"5 "},{"id":863,"value":"250000"},{"id":865,"value":"0.001"},{"id":866,"value":"0.1"},{"id":867,"value":"0.1"},{"id":87,"value":"10 "},{"id":872,"value":"100"},{"id":873,"value":"0.03"},{"id":874,"value":"0.03"},{"id":875,"value":"20"},{"id":876,"value":"https:\/\/clients.config.office.net\/odb\/v1.0\/synchealth"},{"id":88,"value":"Antler"},{"id":880,"value":"50"},{"id":881,"value":"10"},{"id":89,"value":"86400 "},{"id":90,"value":"1"},{"id":91,"value":"10000 "},{"id":93,"value":"604800"},{"id":96,"value":"GetSignature_HighFrequency,OpenUploadSession_HighFrequency,OpenUploadSession,GetSignature_FrequencyBackoff,OpenUploadSession_FrequencyBackoff,UploadBatch,DownloadBlock,InlineBatchUpload_FrequencyBackoff,DiffInlineUploadBatch_FrequencyBackoff"}]} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/Update/update.xml b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/Update/update.xml new file mode 100644 index 00000000..dea9ae81 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/Update/update.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/decom_data.raw b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/decom_data.raw new file mode 100644 index 00000000..b828c045 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/decom_data.raw differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/FileCoAuth-2024-09-23.1347.15868.1.odl b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/FileCoAuth-2024-09-23.1347.15868.1.odl new file mode 100644 index 00000000..47cbefef Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/FileCoAuth-2024-09-23.1347.15868.1.odl differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/telemetry-dll-ramp-value.txt b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/telemetry-dll-ramp-value.txt new file mode 100644 index 00000000..e458db22 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/telemetry-dll-ramp-value.txt @@ -0,0 +1,2 @@ +3 +0,3,2,0,0 \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/telemetryCache.otc b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/telemetryCache.otc new file mode 100644 index 00000000..4e24e71e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Common/telemetryCache.otc differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/Nucleus-2024-09-23.1347.21800.1.odl b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/Nucleus-2024-09-23.1347.21800.1.odl new file mode 100644 index 00000000..b47cfe0e Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/Nucleus-2024-09-23.1347.21800.1.odl differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/microsoftNucleusTelemetryCache.otc b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/microsoftNucleusTelemetryCache.otc new file mode 100644 index 00000000..235a0634 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/microsoftNucleusTelemetryCache.otc differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/telemetry-dll-ramp-value.txt b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/telemetry-dll-ramp-value.txt new file mode 100644 index 00000000..f0e03ed3 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/ListSync/Business1/telemetry-dll-ramp-value.txt @@ -0,0 +1,2 @@ +3 +1,3,2,1,0 \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/FeedbackHub/SubmissionPayload.json b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/FeedbackHub/SubmissionPayload.json new file mode 100644 index 00000000..1751ab91 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/FeedbackHub/SubmissionPayload.json @@ -0,0 +1 @@ +{"AccountType" : "Personal","OneDriveDeviceId" : "1c9a7e98-36bc-8b5a-f67a-85aa0b849694"} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncDiagnostics.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncDiagnostics.log new file mode 100644 index 00000000..862e5ed9 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncDiagnostics.log @@ -0,0 +1,126 @@ +Sync Diagnostics - Sync Progress +SyncProgressState: 16777216 + +================================================================================ +Diagnostic Report +UtcNow: 2024-09-23T13:49:20.0000000Z + +BytesDownloaded = 0 +BytesToDownload = 0 +BytesToUpload = 0 +BytesUploaded = 0 +ChangesToProcess = 0 +ChangesToSend = 0 +DownloadSpeedBytesPerSec = 0 +EstTimeRemainingInSec = 0 +FilesToDownload = 0 +FilesToUpload = 0 +OfficeSyncActive = 0 +OfficeSyncEnabled = 0 +SymLinkCount = 0 +UploadSpeedBytesPerSec = 0 +activeHydrations = 0 +appId = 77 +bytesAvailableOnDiskDrive = 227068833792 +cid = 5bb92615fd01a69c +clientType = Win32 +clientVersion = 24.175.0830.0001 +conflictsFailed = 0 +conflictsHandled = 0 +cpuPercentage = -1 +cpuTimeSecs = 3 +currentPrivateWorkingSetKB = 80176 +datVersion = 54 +dehydrations = 0 +device = ***** +deviceID = 1c9a7e98-36bc-8b5a-f67a-85aa0b849694 +diskFlushOpsDelta = -1 +diskReadBytesDelta = -1 +diskReadOpsDelta = -1 +diskWriteBytesDelta = -1 +diskWriteOpsDelta = -1 +driveChangesToSend = 0 +driveSentChanges = 0 +drivesChangeEnumPending = 0 +drivesConnected = 1 +drivesScanRequested = 0 +drivesWaitingForInitialSync = 0 +env = Production +errorFromGetDiskSizeAPICall = 0 +failedBytesDownloadedTotal = 0 +failedBytesUploadedTotal = 0 +files = 43 +filesToDownload = 0 +flavor = ship +folders = 11 +fullScanCount = 1 +instanceID = b7806ecb-ed47-4e33-8ce1-629d0a9d3744 +invalidatedScanCount = 0 +isMsftInternal = 0 +numAbortedMissingServerChanges = 0 +numAbortedNoLongerIdle = 0 +numAbortedReSyncNeeded = 0 +numAbortedUnexpectedHttpStatus = 0 +numAbortedWatcherEtagDifference = 0 +numDeleteConvToUnmap = 0 +numDownloadErrorsReported = 0 +numDrives = 1 +numDrivesNeedingEventualScan = 0 +numExternalFileUploads = 0 +numFileDownloads = 0 +numFileFailedDownloads = 0 +numFileFailedUploads = 0 +numFileInWarning = 0 +numFileUploads = 0 +numHashMismatchErrorsReported = 0 +numLcChangeFile = 0 +numLcChangeFolder = 0 +numLcCreateFile = 43 +numLcCreateFolder = 11 +numLcDeleteFile = 0 +numLcDeleteFolder = 0 +numLcMoveFile = 0 +numLcMoveFolder = 0 +numLocalChanges = 0 +numProcessors = 4 +numRealizerErrorsReported = 0 +numResyncs = 0 +numSelSyncDrives = 0 +numUploadErrorsReported = 0 +officeVersion = 16.0.17928.20156 +officeVersionDot = 0 +originator = e924b985-1386-4817-b0c3-6500db687d6e +passiveHydrations = 0 +pid = 7960 +placeholdersEnabled = 1 +preciseScanCount = 3 +privateWorkingSetKB = 80176 +privateWorkingSetKBIncreaseDuringSyncVerification = 0 +processPrivateCommitKB = -1 +processVirtualMemoryUsedKB = -1 +scanState = 1 +scanStateStallDetected = 0 +seOfficeFiles = 0 +seOfficeFilesToDownload = 0 +seOfficeFilesToUpload = 0 +successfulBytesDownloadedTotal = 0 +successfulBytesUploadedTotal = 0 +syncProgressState = 16777216 +syncStallDetected = 0 +sync_progress_id = db4f17f7-6e1b-4156-b0b5-1a60b3b7eb57 +threadCount = 58 +timeUtc = 2024-09-23T13:49:20.0000000Z +totalDoScanWorkCpuTimeInMs = 450 +totalDuration = -1 +totalInvalidatedScanCpuTimeInMs = 0 +totalProcessCpuTime = -1 +totalScanCpuTimeInMs = 7378697629407410 +totalSizeOfDiskDrive = 479494754304 +totalSubScopes = 2 +uptimeSecs = 55 +userOverriddenConcurrentUploads = 0 +username = ***** +vaultState = 2 +version = 505 +wasFileDBReset = 0 + diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1347.19172.1.odlsent b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1347.19172.1.odlsent new file mode 100644 index 00000000..1c633893 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1347.19172.1.odlsent differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.19172.2.odlsent b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.19172.2.odlsent new file mode 100644 index 00000000..23cbaf69 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.19172.2.odlsent differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.1.odlsent b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.1.odlsent new file mode 100644 index 00000000..b6991b25 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.1.odlsent differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.2.odlgz b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.2.odlgz new file mode 100644 index 00000000..e9249296 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.2.odlgz differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.3.odlgz b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.3.odlgz new file mode 100644 index 00000000..89e1cf0d Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.3.odlgz differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.4.odlgz b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.4.odlgz new file mode 100644 index 00000000..ccac626b Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.4.odlgz differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.5.odlgz b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.5.odlgz new file mode 100644 index 00000000..c79853be Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.5.odlgz differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.6.odlgz b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.6.odlgz new file mode 100644 index 00000000..1bcec8c6 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1348.7960.6.odlgz differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1349.7960.7.aodl b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1349.7960.7.aodl new file mode 100644 index 00000000..9c212387 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/SyncEngine-2024-09-23.1349.7960.7.aodl differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/general.keystore b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/general.keystore new file mode 100644 index 00000000..b3c68aeb --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/general.keystore @@ -0,0 +1 @@ +[{"CreatedTime" : 1727099289,"Key" : "w77qU9tCy4Hsdd5\/VPgdIhhhx+LFre+qtv0o96p9nG0=\u0000\u0000","Version" : 1}] \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/telemetry-dll-ramp-value.txt b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/telemetry-dll-ramp-value.txt new file mode 100644 index 00000000..2bc7851d --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/telemetry-dll-ramp-value.txt @@ -0,0 +1,2 @@ +3 +0,3,2,1,1 \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/telemetryCache.otc b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/telemetryCache.otc new file mode 100644 index 00000000..60e37fe5 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/logs/Personal/telemetryCache.otc differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/NTUSER.DAT b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/NTUSER.DAT new file mode 100644 index 00000000..d54193cf Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/NTUSER.DAT differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1348.7960.1.odlsent b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1348.7960.1.odlsent new file mode 100644 index 00000000..b6991b25 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1348.7960.1.odlsent differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1348.7960.4.odlgz b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1348.7960.4.odlgz new file mode 100644 index 00000000..ccac626b Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1348.7960.4.odlgz differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1349.7960.7.aodl b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1349.7960.7.aodl new file mode 100644 index 00000000..9c212387 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngine-2024-09-23.1349.7960.7.aodl differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngineDatabase.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngineDatabase.db new file mode 100644 index 00000000..810df17c Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/SyncEngineDatabase.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/UBF8T346G9.OneDriveStandaloneSuite.plist b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/UBF8T346G9.OneDriveStandaloneSuite.plist new file mode 100644 index 00000000..ae496cf2 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/UBF8T346G9.OneDriveStandaloneSuite.plist @@ -0,0 +1,142 @@ + + + + + (16777229,7670709) + 27368839 + (16777230,7670709) + 30719758 + (16777231,7670709) + 4752838 + (16777233,7670709) + 13730229 + AccountInfo_(null) + + SQMSharedMachineId + aaaaaaaa-gggg-dddd-eeeee-aaaaaaaacccccc + SQMSharedUserId + aaaaaaaa-gggg-dddd-eeeee-aaaaaaaacccccc + UAR_Context + InstanceRestarter + UAR_Reason + 4 + UAR_Timestamp + 2024-09-23T23:31:52Z + + AccountInfo_Business1 + + OneDriveDeviceId + aaaaaaaa-gggg-dddd-eeeee-aaaaaaaacccccc + + AccountInfo_Personal + + AccountMarket + US + AgeGroup + Adult + AuthenticationURLs + + Authority + https://login.microsoftonline.com/consumers + DiscoveryAPI + https://odc.officeapps.live.com/odc/servicemanager/userconnected + DiscoveryResourceId + https://api.office.net + GraphAPI + + NextEmailHRDUpdate + 0 + + CrashDetectionKey + + ECSConfigurationETag + "asdfadafbabgxvaefhtsdfghsdfrg=" + ECSConfigurationExpires + 1727248069 + ECSConfigurationLastSuccess + 479779 + ECSConfigurationMaxAge + 43200 + FeatureSupportInstance + 2 + FeatureSupportService + 1 + FirstSignInTimestamp + 2024-03-31T22:10:23Z + GetOnlineStatus + Completed + HasShownFirstRunExperience + + IsGoSov + + IsUpgradeAvailable + + LatestSignInStack + 9 + OfficePrivacySetting + 1 + OneAuthAccountId + aaaaaaaaa + OneDriveDeviceId + aaaaaaaa-gggg-dddd-eeeee-aaaaaaaacccccc + PrivacyKnowledge + 68 + PrivacySettingsVersionSeen + 1 + SQMSharedMachineId + aaaaaaaa-gggg-dddd-eeeee-aaaaaaaacccccc + SQMSharedUserId + aaaaaaaa-gggg-dddd-eeeee-aaaaaaaacccccc + ScopeIdToMountPointPathCache + + 20219EA4F9EC76E0!101 + /Users/dev/Library/Group Containers/UBF8T346G9.OneDriveStandaloneSuite/OneDrive.noindex/OneDrive + cc899733b9eb4f42bccbb83caceea9de + /Users/dev/Library/Group Containers/UBF8T346G9.OneDriveStandaloneSuite/OneDrive.noindex/OneDrive + + ScreenRefreshBackoff + 1 + TenantId + aaaaaaaa-gggg-dddd-eeeee-aaaaaaaacccccc + TimerAgeGroup + 1727739117 + TimerNezhaTelemetryHeartbeat + 1727307838 + UAR_AutoStart + 1 + UAR_Context + SetCommandLine + UAR_InstanceState + Startup + UAR_Reason + 2 + UAR_Timestamp + 2024-09-23T23:31:57Z + UaRAutoStart + 1 + UserEmail + devtester@outlook.com + UserFolder + /Users/dev/Library/Group Containers/UBF8T346G9.OneDriveStandaloneSuite/OneDrive.noindex/OneDrive + cid + 20219ea4f9ec76e0 + + CommonStringUtilUseUnicodeStr + 1 + CurrentVersion + 24.171.0825.0002 + LastSuccessfulUpdateCheckTime + 2025-10-15T00:44:35Z + LastSuccessfulUpdateCheckVersion + 25.179.0914.0003 + NucleusCrashProcessId + + NucleusUseBrokerAuth + 1 + OneDriveRootPaths + + /Users/dev/Library/Group Containers/UBF8T346G9.OneDriveStandaloneSuite/OneDrive.noindex/OneDrive + Personal + + + diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/general.keystore b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/general.keystore new file mode 100644 index 00000000..b3c68aeb --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/mock/general.keystore @@ -0,0 +1 @@ +[{"CreatedTime" : 1727099289,"Key" : "w77qU9tCy4Hsdd5\/VPgdIhhhx+LFre+qtv0o96p9nG0=\u0000\u0000","Version" : 1}] \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/CxP.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/CxP.db new file mode 100644 index 00000000..df2f578d Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/CxP.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/FileSyncFSCache.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/FileSyncFSCache.db new file mode 100644 index 00000000..57014e83 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/FileSyncFSCache.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/5bb92615fd01a69c.ini b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/5bb92615fd01a69c.ini new file mode 100644 index 00000000..3055a1ee Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/5bb92615fd01a69c.ini differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ClientPolicy.ini b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ClientPolicy.ini new file mode 100644 index 00000000..1cdda46a Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ClientPolicy.ini differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ClientPolicy_a25bb334ad5f4204ba91c137f255abae7c731aeda6844198b20320a40c558788dc991eb1fa97419ab41a9561d211b9ee.ini b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ClientPolicy_a25bb334ad5f4204ba91c137f255abae7c731aeda6844198b20320a40c558788dc991eb1fa97419ab41a9561d211b9ee.ini new file mode 100644 index 00000000..4d114c60 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ClientPolicy_a25bb334ad5f4204ba91c137f255abae7c731aeda6844198b20320a40c558788dc991eb1fa97419ab41a9561d211b9ee.ini differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ECSConfig.json b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ECSConfig.json new file mode 100644 index 00000000..8fb1cb54 --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ECSConfig.json @@ -0,0 +1 @@ +{"ECS":{"DisableConfigLog":true,"CacheExpiryInMin":720},"ODSP_Sync_Client":{"Ramps":{"3215":false,"3040":true,"2355":false,"13":false,"14":true,"12":true,"0":true},"RampExperiments":{"3215":{"type":2,"id":1417033,"name":"SyncGraphMetadataLCExperimentRamp","slot":1},"3040":{"type":2,"id":1276784,"name":"FlyoutCalmerLouderStatesExperimentV2","slot":3},"2355":{"type":2,"id":1271629,"name":"AccountTransferExperiment","slot":4},"13":{"type":2,"id":77066,"name":"ACFooterGoPremiumDimeExperiment"},"12":{"type":2,"id":45328,"name":"ShowKFMinFRE_v2"}},"Settings":{"2728":"1,0","0":"Prod"},"SettingExperiments":{"2728":{"type":2,"id":1256751,"name":"Campaign50GBToast","group":1,"slot":4}}},"Headers":{"ETag":"\"Cn5F+pHEKUnIzSXwrCvOYT4JCfzm2pU9QQhuJpKrp60=\"","Expires":"Tue, 24 Sep 2024 01:48:59 GMT","CountryCode":"US","StatusCode":"200"},"ConfigIDs":{"ECS":"P-R-54894-1-3,P-R-53736-1-8","ODSP_Sync_Client":"P-E-1417033-C1-6,P-E-1276784-T2-7,P-E-1271629-C1-10,P-E-1256751-T2-8,P-E-77066-A2-7,P-R-80526-3-4,P-R-69229-1-2,P-D-27657-4-3"},"EventToConfigIdsMapping":{"ODSP_Sync_Client":{"experiments":"P-E-1417033-C1-6"}}} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/KFM.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/KFM.db new file mode 100644 index 00000000..5d2427f2 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/KFM.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ListIdDiscoveryResponse.txt b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ListIdDiscoveryResponse.txt new file mode 100644 index 00000000..bf62ff77 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/ListIdDiscoveryResponse.txt differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/OCSI.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/OCSI.db new file mode 100644 index 00000000..8d2b5faf Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/OCSI.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/Originator.ini b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/Originator.ini new file mode 100644 index 00000000..8b198a44 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/Originator.ini differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SafeDelete.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SafeDelete.db new file mode 100644 index 00000000..64a7abd2 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SafeDelete.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SettingsDatabase.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SettingsDatabase.db new file mode 100644 index 00000000..e65caae7 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SettingsDatabase.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SiteIdDiscoveryResponse.txt b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SiteIdDiscoveryResponse.txt new file mode 100644 index 00000000..66e837b5 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SiteIdDiscoveryResponse.txt differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SurveyManagerState.json b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SurveyManagerState.json new file mode 100644 index 00000000..000039fe --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SurveyManagerState.json @@ -0,0 +1 @@ +{"Campaigns" : [{"CampaignId" : "b44891ef-eac4-4883-9be6-5f73a1961d4b","CampaignState" : "{\"EventCounters\" : [{\"Count\" : 0,\"Name\" : \"FpsSurveyForExperiments\"}],\"ExtraData\" : \"{\\\"ExperimentsTriggerSequence\\\" : [],\\\"FirstTriggerTime\\\" : [0,false],\\\"SeenExperiments\\\" : []}\"}","IsNominated" : false,"LastNominationTime" : "2024-09-23T13:48:59Z","LastSurveyShownTime" : "1970-01-01T00:00:00Z"},{"CampaignId" : "343904b4-40ae-4129-96f2-e6a8353b68c4","CampaignState" : "{\"EventCounters\" : [{\"Count\" : 0,\"Name\" : \"KnownFolderFileOperation\"}],\"ExtraData\" : \"\"}","IsNominated" : false,"LastNominationTime" : "1970-01-01T00:00:00Z","LastSurveyShownTime" : "1970-01-01T00:00:00Z"},{"CampaignId" : "37010caf-3edf-4416-9e98-f5b4c3c7a8b7","CampaignState" : "{\"EventCounters\" : [{\"Count\" : 0,\"Name\" : \"ActiveUsageAction\"}],\"ExtraData\" : \"{\\\"TriggerSequence\\\" : []}\"}","IsNominated" : false,"LastNominationTime" : "1970-01-01T00:00:00Z","LastSurveyShownTime" : "1970-01-01T00:00:00Z"},{"CampaignId" : "4750eb1b-1d8a-41f7-922f-facd7d04f548","CampaignState" : "{\"EventCounters\" : [{\"Count\" : 0,\"Name\" : \"ActiveUsageAction\"}],\"ExtraData\" : \"\"}","IsNominated" : false,"LastNominationTime" : "2024-09-23T13:48:59Z","LastSurveyShownTime" : "1970-01-01T00:00:00Z"},{"CampaignId" : "05255a89-826d-47fd-ad30-198a62e4d5aa","CampaignState" : "{\"EventCounters\" : [{\"Count\" : 0,\"Name\" : \"ContextualExperiment\"}],\"ExtraData\" : \"\"}","IsNominated" : false,"LastNominationTime" : "2024-09-23T13:48:59Z","LastSurveyShownTime" : "1970-01-01T00:00:00Z"},{"CampaignId" : "092b8d95-cf3f-4172-a11b-f5bbc03077ac","CampaignState" : "{\"EventCounters\" : [{\"Count\" : 0,\"Name\" : \"ActiveUsageAction\"}],\"ExtraData\" : \"\"}","IsNominated" : false,"LastNominationTime" : "1970-01-01T00:00:00Z","LastSurveyShownTime" : "1970-01-01T00:00:00Z"}],"LastSurveyShownTime" : "1970-01-01T00:00:00Z"} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SyncEngineDatabase.db b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SyncEngineDatabase.db new file mode 100644 index 00000000..810df17c Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/SyncEngineDatabase.db differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/downloads3.txt b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/downloads3.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/global.ini b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/global.ini new file mode 100644 index 00000000..b3ecf7e5 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/global.ini differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/logUploaderSettings.ini b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/logUploaderSettings.ini new file mode 100644 index 00000000..a609c4e5 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/logUploaderSettings.ini differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/logUploaderSettings_temp.ini b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/logUploaderSettings_temp.ini new file mode 100644 index 00000000..a609c4e5 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/logUploaderSettings_temp.ini differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/uploads.txt b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/Personal/uploads.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/PreSignInSettingsConfig.json b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/PreSignInSettingsConfig.json new file mode 100644 index 00000000..f5c8f79a --- /dev/null +++ b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/settings/PreSignInSettingsConfig.json @@ -0,0 +1 @@ +{"ramps":[{"id":3,"offset":0,"share":100},{"id":4,"offset":0,"share":100},{"id":5,"offset":0,"share":100},{"id":6,"offset":0,"share":100},{"id":7,"offset":0,"share":1},{"id":8,"offset":0,"share":1},{"id":9,"offset":0,"share":1},{"id":10,"offset":0,"share":1},{"id":14,"offset":0,"share":1},{"id":17,"offset":0,"share":100},{"id":18,"offset":0,"share":100},{"id":21,"offset":0,"share":1},{"id":22,"offset":0,"share":1},{"id":24,"offset":0,"share":100},{"id":25,"offset":0,"share":100},{"id":26,"offset":0,"share":100},{"id":27,"offset":0,"share":100},{"id":29,"offset":0,"share":100},{"id":30,"offset":0,"share":100},{"id":31,"offset":31,"share":100},{"id":34,"offset":0,"share":100},{"id":35,"offset":0,"share":100},{"id":36,"offset":0,"share":100},{"id":37,"offset":0,"share":100},{"id":39,"offset":0,"share":100},{"id":41,"offset":0,"share":100},{"id":43,"offset":0,"share":100},{"id":44,"offset":0,"share":100},{"id":45,"offset":0,"share":50},{"id":46,"offset":0,"share":50},{"id":53,"offset":0,"share":1},{"id":54,"offset":0,"share":100},{"id":55,"offset":0,"share":100},{"id":56,"offset":0,"share":100},{"id":58,"offset":0,"share":100},{"id":61,"offset":0,"share":100},{"id":63,"offset":0,"share":100},{"id":66,"offset":0,"share":100},{"id":67,"offset":0,"share":10},{"id":70,"offset":0,"share":100},{"id":71,"offset":0,"share":100},{"id":73,"offset":0,"share":100},{"id":77,"offset":0,"share":100},{"id":78,"offset":0,"share":100},{"id":80,"offset":0,"share":100},{"id":82,"offset":0,"share":100},{"id":83,"offset":0,"share":100},{"id":84,"offset":0,"share":100},{"id":85,"offset":0,"share":100},{"id":86,"offset":0,"share":100},{"id":87,"offset":0,"share":100},{"id":88,"offset":0,"share":100},{"id":92,"offset":0,"share":100},{"id":94,"offset":0,"share":100},{"id":98,"offset":0,"share":100},{"id":100,"offset":0,"share":100},{"id":103,"offset":0,"share":100},{"id":105,"offset":100,"share":100},{"id":107,"offset":23,"share":100},{"id":108,"offset":0,"share":100},{"id":109,"offset":0,"share":100},{"id":112,"offset":0,"share":100},{"id":114,"offset":0,"share":100},{"id":117,"offset":0,"share":100},{"id":118,"offset":0,"share":100},{"id":120,"offset":0,"share":100},{"id":121,"offset":0,"share":100},{"id":122,"offset":50,"share":100},{"id":123,"offset":0,"share":10},{"id":124,"offset":0,"share":100},{"id":125,"offset":0,"share":100},{"id":127,"offset":0,"share":100},{"id":129,"offset":0,"share":100},{"id":131,"offset":0,"share":10},{"id":133,"offset":0,"share":100},{"id":135,"offset":0,"share":100},{"id":136,"offset":0,"share":100},{"id":138,"offset":0,"share":100},{"id":141,"offset":0,"share":100},{"id":144,"offset":0,"share":100},{"id":146,"offset":0,"share":100},{"id":151,"offset":0,"share":100},{"id":153,"offset":0,"share":100},{"id":155,"offset":0,"share":100},{"id":156,"offset":0,"share":100},{"id":157,"offset":0,"share":100},{"id":158,"offset":0,"share":100},{"id":159,"offset":0,"share":100},{"id":165,"offset":0,"share":100},{"id":167,"offset":0,"share":100},{"id":168,"offset":0,"share":100},{"id":172,"offset":0,"share":100},{"id":173,"offset":0,"share":100},{"id":174,"offset":0,"share":100},{"id":175,"offset":0,"share":100},{"id":176,"offset":0,"share":100},{"id":177,"offset":0,"share":100},{"id":178,"offset":0,"share":100},{"id":179,"offset":0,"share":5},{"id":182,"offset":0,"share":100},{"id":183,"offset":0,"share":100},{"id":191,"offset":0,"share":100},{"id":194,"offset":0,"share":100},{"id":195,"offset":0,"share":100},{"id":196,"offset":0,"share":100},{"id":197,"offset":0,"share":100},{"id":198,"offset":0,"share":100},{"id":200,"offset":0,"share":100},{"id":201,"offset":0,"share":100},{"id":204,"offset":0,"share":100},{"id":205,"offset":0,"share":100},{"id":206,"offset":0,"share":100},{"id":207,"offset":0,"share":100},{"id":208,"offset":0,"share":100},{"id":210,"offset":0,"share":100},{"id":211,"offset":0,"share":100},{"id":216,"offset":0,"share":100},{"id":217,"offset":0,"share":100},{"id":218,"offset":0,"share":100},{"id":219,"offset":0,"share":100},{"id":221,"offset":0,"share":100},{"id":224,"offset":0,"share":100},{"id":226,"offset":0,"share":100},{"id":228,"offset":0,"share":100},{"id":231,"offset":0,"share":100},{"id":232,"offset":0,"share":100},{"id":234,"offset":0,"share":100},{"id":239,"offset":0,"share":100},{"id":240,"offset":0,"share":100},{"id":241,"offset":0,"share":100},{"id":242,"offset":0,"share":100},{"id":248,"offset":0,"share":100},{"id":249,"offset":0,"share":100},{"id":251,"offset":0,"share":100},{"id":252,"offset":0,"share":100},{"id":253,"offset":0,"share":100},{"id":254,"offset":0,"share":100},{"id":256,"offset":0,"share":100},{"id":260,"offset":0,"share":100},{"id":262,"offset":0,"share":100},{"id":265,"offset":0,"share":100},{"id":271,"offset":0,"share":100},{"id":274,"offset":0,"share":100},{"id":276,"offset":0,"share":100},{"id":277,"offset":0,"share":100},{"id":281,"offset":0,"share":100},{"id":282,"offset":0,"share":100},{"id":289,"offset":0,"share":100},{"id":290,"offset":0,"share":100},{"id":293,"offset":0,"share":100},{"id":299,"offset":0,"share":100},{"id":300,"offset":0,"share":100},{"id":301,"offset":0,"share":100},{"id":303,"offset":0,"share":100},{"id":304,"offset":0,"share":100},{"id":306,"offset":0,"share":100},{"id":307,"offset":0,"share":100},{"id":315,"offset":0,"share":100},{"id":316,"offset":0,"share":100},{"id":317,"offset":0,"share":100},{"id":318,"offset":0,"share":100},{"id":319,"offset":0,"share":100},{"id":320,"offset":0,"share":100},{"id":322,"offset":0,"share":100},{"id":323,"offset":0,"share":100},{"id":326,"offset":0,"share":100},{"id":327,"offset":0,"share":100},{"id":330,"offset":0,"share":100},{"id":331,"offset":0,"share":100},{"id":332,"offset":0,"share":100},{"id":334,"offset":0,"share":100},{"id":335,"offset":0,"share":100},{"id":336,"offset":0,"share":100},{"id":337,"offset":0,"share":100},{"id":338,"offset":0,"share":100},{"id":339,"offset":0,"share":100},{"id":346,"offset":0,"share":100},{"id":352,"offset":0,"share":100},{"id":358,"offset":0,"share":100},{"id":360,"offset":0,"share":100},{"id":362,"offset":0,"share":100},{"id":364,"offset":0,"share":100},{"id":370,"offset":0,"share":100},{"id":373,"offset":0,"share":100},{"id":374,"offset":17,"share":100},{"id":379,"offset":0,"share":100},{"id":380,"offset":0,"share":100},{"id":381,"offset":0,"share":100},{"id":382,"offset":0,"share":100},{"id":383,"offset":0,"share":100},{"id":384,"offset":0,"share":100},{"id":385,"offset":0,"share":100},{"id":386,"offset":0,"share":100},{"id":388,"offset":0,"share":100},{"id":389,"offset":0,"share":100},{"id":392,"offset":0,"share":100},{"id":393,"offset":0,"share":100},{"id":396,"offset":0,"share":100},{"id":398,"offset":0,"share":100},{"id":401,"offset":0,"share":100},{"id":402,"offset":0,"share":100},{"id":404,"offset":0,"share":100},{"id":405,"offset":0,"share":100},{"id":406,"offset":0,"share":100},{"id":407,"offset":0,"share":100},{"id":408,"offset":0,"share":100},{"id":414,"offset":0,"share":100},{"id":416,"offset":0,"share":100},{"id":421,"offset":0,"share":100},{"id":422,"offset":0,"share":100},{"id":426,"offset":0,"share":100},{"id":430,"offset":0,"share":100},{"id":434,"offset":0,"share":100},{"id":435,"offset":0,"share":100},{"id":436,"offset":0,"share":100},{"id":438,"offset":0,"share":100},{"id":440,"offset":0,"share":100},{"id":443,"offset":0,"share":100},{"id":444,"offset":0,"share":100},{"id":445,"offset":0,"share":100},{"id":446,"offset":0,"share":100},{"id":447,"offset":0,"share":100},{"id":448,"offset":0,"share":100},{"id":449,"offset":0,"share":100},{"id":450,"offset":0,"share":100},{"id":455,"offset":0,"share":100},{"id":456,"offset":0,"share":100},{"id":459,"offset":0,"share":25},{"id":460,"offset":0,"share":100},{"id":462,"offset":0,"share":100},{"id":471,"offset":0,"share":100},{"id":474,"offset":0,"share":100},{"id":475,"offset":0,"share":100},{"id":477,"offset":0,"share":50},{"id":478,"offset":0,"share":100},{"id":479,"offset":0,"share":100},{"id":480,"offset":0,"share":100},{"id":485,"offset":0,"share":100},{"id":486,"offset":0,"share":100},{"id":490,"offset":0,"share":100},{"id":491,"offset":0,"share":100},{"id":493,"offset":0,"share":100},{"id":495,"offset":0,"share":100},{"id":501,"offset":0,"share":100},{"id":502,"offset":0,"share":100},{"id":503,"offset":0,"share":100},{"id":504,"offset":0,"share":100},{"id":506,"offset":0,"share":100},{"id":509,"offset":0,"share":100},{"id":511,"offset":0,"share":100},{"id":515,"offset":0,"share":100},{"id":516,"offset":0,"share":100},{"id":517,"offset":0,"share":100},{"id":518,"offset":23,"share":100},{"id":519,"offset":0,"share":100},{"id":520,"offset":0,"share":100},{"id":521,"offset":0,"share":100},{"id":522,"offset":0,"share":100},{"id":523,"offset":23,"share":100},{"id":526,"offset":0,"share":100},{"id":528,"offset":0,"share":100},{"id":531,"offset":0,"share":100},{"id":532,"offset":23,"share":100},{"id":533,"offset":0,"share":100},{"id":534,"offset":0,"share":100},{"id":535,"offset":0,"share":100},{"id":536,"offset":0,"share":100},{"id":537,"offset":0,"share":100},{"id":539,"offset":0,"share":100},{"id":540,"offset":0,"share":100},{"id":543,"offset":0,"share":100},{"id":544,"offset":0,"share":100},{"id":545,"offset":0,"share":100},{"id":546,"offset":0,"share":100},{"id":547,"offset":0,"share":100},{"id":548,"offset":0,"share":100},{"id":549,"offset":0,"share":100},{"id":550,"offset":0,"share":100},{"id":552,"offset":0,"share":100},{"id":555,"offset":0,"share":100},{"id":556,"offset":0,"share":100},{"id":558,"offset":0,"share":100},{"id":559,"offset":0,"share":100},{"id":561,"offset":0,"share":100},{"id":565,"offset":23,"share":100},{"id":566,"offset":0,"share":100},{"id":568,"offset":0,"share":100},{"id":569,"offset":0,"share":100},{"id":570,"offset":0,"share":100},{"id":572,"offset":0,"share":100},{"id":574,"offset":0,"share":100},{"id":575,"offset":0,"share":100},{"id":577,"offset":0,"share":100},{"id":578,"offset":0,"share":100},{"id":579,"offset":0,"share":100},{"id":580,"offset":0,"share":100},{"id":582,"offset":0,"share":100},{"id":584,"offset":23,"share":60},{"id":586,"offset":0,"share":100},{"id":590,"offset":0,"share":100},{"id":594,"offset":0,"share":100},{"id":596,"offset":0,"share":100},{"id":598,"offset":0,"share":1},{"id":600,"offset":0,"share":100},{"id":604,"offset":0,"share":100},{"id":605,"offset":0,"share":100},{"id":606,"offset":0,"share":100},{"id":612,"offset":0,"share":100},{"id":614,"offset":0,"share":100},{"id":615,"offset":17,"share":100},{"id":616,"offset":0,"share":100},{"id":618,"offset":0,"share":100},{"id":621,"offset":0,"share":100},{"id":622,"offset":0,"share":100},{"id":625,"offset":0,"share":100},{"id":626,"offset":0,"share":100},{"id":627,"offset":0,"share":100},{"id":628,"offset":0,"share":100},{"id":629,"offset":0,"share":100},{"id":630,"offset":0,"share":100},{"id":634,"offset":0,"share":100},{"id":637,"offset":0,"share":100},{"id":640,"offset":0,"share":100},{"id":643,"offset":0,"share":100},{"id":644,"offset":0,"share":100},{"id":646,"offset":0,"share":100},{"id":651,"offset":0,"share":100},{"id":653,"offset":0,"share":100},{"id":655,"offset":0,"share":100},{"id":657,"offset":0,"share":100},{"id":658,"offset":0,"share":100},{"id":662,"offset":0,"share":100},{"id":667,"offset":0,"share":100},{"id":668,"offset":0,"share":100},{"id":671,"offset":0,"share":100},{"id":672,"offset":0,"share":100},{"id":674,"offset":0,"share":100},{"id":679,"offset":0,"share":100},{"id":680,"offset":0,"share":100},{"id":684,"offset":0,"share":25},{"id":686,"offset":0,"share":100},{"id":689,"offset":0,"share":100},{"id":692,"offset":0,"share":100},{"id":693,"offset":0,"share":100},{"id":694,"offset":0,"share":100},{"id":695,"offset":0,"share":100},{"id":697,"offset":0,"share":100},{"id":700,"offset":0,"share":100},{"id":701,"offset":0,"share":100},{"id":703,"offset":23,"share":100},{"id":704,"offset":0,"share":100},{"id":706,"offset":0,"share":100},{"id":709,"offset":0,"share":50},{"id":710,"offset":0,"share":100},{"id":715,"offset":0,"share":100},{"id":716,"offset":0,"share":100},{"id":718,"offset":23,"share":100},{"id":719,"offset":0,"share":100},{"id":720,"offset":0,"share":100},{"id":722,"offset":0,"share":100},{"id":723,"offset":0,"share":100},{"id":724,"offset":0,"share":100},{"id":726,"offset":0,"share":100},{"id":727,"offset":0,"share":100},{"id":728,"offset":0,"share":100},{"id":729,"offset":0,"share":100},{"id":730,"offset":0,"share":100},{"id":732,"offset":0,"share":100},{"id":739,"offset":0,"share":100},{"id":741,"offset":0,"share":100},{"id":745,"offset":0,"share":100},{"id":746,"offset":23,"share":100},{"id":747,"offset":23,"share":100},{"id":748,"offset":0,"share":1},{"id":752,"offset":0,"share":100},{"id":753,"offset":0,"share":100},{"id":755,"offset":0,"share":100},{"id":762,"offset":0,"share":100},{"id":763,"offset":23,"share":100},{"id":764,"offset":23,"share":100},{"id":767,"offset":0,"share":100},{"id":768,"offset":0,"share":100},{"id":770,"offset":0,"share":100},{"id":771,"offset":0,"share":100},{"id":773,"offset":0,"share":100},{"id":774,"offset":0,"share":100},{"id":775,"offset":0,"share":100},{"id":779,"offset":0,"share":100},{"id":783,"offset":0,"share":100},{"id":784,"offset":0,"share":100},{"id":786,"offset":0,"share":100},{"id":793,"offset":0,"share":100},{"id":796,"offset":0,"share":100},{"id":800,"offset":0,"share":100},{"id":801,"offset":0,"share":100},{"id":804,"offset":0,"share":100},{"id":806,"offset":0,"share":100},{"id":812,"offset":0,"share":100},{"id":813,"offset":0,"share":100},{"id":814,"offset":0,"share":100},{"id":817,"offset":0,"share":100},{"id":818,"offset":0,"share":100},{"id":820,"offset":0,"share":100},{"id":821,"offset":0,"share":100},{"id":822,"offset":0,"share":100},{"id":823,"offset":0,"share":100},{"id":824,"offset":0,"share":100},{"id":825,"offset":0,"share":100},{"id":829,"offset":0,"share":100},{"id":831,"offset":0,"share":100},{"id":833,"offset":0,"share":100},{"id":836,"offset":0,"share":100},{"id":837,"offset":0,"share":100},{"id":838,"offset":0,"share":100},{"id":839,"offset":0,"share":100},{"id":840,"offset":0,"share":100},{"id":842,"offset":23,"share":100},{"id":843,"offset":0,"share":100},{"id":845,"offset":0,"share":100},{"id":846,"offset":0,"share":100},{"id":847,"offset":0,"share":100},{"id":851,"offset":0,"share":100},{"id":854,"offset":0,"share":100},{"id":856,"offset":0,"share":100},{"id":857,"offset":0,"share":100},{"id":859,"offset":0,"share":100},{"id":860,"offset":0,"share":100},{"id":863,"offset":0,"share":100},{"id":864,"offset":0,"share":100},{"id":865,"offset":0,"share":100},{"id":866,"offset":0,"share":100},{"id":867,"offset":0,"share":100},{"id":871,"offset":0,"share":100},{"id":874,"offset":0,"share":100},{"id":875,"offset":0,"share":100},{"id":876,"offset":0,"share":100},{"id":878,"offset":0,"share":100},{"id":879,"offset":0,"share":10},{"id":880,"offset":0,"share":100},{"id":882,"offset":0,"share":50},{"id":886,"offset":0,"share":50},{"id":888,"offset":0,"share":100},{"id":893,"offset":0,"share":100},{"id":896,"offset":0,"share":100},{"id":897,"offset":0,"share":100},{"id":898,"offset":0,"share":100},{"id":900,"offset":0,"share":100},{"id":901,"offset":0,"share":100},{"id":902,"offset":0,"share":100},{"id":904,"offset":0,"share":100},{"id":908,"offset":0,"share":100},{"id":909,"offset":0,"share":100},{"id":910,"offset":0,"share":100},{"id":911,"offset":23,"share":100},{"id":912,"offset":0,"share":100},{"id":915,"offset":0,"share":100},{"id":916,"offset":0,"share":100},{"id":918,"offset":0,"share":100},{"id":919,"offset":0,"share":100},{"id":921,"offset":0,"share":100},{"id":922,"offset":0,"share":100},{"id":923,"offset":0,"share":100},{"id":925,"offset":0,"share":100},{"id":926,"offset":0,"share":100},{"id":927,"offset":0,"share":100},{"id":928,"offset":0,"share":100},{"id":929,"offset":0,"share":100},{"id":932,"offset":0,"share":100},{"id":933,"offset":0,"share":100},{"id":935,"offset":0,"share":100},{"id":941,"offset":0,"share":100},{"id":942,"offset":0,"share":100},{"id":944,"offset":0,"share":100},{"id":948,"offset":0,"share":100},{"id":949,"offset":0,"share":100},{"id":953,"offset":0,"share":100},{"id":954,"offset":0,"share":100},{"id":955,"offset":0,"share":100},{"id":957,"offset":0,"share":100},{"id":959,"offset":0,"share":100},{"id":960,"offset":0,"share":100},{"id":961,"offset":0,"share":100},{"id":963,"offset":0,"share":100},{"id":964,"offset":0,"share":100},{"id":966,"offset":0,"share":100},{"id":968,"offset":0,"share":100},{"id":969,"offset":0,"share":100},{"id":971,"offset":0,"share":100},{"id":972,"offset":0,"share":100},{"id":973,"offset":0,"share":100},{"id":977,"offset":0,"share":100},{"id":979,"offset":0,"share":100},{"id":987,"offset":0,"share":100},{"id":989,"offset":0,"share":100},{"id":993,"offset":0,"share":100},{"id":995,"offset":0,"share":100},{"id":997,"offset":0,"share":100},{"id":999,"offset":0,"share":100},{"id":1000,"offset":0,"share":100},{"id":1003,"offset":0,"share":100},{"id":1006,"offset":0,"share":100},{"id":1007,"offset":0,"share":100},{"id":1014,"offset":0,"share":100},{"id":1015,"offset":0,"share":100},{"id":1016,"offset":0,"share":100},{"id":1020,"offset":0,"share":100},{"id":1021,"offset":0,"share":100},{"id":1022,"offset":0,"share":100},{"id":1024,"offset":0,"share":100},{"id":1031,"offset":0,"share":100},{"id":1032,"offset":0,"share":100},{"id":1034,"offset":0,"share":100},{"id":1035,"offset":0,"share":100},{"id":1037,"offset":0,"share":100},{"id":1038,"offset":0,"share":100},{"id":1045,"offset":0,"share":100},{"id":1046,"offset":0,"share":100},{"id":1048,"offset":0,"share":100},{"id":1058,"offset":0,"share":100},{"id":1059,"offset":0,"share":100},{"id":1062,"offset":0,"share":100},{"id":1064,"offset":0,"share":100},{"id":1068,"offset":0,"share":100},{"id":1069,"offset":0,"share":100},{"id":1070,"offset":0,"share":100},{"id":1072,"offset":0,"share":100},{"id":1073,"offset":0,"share":100},{"id":1075,"offset":0,"share":100},{"id":1076,"offset":0,"share":100},{"id":1079,"offset":0,"share":100},{"id":1080,"offset":0,"share":100},{"id":1082,"offset":0,"share":100},{"id":1083,"offset":0,"share":100},{"id":1084,"offset":0,"share":100},{"id":1085,"offset":0,"share":100},{"id":1086,"offset":0,"share":100},{"id":1087,"offset":0,"share":100},{"id":1088,"offset":0,"share":100},{"id":1093,"offset":0,"share":100},{"id":1094,"offset":0,"share":100},{"id":1097,"offset":0,"share":100},{"id":1104,"offset":0,"share":100},{"id":1105,"offset":0,"share":100},{"id":1106,"offset":0,"share":100},{"id":1107,"offset":0,"share":100},{"id":1108,"offset":0,"share":100},{"id":1109,"offset":0,"share":100},{"id":1111,"offset":0,"share":100},{"id":1114,"offset":0,"share":100},{"id":1115,"offset":0,"share":100},{"id":1122,"offset":0,"share":100},{"id":1123,"offset":0,"share":100},{"id":1124,"offset":0,"share":100},{"id":1126,"offset":0,"share":100},{"id":1130,"offset":0,"share":100},{"id":1138,"offset":0,"share":100},{"id":1145,"offset":0,"share":100},{"id":1148,"offset":0,"share":100},{"id":1149,"offset":0,"share":100},{"id":1150,"offset":0,"share":100},{"id":1151,"offset":0,"share":100},{"id":1152,"offset":0,"share":100},{"id":1153,"offset":0,"share":100},{"id":1154,"offset":0,"share":100},{"id":1155,"offset":0,"share":100},{"id":1158,"offset":0,"share":100},{"id":1163,"offset":0,"share":100},{"id":1165,"offset":0,"share":100},{"id":1168,"offset":0,"share":100},{"id":1172,"offset":0,"share":100},{"id":1176,"offset":0,"share":100},{"id":1180,"offset":0,"share":100},{"id":1181,"offset":0,"share":100},{"id":1182,"offset":0,"share":100},{"id":1184,"offset":0,"share":100},{"id":1188,"offset":0,"share":100},{"id":1189,"offset":0,"share":100},{"id":1190,"offset":0,"share":100},{"id":1191,"offset":0,"share":100},{"id":1192,"offset":0,"share":100},{"id":1193,"offset":0,"share":100},{"id":1194,"offset":0,"share":100},{"id":1195,"offset":0,"share":100},{"id":1197,"offset":0,"share":100},{"id":1198,"offset":0,"share":100},{"id":1201,"offset":0,"share":100},{"id":1202,"offset":0,"share":100},{"id":1206,"offset":0,"share":100},{"id":1210,"offset":0,"share":100},{"id":1211,"offset":0,"share":100},{"id":1213,"offset":0,"share":100},{"id":1215,"offset":0,"share":100},{"id":1216,"offset":0,"share":100},{"id":1217,"offset":0,"share":100},{"id":1218,"offset":0,"share":100},{"id":1219,"offset":0,"share":100},{"id":1220,"offset":0,"share":100},{"id":1223,"offset":0,"share":100},{"id":1224,"offset":0,"share":100},{"id":1227,"offset":0,"share":100},{"id":1230,"offset":0,"share":100},{"id":1231,"offset":0,"share":100},{"id":1233,"offset":0,"share":100},{"id":1234,"offset":0,"share":100},{"id":1235,"offset":0,"share":100},{"id":1236,"offset":0,"share":100},{"id":1237,"offset":0,"share":100},{"id":1239,"offset":0,"share":100},{"id":1241,"offset":0,"share":100},{"id":1245,"offset":0,"share":100},{"id":1246,"offset":0,"share":100},{"id":1248,"offset":0,"share":100},{"id":1249,"offset":0,"share":100},{"id":1252,"offset":0,"share":100},{"id":1253,"offset":0,"share":100},{"id":1254,"offset":0,"share":100},{"id":1255,"offset":0,"share":100},{"id":1257,"offset":0,"share":100},{"id":1258,"offset":0,"share":100},{"id":1259,"offset":0,"share":100},{"id":1260,"offset":0,"share":100},{"id":1261,"offset":0,"share":100},{"id":1262,"offset":0,"share":100},{"id":1263,"offset":0,"share":100},{"id":1264,"offset":0,"share":100},{"id":1266,"offset":0,"share":100},{"id":1267,"offset":0,"share":100},{"id":1271,"offset":0,"share":100},{"id":1272,"offset":0,"share":100},{"id":1273,"offset":0,"share":100},{"id":1274,"offset":0,"share":4},{"id":1275,"offset":0,"share":100},{"id":1276,"offset":0,"share":100},{"id":1277,"offset":0,"share":100},{"id":1280,"offset":0,"share":100},{"id":1281,"offset":0,"share":100},{"id":1282,"offset":0,"share":100},{"id":1288,"offset":0,"share":100},{"id":1292,"offset":0,"share":100},{"id":1293,"offset":0,"share":1},{"id":1294,"offset":0,"share":100},{"id":1296,"offset":0,"share":100},{"id":1297,"offset":0,"share":100},{"id":1301,"offset":0,"share":100},{"id":1302,"offset":0,"share":100},{"id":1304,"offset":0,"share":100},{"id":1305,"offset":0,"share":1},{"id":1306,"offset":0,"share":100},{"id":1309,"offset":0,"share":100},{"id":1315,"offset":0,"share":1},{"id":1323,"offset":0,"share":100},{"id":1331,"offset":0,"share":100},{"id":1332,"offset":0,"share":100},{"id":1336,"offset":0,"share":100},{"id":1338,"offset":0,"share":100},{"id":1346,"offset":0,"share":100},{"id":1348,"offset":0,"share":100},{"id":1354,"offset":0,"share":100},{"id":1356,"offset":0,"share":100},{"id":1357,"offset":0,"share":100},{"id":1358,"offset":0,"share":100},{"id":1359,"offset":0,"share":100},{"id":1360,"offset":0,"share":100},{"id":1361,"offset":0,"share":100},{"id":1362,"offset":0,"share":100},{"id":1365,"offset":0,"share":100},{"id":1369,"offset":0,"share":100},{"id":1370,"offset":0,"share":100},{"id":1371,"offset":0,"share":100},{"id":1372,"offset":0,"share":100},{"id":1376,"offset":0,"share":100},{"id":1379,"offset":0,"share":100},{"id":1384,"offset":0,"share":100},{"id":1386,"offset":0,"share":100},{"id":1387,"offset":0,"share":1},{"id":1390,"offset":0,"share":100},{"id":1391,"offset":0,"share":100},{"id":1392,"offset":0,"share":100},{"id":1393,"offset":0,"share":100},{"id":1398,"offset":0,"share":100},{"id":1400,"offset":0,"share":100},{"id":1401,"offset":0,"share":100},{"id":1402,"offset":0,"share":100},{"id":1405,"offset":0,"share":100},{"id":1406,"offset":0,"share":100},{"id":1408,"offset":0,"share":100},{"id":1409,"offset":0,"share":100},{"id":1410,"offset":0,"share":100},{"id":1411,"offset":0,"share":100},{"id":1413,"offset":0,"share":100},{"id":1420,"offset":0,"share":1},{"id":1426,"offset":0,"share":100},{"id":1428,"offset":0,"share":100},{"id":1429,"offset":0,"share":100},{"id":1430,"offset":0,"share":100},{"id":1431,"offset":0,"share":100},{"id":1432,"offset":0,"share":100},{"id":1433,"offset":0,"share":100},{"id":1434,"offset":0,"share":100},{"id":1435,"offset":0,"share":100},{"id":1436,"offset":0,"share":10},{"id":1441,"offset":0,"share":50},{"id":1442,"offset":0,"share":100},{"id":1447,"offset":0,"share":100},{"id":1448,"offset":0,"share":100},{"id":1449,"offset":0,"share":100},{"id":1452,"offset":0,"share":100},{"id":1453,"offset":0,"share":100},{"id":1454,"offset":0,"share":100},{"id":1456,"offset":0,"share":100},{"id":1458,"offset":0,"share":100},{"id":1459,"offset":0,"share":100},{"id":1460,"offset":0,"share":100},{"id":1465,"offset":0,"share":100},{"id":1466,"offset":0,"share":100},{"id":1467,"offset":0,"share":50},{"id":1468,"offset":0,"share":100},{"id":1469,"offset":0,"share":100},{"id":1470,"offset":0,"share":100},{"id":1473,"offset":0,"share":100},{"id":1474,"offset":0,"share":100},{"id":1475,"offset":0,"share":100},{"id":1480,"offset":0,"share":100},{"id":1483,"offset":0,"share":100},{"id":1486,"offset":0,"share":100},{"id":1489,"offset":0,"share":100},{"id":1490,"offset":0,"share":100},{"id":1494,"offset":0,"share":100},{"id":1495,"offset":0,"share":100},{"id":1496,"offset":0,"share":100},{"id":1497,"offset":0,"share":100},{"id":1498,"offset":0,"share":100},{"id":1505,"offset":0,"share":100},{"id":1506,"offset":0,"share":100},{"id":1513,"offset":0,"share":100},{"id":1515,"offset":0,"share":100},{"id":1517,"offset":0,"share":100},{"id":1518,"offset":0,"share":100},{"id":1519,"offset":0,"share":100},{"id":1520,"offset":0,"share":100},{"id":1522,"offset":0,"share":100},{"id":1523,"offset":0,"share":100},{"id":1524,"offset":0,"share":100},{"id":1530,"offset":0,"share":100},{"id":1531,"offset":0,"share":100},{"id":1532,"offset":0,"share":100},{"id":1533,"offset":0,"share":100},{"id":1535,"offset":0,"share":100},{"id":1537,"offset":0,"share":100},{"id":1539,"offset":0,"share":100},{"id":1540,"offset":0,"share":100},{"id":1543,"offset":0,"share":100},{"id":1544,"offset":0,"share":100},{"id":1545,"offset":0,"share":100},{"id":1546,"offset":0,"share":100},{"id":1547,"offset":0,"share":100},{"id":1548,"offset":0,"share":100},{"id":1549,"offset":0,"share":100},{"id":1555,"offset":0,"share":100},{"id":1558,"offset":0,"share":100},{"id":1559,"offset":0,"share":100},{"id":1561,"offset":0,"share":100},{"id":1562,"offset":0,"share":100},{"id":1567,"offset":0,"share":100},{"id":1570,"offset":0,"share":100},{"id":1571,"offset":0,"share":100},{"id":1572,"offset":0,"share":100},{"id":1573,"offset":0,"share":100},{"id":1574,"offset":0,"share":100},{"id":1575,"offset":0,"share":100},{"id":1577,"offset":0,"share":100},{"id":1588,"offset":0,"share":100},{"id":1589,"offset":0,"share":100},{"id":1596,"offset":0,"share":100},{"id":1598,"offset":0,"share":100},{"id":1600,"offset":0,"share":100},{"id":1601,"offset":0,"share":100},{"id":1609,"offset":0,"share":100},{"id":1610,"offset":0,"share":10},{"id":1613,"offset":0,"share":100},{"id":1615,"offset":0,"share":100},{"id":1618,"offset":0,"share":100},{"id":1620,"offset":0,"share":100},{"id":1621,"offset":0,"share":100},{"id":1624,"offset":0,"share":100},{"id":1626,"offset":0,"share":100},{"id":1627,"offset":0,"share":100},{"id":1628,"offset":0,"share":100},{"id":1636,"offset":0,"share":100},{"id":1640,"offset":0,"share":10},{"id":1641,"offset":0,"share":100},{"id":1643,"offset":0,"share":100},{"id":1646,"offset":0,"share":100},{"id":1649,"offset":0,"share":100},{"id":1650,"offset":0,"share":100},{"id":1652,"offset":0,"share":100},{"id":1654,"offset":0,"share":100},{"id":1661,"offset":0,"share":100},{"id":1664,"offset":0,"share":100},{"id":1665,"offset":0,"share":100},{"id":1666,"offset":0,"share":100},{"id":1668,"offset":0,"share":100},{"id":1669,"offset":0,"share":100},{"id":1670,"offset":0,"share":100},{"id":1673,"offset":0,"share":100},{"id":1678,"offset":0,"share":100},{"id":1681,"offset":0,"share":100},{"id":1682,"offset":0,"share":100},{"id":1684,"offset":0,"share":100},{"id":1690,"offset":0,"share":100},{"id":1693,"offset":0,"share":100},{"id":1694,"offset":0,"share":100},{"id":1695,"offset":0,"share":100},{"id":1696,"offset":0,"share":100},{"id":1698,"offset":0,"share":1},{"id":1699,"offset":0,"share":1},{"id":1703,"offset":0,"share":100},{"id":1704,"offset":0,"share":100},{"id":1707,"offset":0,"share":100},{"id":1710,"offset":0,"share":100},{"id":1711,"offset":0,"share":100},{"id":1712,"offset":0,"share":100},{"id":1716,"offset":0,"share":100},{"id":1718,"offset":0,"share":100},{"id":1720,"offset":0,"share":100},{"id":1721,"offset":0,"share":100},{"id":1722,"offset":0,"share":100},{"id":1723,"offset":0,"share":100},{"id":1724,"offset":0,"share":100},{"id":1731,"offset":0,"share":100},{"id":1732,"offset":0,"share":100},{"id":1734,"offset":0,"share":100},{"id":1739,"offset":0,"share":100},{"id":1741,"offset":0,"share":1},{"id":1742,"offset":0,"share":1},{"id":1748,"offset":0,"share":100},{"id":1749,"offset":0,"share":100},{"id":1755,"offset":0,"share":100},{"id":1756,"offset":0,"share":100},{"id":1757,"offset":0,"share":100},{"id":1762,"offset":0,"share":100},{"id":1763,"offset":0,"share":100},{"id":1765,"offset":0,"share":1},{"id":1766,"offset":0,"share":1},{"id":1767,"offset":0,"share":100},{"id":1768,"offset":0,"share":100},{"id":1769,"offset":0,"share":100},{"id":1770,"offset":0,"share":100},{"id":1772,"offset":0,"share":1},{"id":1773,"offset":0,"share":1},{"id":1779,"offset":0,"share":100},{"id":1780,"offset":0,"share":100},{"id":1782,"offset":0,"share":100},{"id":1784,"offset":0,"share":100},{"id":1785,"offset":0,"share":100},{"id":1786,"offset":0,"share":100},{"id":1787,"offset":0,"share":100},{"id":1790,"offset":0,"share":100},{"id":1795,"offset":0,"share":100},{"id":1797,"offset":0,"share":100},{"id":1798,"offset":0,"share":10},{"id":1800,"offset":0,"share":100},{"id":1801,"offset":0,"share":100},{"id":1802,"offset":0,"share":100},{"id":1803,"offset":0,"share":100},{"id":1804,"offset":0,"share":100},{"id":1805,"offset":0,"share":100},{"id":1806,"offset":0,"share":100},{"id":1807,"offset":0,"share":100},{"id":1811,"offset":0,"share":100},{"id":1814,"offset":0,"share":100},{"id":1815,"offset":0,"share":100},{"id":1821,"offset":0,"share":100},{"id":1825,"offset":0,"share":100},{"id":1830,"offset":0,"share":100},{"id":1831,"offset":0,"share":100},{"id":1833,"offset":0,"share":100},{"id":1834,"offset":0,"share":100},{"id":1835,"offset":0,"share":100},{"id":1836,"offset":0,"share":100},{"id":1847,"offset":0,"share":100},{"id":1850,"offset":0,"share":100},{"id":1851,"offset":0,"share":100},{"id":1853,"offset":0,"share":100},{"id":1854,"offset":0,"share":100},{"id":1855,"offset":0,"share":100},{"id":1856,"offset":0,"share":100},{"id":1861,"offset":0,"share":100},{"id":1863,"offset":0,"share":100},{"id":1864,"offset":0,"share":100},{"id":1867,"offset":0,"share":100},{"id":1868,"offset":0,"share":100},{"id":1871,"offset":0,"share":100},{"id":1876,"offset":0,"share":100},{"id":1878,"offset":0,"share":100},{"id":1879,"offset":0,"share":100},{"id":1880,"offset":0,"share":100},{"id":1882,"offset":0,"share":100},{"id":1885,"offset":0,"share":100},{"id":1886,"offset":0,"share":100},{"id":1887,"offset":0,"share":100},{"id":1892,"offset":0,"share":100},{"id":1893,"offset":0,"share":100},{"id":1894,"offset":0,"share":100},{"id":1895,"offset":0,"share":100},{"id":1899,"offset":0,"share":100},{"id":1900,"offset":0,"share":100},{"id":1902,"offset":0,"share":100},{"id":1904,"offset":0,"share":100},{"id":1906,"offset":0,"share":100},{"id":1907,"offset":0,"share":100},{"id":1908,"offset":0,"share":1},{"id":1909,"offset":0,"share":100},{"id":1910,"offset":0,"share":100},{"id":1911,"offset":0,"share":100},{"id":1912,"offset":0,"share":100},{"id":1913,"offset":0,"share":100},{"id":1919,"offset":0,"share":100},{"id":1922,"offset":0,"share":100},{"id":1925,"offset":0,"share":100},{"id":1932,"offset":0,"share":100},{"id":1934,"offset":0,"share":100},{"id":1937,"offset":0,"share":100},{"id":1943,"offset":0,"share":100},{"id":1945,"offset":0,"share":100},{"id":1946,"offset":0,"share":100},{"id":1951,"offset":0,"share":100},{"id":1952,"offset":0,"share":100},{"id":1953,"offset":0,"share":100},{"id":1955,"offset":0,"share":100},{"id":1959,"offset":0,"share":100},{"id":1960,"offset":0,"share":100},{"id":1963,"offset":0,"share":100},{"id":1967,"offset":0,"share":100},{"id":1969,"offset":0,"share":100},{"id":1975,"offset":0,"share":100},{"id":1977,"offset":0,"share":100},{"id":1979,"offset":0,"share":100},{"id":1984,"offset":0,"share":100},{"id":1989,"offset":0,"share":100},{"id":1990,"offset":0,"share":100},{"id":1992,"offset":0,"share":100},{"id":1995,"offset":0,"share":100},{"id":1996,"offset":0,"share":100},{"id":1997,"offset":0,"share":100},{"id":1998,"offset":0,"share":100},{"id":2000,"offset":0,"share":100},{"id":2001,"offset":0,"share":100},{"id":2009,"offset":0,"share":100},{"id":2010,"offset":0,"share":100},{"id":2013,"offset":0,"share":100},{"id":2014,"offset":0,"share":100},{"id":2015,"offset":0,"share":100},{"id":2019,"offset":0,"share":100},{"id":2022,"offset":0,"share":100},{"id":2026,"offset":0,"share":1},{"id":2027,"offset":0,"share":100},{"id":2029,"offset":0,"share":100},{"id":2031,"offset":0,"share":100},{"id":2032,"offset":0,"share":100},{"id":2035,"offset":0,"share":100},{"id":2038,"offset":0,"share":100},{"id":2039,"offset":0,"share":100},{"id":2041,"offset":0,"share":100},{"id":2043,"offset":0,"share":100},{"id":2046,"offset":0,"share":100},{"id":2058,"offset":0,"share":100},{"id":2061,"offset":0,"share":100},{"id":2063,"offset":0,"share":100},{"id":2064,"offset":0,"share":100},{"id":2065,"offset":0,"share":100},{"id":2066,"offset":0,"share":100},{"id":2071,"offset":0,"share":100},{"id":2078,"offset":0,"share":100},{"id":2079,"offset":0,"share":100},{"id":2080,"offset":0,"share":100},{"id":2081,"offset":0,"share":100},{"id":2084,"offset":0,"share":100},{"id":2089,"offset":0,"share":100},{"id":2092,"offset":0,"share":100},{"id":2095,"offset":0,"share":100},{"id":2100,"offset":0,"share":50},{"id":2102,"offset":0,"share":100},{"id":2105,"offset":0,"share":100},{"id":2107,"offset":0,"share":100},{"id":2108,"offset":0,"share":100},{"id":2109,"offset":0,"share":100},{"id":2111,"offset":0,"share":50},{"id":2113,"offset":0,"share":100},{"id":2118,"offset":0,"share":10},{"id":2119,"offset":0,"share":100},{"id":2124,"offset":0,"share":100},{"id":2125,"offset":0,"share":100},{"id":2126,"offset":0,"share":100},{"id":2128,"offset":0,"share":100},{"id":2133,"offset":0,"share":100},{"id":2137,"offset":0,"share":100},{"id":2139,"offset":0,"share":100},{"id":2142,"offset":0,"share":100},{"id":2144,"offset":0,"share":100},{"id":2147,"offset":0,"share":100},{"id":2148,"offset":0,"share":100},{"id":2152,"offset":0,"share":100},{"id":2155,"offset":0,"share":1},{"id":2162,"offset":0,"share":100},{"id":2163,"offset":0,"share":100},{"id":2164,"offset":0,"share":1},{"id":2169,"offset":0,"share":100},{"id":2174,"offset":0,"share":100},{"id":2177,"offset":0,"share":100},{"id":2178,"offset":0,"share":100},{"id":2179,"offset":0,"share":100},{"id":2180,"offset":0,"share":100},{"id":2181,"offset":0,"share":100},{"id":2182,"offset":0,"share":100},{"id":2183,"offset":0,"share":100},{"id":2185,"offset":0,"share":10},{"id":2190,"offset":0,"share":100},{"id":2192,"offset":0,"share":100},{"id":2195,"offset":0,"share":100},{"id":2199,"offset":0,"share":100},{"id":2202,"offset":0,"share":100},{"id":2205,"offset":0,"share":100},{"id":2206,"offset":0,"share":100},{"id":2208,"offset":0,"share":100},{"id":2210,"offset":0,"share":100},{"id":2212,"offset":0,"share":100},{"id":2214,"offset":0,"share":100},{"id":2217,"offset":0,"share":100},{"id":2219,"offset":0,"share":100},{"id":2221,"offset":0,"share":100},{"id":2226,"offset":0,"share":100},{"id":2234,"offset":0,"share":100},{"id":2235,"offset":0,"share":100},{"id":2236,"offset":0,"share":100},{"id":2239,"offset":0,"share":100},{"id":2243,"offset":0,"share":100},{"id":2248,"offset":0,"share":100},{"id":2254,"offset":0,"share":1},{"id":2258,"offset":0,"share":100},{"id":2263,"offset":0,"share":100},{"id":2268,"offset":0,"share":100},{"id":2271,"offset":0,"share":100},{"id":2274,"offset":0,"share":100},{"id":2281,"offset":0,"share":100},{"id":2290,"offset":0,"share":100},{"id":2293,"offset":0,"share":100},{"id":2294,"offset":0,"share":100},{"id":2298,"offset":0,"share":100},{"id":2305,"offset":0,"share":100},{"id":2307,"offset":0,"share":100},{"id":2308,"offset":0,"share":100},{"id":2311,"offset":0,"share":100},{"id":2317,"offset":0,"share":100},{"id":2318,"offset":0,"share":100},{"id":2319,"offset":0,"share":100},{"id":2322,"offset":0,"share":100},{"id":2325,"offset":0,"share":100},{"id":2327,"offset":0,"share":100},{"id":2332,"offset":0,"share":100},{"id":2335,"offset":0,"share":25},{"id":2337,"offset":0,"share":100},{"id":2340,"offset":0,"share":100},{"id":2342,"offset":0,"share":100},{"id":2346,"offset":0,"share":100},{"id":2348,"offset":0,"share":100},{"id":2349,"offset":0,"share":100},{"id":2350,"offset":0,"share":100},{"id":2351,"offset":0,"share":100},{"id":2354,"offset":0,"share":100},{"id":2355,"offset":0,"share":100},{"id":2357,"offset":0,"share":100},{"id":2362,"offset":0,"share":100},{"id":2363,"offset":0,"share":100},{"id":2366,"offset":0,"share":100},{"id":2367,"offset":0,"share":100},{"id":2371,"offset":0,"share":100},{"id":2372,"offset":0,"share":100},{"id":2374,"offset":0,"share":100},{"id":2376,"offset":0,"share":100},{"id":2377,"offset":0,"share":10},{"id":2378,"offset":0,"share":100},{"id":2383,"offset":0,"share":100},{"id":2389,"offset":0,"share":100},{"id":2391,"offset":0,"share":100},{"id":2393,"offset":0,"share":100},{"id":2394,"offset":0,"share":25},{"id":2395,"offset":0,"share":100},{"id":2397,"offset":0,"share":100},{"id":2398,"offset":0,"share":100},{"id":2399,"offset":0,"share":100},{"id":2401,"offset":0,"share":100},{"id":2404,"offset":0,"share":100},{"id":2406,"offset":0,"share":100},{"id":2409,"offset":0,"share":100},{"id":2410,"offset":0,"share":100},{"id":2411,"offset":0,"share":100},{"id":2412,"offset":0,"share":100},{"id":2415,"offset":0,"share":100},{"id":2416,"offset":0,"share":100},{"id":2419,"offset":0,"share":100},{"id":2422,"offset":0,"share":100},{"id":2423,"offset":0,"share":10},{"id":2424,"offset":0,"share":100},{"id":2425,"offset":0,"share":100},{"id":2427,"offset":0,"share":100},{"id":2430,"offset":0,"share":100},{"id":2434,"offset":0,"share":100},{"id":2439,"offset":0,"share":100},{"id":2440,"offset":0,"share":100},{"id":2441,"offset":0,"share":100},{"id":2444,"offset":0,"share":100},{"id":2446,"offset":0,"share":100},{"id":2447,"offset":0,"share":10},{"id":2448,"offset":0,"share":100},{"id":2449,"offset":0,"share":100},{"id":2450,"offset":0,"share":100},{"id":2451,"offset":0,"share":100},{"id":2454,"offset":0,"share":100},{"id":2456,"offset":0,"share":100},{"id":2458,"offset":0,"share":100},{"id":2461,"offset":0,"share":100},{"id":2463,"offset":0,"share":100},{"id":2466,"offset":0,"share":100},{"id":2467,"offset":0,"share":100},{"id":2474,"offset":0,"share":1},{"id":2476,"offset":0,"share":100},{"id":2480,"offset":0,"share":100},{"id":2482,"offset":0,"share":100},{"id":2485,"offset":0,"share":100},{"id":2488,"offset":0,"share":100},{"id":2497,"offset":0,"share":100},{"id":2498,"offset":0,"share":100},{"id":2500,"offset":0,"share":100},{"id":2502,"offset":0,"share":100},{"id":2505,"offset":0,"share":100},{"id":2506,"offset":0,"share":100},{"id":2507,"offset":0,"share":100},{"id":2508,"offset":0,"share":60},{"id":2509,"offset":0,"share":100},{"id":2517,"offset":0,"share":100},{"id":2520,"offset":0,"share":100},{"id":2521,"offset":0,"share":100},{"id":2522,"offset":0,"share":100},{"id":2524,"offset":0,"share":100},{"id":2525,"offset":0,"share":100},{"id":2526,"offset":0,"share":100},{"id":2532,"offset":0,"share":1},{"id":2535,"offset":0,"share":100},{"id":2536,"offset":0,"share":100},{"id":2538,"offset":0,"share":100},{"id":2546,"offset":0,"share":100},{"id":2547,"offset":0,"share":100},{"id":2550,"offset":0,"share":100},{"id":2552,"offset":0,"share":100},{"id":2555,"offset":0,"share":100},{"id":2557,"offset":0,"share":100},{"id":2559,"offset":0,"share":100},{"id":2561,"offset":0,"share":100},{"id":2563,"offset":0,"share":100},{"id":2578,"offset":0,"share":100},{"id":2579,"offset":0,"share":100},{"id":2582,"offset":0,"share":100},{"id":2584,"offset":0,"share":100},{"id":2587,"offset":0,"share":100},{"id":2588,"offset":0,"share":100},{"id":2591,"offset":0,"share":100},{"id":2592,"offset":0,"share":100},{"id":2595,"offset":0,"share":100},{"id":2601,"offset":0,"share":100},{"id":2602,"offset":0,"share":100},{"id":2606,"offset":0,"share":10},{"id":2612,"offset":0,"share":50},{"id":2617,"offset":0,"share":5},{"id":2620,"offset":0,"share":25},{"id":2623,"offset":0,"share":100},{"id":2641,"offset":0,"share":100},{"id":2650,"offset":0,"share":100},{"id":2655,"offset":0,"share":1},{"id":2656,"offset":0,"share":100},{"id":2657,"offset":0,"share":50},{"id":2659,"offset":0,"share":50},{"id":2662,"offset":0,"share":25},{"id":2663,"offset":0,"share":50}],"settings":[{"id":0,"value":"VRR1TASCLT*|odsp35*|VNBP101*|*\\Abby|*\\moeuser|moeuser|*\\drxaccount|drxaccount|*\\TASClient|TASClient|PYXIDIS\\pulsar|PYXIDIS\\tank|LocalAdminUser|AdminUAC|*\\cloudtest|cloudtest|NTDEV\\ntlab"},{"id":1,"value":"0x8004de25|0x0000de2a|0x8004de40|0x8004de42|0x8004de43|0x8004de44|0x8004de85|0x8004de8b|0x8004deb2|0x8004deb6|0x8004dea0|0x8004deaa|0x8004deac|0x8004deae|0x8004deaf|0x8004dea3|0x8004dea9"},{"id":10,"value":"0"},{"id":105,"value":"-1071316797|-1071316963|-2147164539"},{"id":108,"value":"0x8004de40|0x8004de81|0x00000001"},{"id":109,"value":"350000"},{"id":11,"value":"desktop.ini|thumbs.db|Microsoft Edge.lnk"},{"id":110,"value":"3600"},{"id":111,"value":"604800"},{"id":114,"value":"2"},{"id":117,"value":"7200000 "},{"id":118,"value":"300"},{"id":119,"value":"2048"},{"id":120,"value":"2048"},{"id":121,"value":"fpc.msedge.net\/conf\/v2\/odsync\/fpconfig.min.json"},{"id":122,"value":"100"},{"id":123,"value":"127116"},{"id":124,"value":"6"},{"id":125,"value":"Other"},{"id":127,"value":"1"},{"id":128,"value":"10"},{"id":129,"value":"6300000 "},{"id":130,"value":"120"},{"id":131,"value":"clients.config.office.net\/user\/v1.0\/windows\/ack"},{"id":132,"value":"roaming.officeapps.live.com\/rs\/RoamingSoapService.svc"},{"id":133,"value":"clients.config.office.net\/user\/v1.0\/windows\/policies"},{"id":134,"value":"roaming.officeapps.live.com\/rs\/RoamingSoapService.svc"},{"id":137,"value":"30"},{"id":138,"value":"600"},{"id":139,"value":"3"},{"id":14,"value":"600 "},{"id":140,"value":"14400"},{"id":143,"value":"604800"},{"id":144,"value":"14400"},{"id":145,"value":"10"},{"id":149,"value":"[{\n \"name\": \"OD_CUSTOM_PROFILE\",\n \"rules\": [\n { \"netCost\": \"restricted\", \"timers\": [ -1, -1, -1 ] },\n { \"netCost\": \"high\", \"powerState\": \"unknown\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"high\", \"powerState\": \"battery\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"high\", \"powerState\": \"charging\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"low\", \"powerState\": \"unknown\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"low\", \"powerState\": \"battery\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"low\", \"powerState\": \"charging\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"unknown\", \"powerState\": \"unknown\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"unknown\", \"powerState\": \"battery\", \"timers\": [ 300, 30, 10 ] },\n { \"netCost\": \"unknown\", \"powerState\": \"charging\", \"timers\": [ 300, 30, 10 ] },\n { \"timers\": [ -1, -1, -1 ] }\n ]\n}]"},{"id":15,"value":"1209600"},{"id":150,"value":"fpc.msedge.net\/conf\/v2\/odsync2\/fpconfig.min.json"},{"id":151,"value":"pst,nst,ost"},{"id":152,"value":"*.laccdb|*.tpm|thumbs.db|EhThumbs.db|Desktop.ini|.DS_Store|Icon\\r|.lock|.849C9593-D756-4E56-8D6E-42412F2A707B"},{"id":155,"value":"pst,nst,ost"},{"id":158,"value":"1"},{"id":159,"value":"604800"},{"id":16,"value":"|one|onepkg|onetoc|onetoc2|"},{"id":160,"value":"604800"},{"id":161,"value":"1"},{"id":162,"value":"43200"},{"id":163,"value":"21600"},{"id":164,"value":"3"},{"id":165,"value":"90"},{"id":166,"value":"120"},{"id":167,"value":"15"},{"id":168,"value":"120000"},{"id":169,"value":"1.2.0.9"},{"id":17,"value":"|doc|docm|docx|odt|odp|pps|ppsm|ppsx|ppt|pptm|pptx|vsd|vsdx|ods|xls|xlsb|xlsm|xlsx|"},{"id":170,"value":"https:\/\/clients.config.office.net\/collector\/v1.0\/inventoryodb"},{"id":178,"value":"-895221759|-2147024809|-2147023508|-2147023579|-2147164433|-2147164592|-2147162950"},{"id":179,"value":"0"},{"id":18,"value":"|pst|"},{"id":180,"value":"0.01"},{"id":181,"value":"0.03"},{"id":182,"value":"3"},{"id":183,"value":"30"},{"id":184,"value":"10"},{"id":185,"value":"ar;bg;ca;cs;da;de;el;en;en-GB;en-US;es;et;eu;fi;fr;gl;he;hi;hr;hu;id;it;ja;kk;ko;lt;lv;ms;nb-NO;nl;pl;pt-BR;pt-PT;ro;ru;sk;sl;sr-Cyrl-RS;sr-Latn-RS;sv;th;tr;uk;vi;zh-CN;zh-TW;"},{"id":187,"value":"lnk|xlsx|xls|url|exe|zip|rar|rdp|appref-ms|msi|website|xlsm|xml|xlsb|pub|mht|accdb|bak|reg|mpp|ini|pbix|mdb|indd|nal|dwg|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|mov|oxps|stp|dpk"},{"id":188,"value":"1440"},{"id":189,"value":"7200000"},{"id":19,"value":"22528"},{"id":190,"value":"1800000"},{"id":191,"value":"0.05"},{"id":192,"value":"|pdf:20|accdb:20|exe:20|mp4:60|mdb:20|pst:1200|myox:15|"},{"id":195,"value":"900 "},{"id":2,"value":"0x8004de40|0x8004de42|0x8004de85|0x8004de8b|0x8004deb6|0x8004de9b|0x8004ded0|0x8004ded2|0x8004de45|0x8004de8a|0x8004ded5"},{"id":20,"value":"133120"},{"id":201,"value":"lnk|xlsx|xls|xlsb|xlsm|docx|doc|docm|pptx|pub|url|exe|zip|rar|rdp|appref-ms|msi|website|txt|msg|xml|mht|accdb|csv|wav|bak|reg|mpp|html|pst|ini|pbix|mdb|indd|nal|dwg|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|one|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|oxps|stp|dpk"},{"id":204,"value":"6|37|78|79|80|106|107|146|151|155|178|179|182|193|208|232|256|283|300|349|372|376|379|406|417|420|428|432|466|479|484|522|532|533|541|550|584|588|591|592|616|618|629|653|655|685|688|707|715|729|733|758|766|767|797|804|835|848|854|872|875|882|885|895|903|910|923|938|969|990|998|1006|1007|1009|1011|1012|1030|1040|1045|1049|1050|1087|1096|1099|1142|1147|1149|1154|1171|1194|1197|1207|1208|1209|1214|1273|1280|1288|1303|1313|1349|1366|1387|1423|1466|1507|1514|1533|1551|1602|1650|1654|1704|1708|1709|1722|1734|1741|1761|1762|1785|1787|1802|1811|1834|1835|1839|1845|1846|1856|1857|1858|1865|1867|1868|1871|1883|1892|1897|1898|1908|1910|1914|1922|1929|1937|1945|1946|1949|1984|1999|2043|2047|2052|2053|2062|2083|2094|2103|2107|2121|2125|2140|2160|2177|2180|2186|2195|2206|2216|2232|2233|2240|2251|2253|2268|2290|2303|2312|2313|2317|2328|2339|2363|2373|2395|2419|2433|2440|2447|2455|2456|2507|2553|2559|2579|2597|2601|2607|2630|2635|2648|2665|2678|2698|2705|2713|2729|2742|2760|2761|2765|2770|2772|2785|2847|2875|2887|2908|2921|2950|2992|3009|3013|3034|3054|3055|3069|3085|3097|3108|3139|3164|3171|3179|3189|3202|3210|3246|3254|19999"},{"id":205,"value":"dwg"},{"id":206,"value":"bak"},{"id":208,"value":"14"},{"id":209,"value":"0.0"},{"id":21,"value":"lnk|xlsx|xls|xlsb|xlsm|docx|doc|docm|pptx|pub|url|exe|zip|rar|rdp|appref-ms|msi|website|txt|msg|xml|mht|accdb|csv|wav|bak|reg|mpp|html|pst|ini|pbix|mdb|indd|nal|dwg|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|one|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|oxps|stp|dpk"},{"id":210,"value":"0.0"},{"id":213,"value":"20"},{"id":214,"value":"180"},{"id":216,"value":"VaultUnlockScenario:-2144272294;AddMountedFolderScenario:38;"},{"id":22,"value":"minCountForConsideration:6"},{"id":222,"value":"15"},{"id":223,"value":"Level:Request,Verbose:Rotate:1\/100;\nName:ReportChangeEnumerationTimeDelay:Rotate:1\/30;\nScenario:ThumbnailScenario,StartOCSIScenario,UploadScenario,DownloadScenario,UploadMetadataScenario,UploadMetadataBatchScenario:Rotate:1\/30;\nScenario:Upload,MetadataDownload,Download:Rotate:1\/2;\nApi:ProcessLocalChange*:Random:0.0001;\nApi:UXMacLocalization:Random:0.0001;\nName:ScenarioHeaderMissing:Rotate:1\/20;\nApi:LoggingScenarioReporting:Rotate:1\/30;\nName:StorageProviderUriSourceResult,CrossScopeMoveBytesTransferred,UpdateRingSource,StorageApiScenarioHeaderDiffersInTrace,FALDeleteCompletion,DeviceHealthScore,OOBERequestHandlerClientKFMUpsellState:Rotate:0\/1;\nName:CloudFilesApiResult:Rotate:1\/100;\nApi:SyncPerfScenario:Rotate:0\/1;\nApi:MacboxFPEnumChangesCompleteWorkingSet:Rotate:1\/10;\nApi:MacboxFPExtFALConnectionFetch,MacboxFPExtFetchComplete:Rotate:1\/2;\nApi:ReparentChildrenOfFolderInRecycleBin:Random:0.1;\nName:IdleJobExecutionDelayed:Random:0.0001;\nName:RealizerChangeInterpreterFilterBackfill:Random:0.01;\nName:UploadCxPUnableToResolveToken:Random:0.001;\nApi:MacboxUserVisibleFetch:Random:0.01;\nName:RealizerAwareChangeEnumerationStatsResult:Random:10.0;\nName:ChangeEnumerationMissingQuotaState:Random:10.0;\nFunnel:Infrastructure:Rotate:1%+1\/100;\nFunnel:hiddenRoot:Rotate:1%+1\/100;\nName:OOBERequestHandlerSyncClientSignInState:Random:0.0001;\nApi:WinboxConvertToPlaceholder:Random:1.0;\nApi:UploadCxPGetTokenFromPath:Random:1.0;\nNucleus:FonDSyncInit:Random:0.01;\nNucleus:AutoStartStatus:Random:0.01;\nNucleus:AuthAcquireTokenSilently:Random:0.25;\nStallError:NewStall_*:Random:0.1;\nApi:RetrieveProperties,getonedrivesigninstate,GetPropertyHandlerFromPath,SaveProperties,getkfmupsellstate,GetStatusUI,GetPropertyHandlerFromUri:Random:0.1;"},{"id":226,"value":"1.2.0.16"},{"id":227,"value":"1.2.1.1"},{"id":228,"value":" "},{"id":229,"value":"21.109.0530.0001"},{"id":231,"value":"lnk|xlsx|xls|xlsb|xlsm|pub|url|exe|zip|rar|rdp|appref-ms|msi|website|msg|xml|mht|accdb|csv|wav|bak|reg|mpp|pst|ini|pbix|mdb|indd|nal|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|one|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|oxps|stp|dpk"},{"id":232,"value":"lnk|xlsx|xls|xlsb|xlsm|pub|url|exe|zip|rar|rdp|appref-ms|msi|website|msg|xml|mht|accdb|csv|wav|bak|reg|mpp|pst|ini|pbix|mdb|indd|nal|saz|oft|cer|pfx|dll|nfo|ics|rdg|vsdx|tsv|config|partial|script|one|kql|evtx|har|csl|ipynb|webm|iso|tm7|ts|application|nupkg|cab|oxps|stp|dpk"},{"id":233,"value":"2.9.7653.47581"},{"id":237,"value":"50"},{"id":238,"value":"900|300|600|900"},{"id":24,"value":"4"},{"id":240,"value":"3600"},{"id":241,"value":"10000"},{"id":243,"value":"900"},{"id":244,"value":"900"},{"id":245,"value":"P1D"},{"id":246,"value":"200000"},{"id":249,"value":"300000"},{"id":25,"value":"15"},{"id":250,"value":"20"},{"id":251,"value":"180"},{"id":252,"value":"5"},{"id":253,"value":"180"},{"id":254,"value":"1"},{"id":26,"value":"100"},{"id":269,"value":"25|26|27|29|19|10|23|30|35|14,22.235.1109.0001"},{"id":273,"value":"250000"},{"id":274,"value":"100000"},{"id":283,"value":"siteUrl|listId"},{"id":284,"value":"100,siteUrl=https?:\\\/\\\/(www\\.)?laposte\\.sharepoint\\.com\\b(.*),INF,lh-lap|100,siteUrl=.*\\s.*,24.178.0903.0001,lh-sws|100,listId=acc3ba2d-929f-41d1-aee5-4c99be7b0277,INF,ln-lh|100,listId=a0fec449-25ba-4637-97d6-57660475b73b,INF,ln-lo|100,listId=2a7093aa-c228-4672-a093-aa7f86b3e13b,INF,ln-lo"},{"id":285,"value":"ModernListTemplateTypeId|ClientFormCustomFormatter|ContentTypeIdToNameMap|isModerated|listName|FormRenderModes|EnableMinorVersions"},{"id":286,"value":"100,ModernListTemplateTypeId=3a867b4a-7429-0e1a-b02e-bf4b240ff1ce,INF,tm-pl|100,ModernListTemplateTypeId=b117a022-9f8b-002d-bda8-fa266f0ff1ce,22.176.0821.0001,tm-pro|100,ModernListTemplateTypeId=a5126f70-467d-4257-954b-95fba9bb008c,22.176.0821.0001,tm-pro|100,ModernListTemplateTypeId=3a7c53be-a128-0ff9-9f97-7b6f700ff1ce,22.176.0821.0001,tm_rec|100,ModernListTemplateTypeId=92946f48-bed9-4299-825d-dc3768f59d54,22.176.0821.0001,tm_rec|100,ModernListTemplateTypeId=9a429811-2ab5-07bc-b5a0-2de9590ff1ce,22.176.0821.0001,tm-co|100,ModernListTemplateTypeId=bd8bdab7-5730-4f57-9050-0bd66c988b15,22.176.0821.0001,tm-co|100,ContentTypeIdToNameMap=.*:.*:.*,22.055.0313.0001,ct|100,listName=.ACC3BA2D-929F-41D1-AEE5-4C99BE7B0277.,INF,ln-la|100,FormRenderModes=.*:.*:.*\"RenderType\" : 3.*,INF,frn|100,EnableMinorVersions=true,INF,emv"},{"id":287,"value":"ClientSideComponentProperties|SchemaXml|Formula|TypeAsString|InternalName"},{"id":288,"value":"100,ClientSideComponentProperties=^(?!null).*,22.002.0103.0004|100,SchemaXml=.*AppendOnly.\\\"TRUE\\\".*Type.\\\"Note\\\".*,22.222.1023.0001,notes|100,SchemaXml=.*Type.\\\"Note\\\".*AppendOnly.\\\"TRUE\\\".*,22.222.1023.0001,notes|100,Formula=.+,22.025.0202.0001,frml|100,TypeAsString=TaxonomyFieldTypeMulti,INF,tax-mlt|100,InternalName=_ApprovalStatus,INF,ap_st|100,TypeAsString=Likes,INF,rtg"},{"id":289,"value":"modernType|viewXml|query"},{"id":290,"value":"100,modernType=KANBAN,21.229.1104.0001,Kanban|100,viewXml=.*.+<\/CustomOrder>.*,INF,cu-ord|100,modernType=TILES,22.045.0227.0001,tiles|100,query=.*.*.+<\/Value><\/Eq>.*<\/Where>.*,INF,ca-fil|100,viewXml=.*.*.*<\/ViewFields>.*,INF,ms-img,ALL,FILES"},{"id":291,"value":"TimeZone_Id|RegionalSetting_Locale"},{"id":292,"value":"100,TimeZone_Id=^5[3-9],21.230.1107.0004,tz|100,TimeZone_Id=^[6-9]\\d,21.230.1107.0004,tz|100,TimeZone_Id=^\\d{3},21.230.1107.0004,tz|100,RegionalSetting_Locale=^1025|100,RegionalSetting_Locale=^1052|100,RegionalSetting_Locale=^1098|100,RegionalSetting_Locale=^1164|100,RegionalSetting_Locale=^2068|100,RegionalSetting_Locale=^6170|100,RegionalSetting_Locale=^7194|100,RegionalSetting_Locale=^8218|100,RegionalSetting_Locale=^12314|100,RegionalSetting_Locale=^102[68],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^103[47],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^104[12467],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^105[2467],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^106[2-68],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1079,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^108[0-36],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^108[89],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^109[0-79],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^110[0-8],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^111[014578],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^112[1-58],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^113[0-6],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^114[468],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^115[02-9],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^116[049],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^2049,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^20[56]8,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^207[07],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^209[24],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^210[78],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^211[057],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^2128,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^214[13],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^2155,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^307[36],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^3131,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^3179,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^4097,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^410[03],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^4106,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^4122,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^4155,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^512[147],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^513[02],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^5146,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^5179,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^6145,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^615[46],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^6170,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^6203,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^7169,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^717[78],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^7194,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^7227,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^8193,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^820[12],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^8218,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^8251,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^9217,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^922[56],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^9242,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^9275,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1024[19],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^10250,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^10266,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^11265,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1127[34],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^11290,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^12289,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1229[78],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^12314,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^13313,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1332[12],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^14337,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^14346,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^15361,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^15370,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^16385,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1639[34],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1741[78],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1844[12],INF,dis-loc,MACOS|100,RegionalSetting_Locale=^19466,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^20490,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^21514,INF,dis-loc,MACOS|100,RegionalSetting_Locale=^1026,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1029,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1035,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1036,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1038,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1044,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1045,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1047,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1049,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1051,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1052,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1053,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1058,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1059,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1061,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1062,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1063,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1064,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1074,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1076,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1078,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1079,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1083,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1087,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1088,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1090,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1091,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1092,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1132,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1133,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1134,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1150,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1154,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1155,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1156,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1157,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^1160,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2055,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2064,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2068,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2070,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2077,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2092,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2107,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2115,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^2143,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^3079,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^3084,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^3131,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^4108,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^4155,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^5127,22.146.0710.0001,wr-enc|100,RegionalSetting_Locale=^102[6-79],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^103[0-24-68-9],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^104[03-689],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^105[0-357-9],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^106[0-68-9],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^107[0-18-9],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^108[037-8],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^109[0-2],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^1108,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^1110,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^112[2-3],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^113[13-5],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^1146,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^115[04-79],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^116[04],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^206[07-8],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^207[07],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^209[24],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^2107,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^211[05],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^2143,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^2155,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^3079,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^308[24],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^3131,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^410[38],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^4122,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^4155,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^513[02],21.270.0102.0001,frmt|100,RegionalSetting_Locale=^5146,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^5179,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^6156,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^6170,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^6203,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^7177,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^7194,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^7227,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^8202,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^8218,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^8251,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^9226,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^9242,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^9275,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^10266,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^11274,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^11290,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^12298,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^12314,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^13322,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^14346,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^15370,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^16394,21.270.0102.0001,frmt|100,RegionalSetting_Locale=^102[679],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^103[02578],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^104[4-689],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^105[014578],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^106[1-3689],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^1071,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^108[167],22.033.0213.0001,frmt|100,RegionalSetting_Locale=^1106,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^1110,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^1152,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^2049,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^2070,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^2108,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^2110,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^3073,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^4097,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^4122,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^5121,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^5146,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^6145,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^7169,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^8193,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^9217,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^9242,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^10241,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^10266,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^11265,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^11290,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^12289,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^13313,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^14337,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^15361,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^16385,22.033.0213.0001,frmt|100,RegionalSetting_Locale=^16393,22.040.0220.0001,frmt|100,RegionalSetting_Locale=^1029,INF,alt-sep|100,RegionalSetting_Locale=^1042,INF,dis-loc"},{"id":294,"value":"604800"},{"id":297,"value":"ctxId|tick|expirationDateTime|ClientForms|notificationUrl|subscribeID|lastItemModifiedTime|PageContextInfo"},{"id":30,"value":"30"},{"id":302,"value":"60"},{"id":303,"value":"0"},{"id":304,"value":"&CallerScenarioId={Scenario}&CallerId={Caller}"},{"id":305,"value":"8192"},{"id":306,"value":"2"},{"id":309,"value":"Linear"},{"id":310,"value":"2"},{"id":311,"value":"2"},{"id":318,"value":"500"},{"id":320,"value":"65535"},{"id":321,"value":"600000"},{"id":322,"value":"2"},{"id":323,"value":"5"},{"id":324,"value":"30"},{"id":325,"value":"22.012.0116.0001"},{"id":329,"value":"100"},{"id":330,"value":"0x8004da9a|0x8004da12|0x8004da17"},{"id":331,"value":"|db:60|package:60|db-wal:60|accdb:30|log:30|txt:30|"},{"id":334,"value":"RuntimeBroker.exe"},{"id":36,"value":"40"},{"id":37,"value":"4096"},{"id":38,"value":"10240"},{"id":39,"value":"5120"},{"id":40,"value":"133120"},{"id":41,"value":"|pst|"},{"id":42,"value":"|pst|"},{"id":43,"value":"|one|onepkg|onetoc|onetoc2|"},{"id":45,"value":"200"},{"id":46,"value":"18.168.0820.0001"},{"id":47,"value":"18.168.0820.0001"},{"id":48,"value":"100"},{"id":49,"value":"1534956090"},{"id":5,"value":"0"},{"id":51,"value":"7200 "},{"id":52,"value":"7200"},{"id":53,"value":"2 "},{"id":538,"value":"0,Etc\/UTC|1,Etc\/GMT|2,Europe\/London|3,Europe\/Paris|4,Europe\/Berlin|5,Europe\/Bucharest|6,Europe\/Budapest|7,Europe\/Minsk|8,America\/Sao_Paulo|9,America\/Halifax|10,America\/New_York|11,America\/Chicago|12,America\/Denver|13,America\/Los_Angeles|14,America\/Anchorage|15,Pacific\/Honolulu|16,Pacific\/Apia|17,Pacific\/Auckland|18,Australia\/Brisbane|19,Australia\/Adelaide|20,Asia\/Tokyo|21,Asia\/Singapore|22,Asia\/Bangkok|23,Asia\/Calcutta|24,Asia\/Dubai|25,Asia\/Tehran|26,Asia\/Baghdad|27,Asia\/Jerusalem|28,America\/St_Johns|29,Atlantic\/Azores|30,Etc\/GMT+2|31,Atlantic\/Reykjavik|32,America\/Cayenne|33,America\/La_Paz|34,America\/Indianapolis|35,America\/Bogota|36,America\/Regina|37,America\/Mexico_City|38,America\/Phoenix|39,Etc\/GMT+12|40,Pacific\/Fiji|41,Pacific\/Guadalcanal|42,Australia\/Hobart|43,Pacific\/Port_Moresby|44,Australia\/Darwin|45,Asia\/Shanghai|46,Asia\/Novosibirsk|47,Asia\/Tashkent|48,Asia\/Kabul|49,Africa\/Cairo|50,Africa\/Johannesburg|51,Europe\/Moscow|53,Atlantic\/Cape_Verde|54,Asia\/Baku|55,America\/Guatemala|56,Africa\/Nairobi|57,Europe\/Warsaw|58,Asia\/Yekaterinburg|59,Europe\/Kiev|60,America\/Godthab|61,Asia\/Rangoon|62,Asia\/Katmandu|63,Asia\/Irkutsk|64,Asia\/Krasnoyarsk|65,America\/Santiago|66,Asia\/Colombo|67,Pacific\/Tongatapu|68,Asia\/Vladivostok|69,Africa\/Lagos|70,Asia\/Yakutsk|71,Asia\/Almaty|72,Asia\/Seoul|73,Australia\/Perth|74,Asia\/Riyadh|75,Asia\/Taipei|76,Australia\/Sydney|77,America\/Chihuahua|78,America\/Tijuana|79,Asia\/Amman|80,Asia\/Beirut|81,America\/Cuiaba|82,Asia\/Tbilisi|83,Africa\/Windhoek|84,Asia\/Yerevan|85,America\/Buenos_Aires|86,Africa\/Casablanca|87,Asia\/Karachi|88,America\/Caracas|89,Indian\/Mauritius|90,America\/Montevideo|91,America\/Asuncion|92,Asia\/Kamchatka|93,Etc\/UTC|94,Asia\/Ulaanbaatar|95,Etc\/GMT+11|96,Etc\/GMT+2|97,Etc\/GMT-12|98,Asia\/Damascus|99,Asia\/Magadan|100,Europe\/Kaliningrad|101,Europe\/Istanbul|102,Asia\/Dhaka|103,America\/Bahia|104,Europe\/Chisinau|106,Europe\/Samara|107,Asia\/Srednekolymsk|108,Asia\/Kamchatka|109,Europe\/Minsk|110,Europe\/Astrakhan|111,Asia\/Barnaul|112,Asia\/Tomsk|114,Asia\/Sakhalin|115,Asia\/Omsk"},{"id":539,"value":"5121|15361|3073|2049|11265|13313|12289|4097|6145|8193|16385|1025|10241|7169|14337|9217|1068|1069|8218|5146|1026|1027|2052|3076|5124|4100|1028|4122|1050|1029|1030|1164|2067|1043|3081|10249|4105|9225|16393|6153|8201|17417|5129|13321|18441|7177|11273|2057|1033|12297|1061|1035|2060|3084|1036|5132|6156|4108|1110|3079|1031|5127|4103|2055|1032|1037|1081|1038|1057|2108|1040|2064|1041|1087|1042|1062|1063|1071|1086|2110|1044|2068|1045|1046|2070|1048|1049|7194|12314|10266|6170|11290|9242|1051|11274|16394|13322|9226|5130|7178|12298|17418|4106|18442|2058|19466|6154|15370|10250|20490|1034|3082|21514|14346|8202|1053|2077|1054|1055|1058|1066|1106"},{"id":540,"value":"1093|2052|3076|5124|4100|1028|1095|1081|1041|1099|1111|1102|1096|1103|1097|1098|1152|1042"},{"id":541,"value":"1052|1118|1101|2117|1093|2052|4100|1028|1164|1125|3081|4105|9225|16393|6153|8201|17417|5129|13321|18441|11273|2057|1033|1124|1032|1095|1037|1081|2141|1117|1041|1099|1158|1111|1042|1086|2110|1100|1153|1102|1148|1121|1096|1065|1094|1131|3179|1103|9226|7178|2058|6154|20490|21514|14346|8202|1114|1097|1098|1054|1056|1152|1066|1144|5121|15361|3073|2049|11265|13313|12289|4097|6145|8193|16385|1025|10241|7169|14337|9217"},{"id":543,"value":"2067=%d %B|1043=%d %B|2052=%m月%dę—„|3076=%m月%dę—„|5124=%m月%dę—„|4100=%m月%dę—„|1028=%m月%dę—„|1053=den %d %B|2077=den %d %B|2060=%d %B|3084=%d %B|1036=%d %B|5132=%d %B|6156=%d %B|4108=%d %B|3079=%d. %B|1031=%d. %B|5127=%d. %B|4103=%d. %B|2055=%d. %B|1040=%d %B|2064=%d %B|1041=%m月%dę—„|1042=%B %dģ¼|1049=%d %B|11274=%d de %B|16394=%d de %B|13322=%d de %B|9226=%d de %B|5130=%d de %B|7178=%d de %B|12298=%d de %B|17418=%d de %B|4106=%d de %B|18442=%d de %B|2058=%d de %B|19466=%d de %B|6154=%d de %B|15370=%d de %B|10250=%d de %B|20490=%d de %B|1034=%d de %B|3082=%d de %B|21514=%d de %B|14346=%d de %B|8202=%d de %B|2070=%d de %B|1046=%d de %B|1037=%d %B|1030=%d. %B|1044=%d. %B|1048=%d %B|5121=%d %B|15361=%d %B|3073=%d %B|2049=%d %B|11265=%d %B|13313=%d %B|12289=%d %B|4097=%d %B|6145=%d %B|8193=%d %B|16385=%d %B|10241=%d %B|7169=%d %B|14337=%d %B|9217=%d %B|1068=%d %B|1069=%B %d|8218=%d. %B|5146=%d. %B|1026=%d %B|1027=%d %B|4122=%d. %B|1050=%d. %B|1029=%d. %B|1061=%d. %B|1035=%d. %Bta|1110=%d de %B|1032=%d %B|1081=%d %B|1038=%B %d.|1057=%d %B|2108=%d %B|1062=%d. %B|1071=%d %B|2110=%d %B|1086=%d %B|2068=%d. %B|1045=%d %B|7194=%d. %B|12314=%d. %B|10266=%d. %B|6170=%d. %B|11290=%d. %B|9242=%d. %B|1051=%d. %B|1054=%d %B|1055=%d %B|1058=%d %B|1066=%d %B|1106=%B %d|1087=%d %B|1063=%B %d d."},{"id":544,"value":"2067=%d %B %Y|1043=%d %B %Y|2052=%y幓%m月%dę—„|3076=%y幓%m月%dę—„|5124=%y幓%m月%dę—„|4100=%y幓%m月%dę—„|1028=%y幓%m月%dę—„|1053=den %d %B %Y|2077=den %d %B %Y|2060=%d %B %Y|3084=%d %B %Y|1036=%d %B %Y|5132=%d %B %Y|6156=%d %B %Y|4108=%d %B %Y|3079=%d.%m.%Y|1031=%d.%m.%Y|5127=%d.%m.%Y|4103=%d.%m.%Y|2055=%d.%m.%Y|1040=%d %B %Y|2064=%d %B %Y|1041=%Y幓%Om月%dę—„|1042=%Yė…„ %mģ›” %dģ¼|1049=%d.%m.%Y|11274=%d\/%m\/%Y|16394=%d\/%m\/%Y|13322=%d-%m-%Y|9226=%d\/%m\/%Y|5130=%d\/%m\/%Y|7178=%d\/%m\/%Y|12298=%d\/%m\/%Y|17418=%d\/%m\/%Y|4106=%d\/%m\/%Y|18442=%d\/%m\/%Y|2058=%d\/%m\/%Y|19466=%d\/%m\/%Y|6154=%m\/%d\/%Y|15370=%d\/%m\/%Y|10250=%d\/%m\/%Y|20490=%m\/%d\/%Y|1034=%d\/%m\/%Y|3082=%d\/%m\/%Y|21514=%m\/%d\/%Y|14346=%d\/%m\/%Y|8202=%d\/%m\/%Y|2070=%d\/%m\/%Y|1046=%d de %B de %Y|1037=%d %B %Y|1030=%d. %B %Y|1044=%d. %B %Y|1048=%d %B %Y|5121=%d-%m-%Y|15361=%d\/%m\/%Y|3073=%d\/%m\/%Y|2049=%d\/%m\/%Y|11265=%d\/%m\/%Y|13313=%d\/%m\/%Y|12289=%d\/%m\/%Y|4097=%d\/%m\/%Y|6145=%d-%m-%Y|8193=%d\/%m\/%Y|16385=%d\/%m\/%Y|10241=%d\/%m\/%Y|7169=%d-%m-%Y|14337=%d\/%m\/%Y|9217=%d\/%m\/%Y|1068=%d %B %Y|1069=%Y\/%m\/%d|8218=%d. %B %Y|5146=%d. %B %Y|1026=%d %B %Y г.|1027=%d\/%m\/%Y|4122=%d. %B %Y.|1050=%d. %B %Y.|1029=%d.%m.%Y|1061=%d. %B %Y|1035=%d.%m.%Y|1110=%d\/%m\/%Y|1032=%d %B %Y|1081=%d %B %Y|1038=%B %d., %Y|1057=%d %B %Y|2108=%d %B, %Y|1062=%Y. gada %d. %B|1071=%d %B %Y|2110=%d %B %Y|1086=%d %B %Y|2068=%d. %B %Y|1045=%d %B %Y|7194=%d. %B %Y|12314=%d. %B %Y|10266=%d. %B %Y|6170=%d. %B %Y|11290=%d. %B %Y|9242=%d. %B %Y|1051=%d. %m. %Y|1054=%d %B %Y|1055=%d %B %Y|1058=%d %B %Y р.|1066=%d %B %Y|1106=%B %d %Y|1087=%d %B %Y ж.|1063=%Y m. %B %d d."},{"id":547,"value":"https:\/\/clients.config.office.net\/user\/v1.0\/tenantassociationkey"},{"id":549,"value":"43200"},{"id":550,"value":"3600"},{"id":551,"value":"30"},{"id":552,"value":"25.0"},{"id":553,"value":"600"},{"id":556,"value":"16393=%I.%M %p"},{"id":560,"value":"1045=stycznia;lutego;marca;kwietnia;maja;czerwca;lipca;sierpnia;września;paÅŗdziernika;listopada;grudnia|1049=ŃŠ½Š²Š°Ń€Ń;Ń„ŠµŠ²Ń€Š°Š»Ń;марта;Š°ŠæŃ€ŠµŠ»Ń;Š¼Š°Ń;ŠøŃŽŠ½Ń;ŠøŃŽŠ»Ń;Š°Š²Š³ŃƒŃŃ‚Š°;ŃŠµŠ½Ń‚ŃŠ±Ń€Ń;Š¾ŠŗŃ‚ŃŠ±Ń€Ń;Š½Š¾ŃŠ±Ń€Ń;Š“ŠµŠŗŠ°Š±Ń€Ń|5121=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|2049=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|11265=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|12289=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|6145=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|10241=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|7169=ŁŠŁ†Ų§ŁŠŲ±;فبراير;Ł…Ų§Ų±Ų³;Ų£ŲØŲ±ŁŠŁ„;Ł…Ų§ŁŠŁˆ;ŁŠŁˆŁ†ŁŠŁˆ;ŁŠŁˆŁ„ŁŠŁ‡;Ų£ŲŗŲ³Ų·Ų³;Ų³ŲØŲŖŁ…ŲØŲ±;أكتوبر;Ł†ŁˆŁŁ…ŲØŲ±;ŲÆŁŠŲ³Ł…ŲØŲ±|1068=yanvar;fevral;mart;aprel;may;iyun;iyul;avqust;sentyabr;oktyabr;noyabr;dekabr|5146=januar;februar;mart;april;maj;juni;juli;avgust;septembar;oktobar;novembar;decembar|1027=de gener;de febrer;de marƧ;d’abril;de maig;de juny;de juliol;d’agost;de setembre;d’octubre;de novembre;de desembre|4122=siječnja;veljače;ožujka;travnja;svibnja;lipnja;srpnja;kolovoza;rujna;listopada;studenoga;prosinca|1050=siječnja;veljače;ožujka;travnja;svibnja;lipnja;srpnja;kolovoza;rujna;listopada;studenog;prosinca|1029=ledna;Ćŗnora;března;dubna;května;června;července;srpna;zÔří;října;listopadu;prosince|1032=Ιανουαρίου;Φεβρουαρίου;ĪœĪ±ĻĻ„ĪÆĪæĻ…;Απριλίου;ĪœĪ±ĪĪæĻ…;Ιουνίου;Ιουλίου;Ī‘Ļ…Ī³ĪæĻĻƒĻ„ĪæĻ…;Σεπτεμβρίου;ĪŸĪŗĻ„Ļ‰Ī²ĻĪÆĪæĻ…;ĪĪæĪµĪ¼Ī²ĻĪÆĪæĻ…;Δεκεμβρίου|1087=қаңтар;ақпан;Š½Š°ŃƒŃ€Ń‹Š·;сәуір;мамыр;Š¼Š°ŃƒŃŃ‹Š¼;ŃˆŃ–Š»Š“Šµ;тамыз;қыркүйек;қазан;Ņ›Š°Ń€Š°ŃˆŠ°;желтоқсан|1063=sausio;vasario;kovo;balandžio;gegužės;birželio;liepos;rugpjūčio;rugsėjo;spalio;lapkričio;gruodžio|1051=januĆ”ra;februĆ”ra;marca;aprĆ­la;mĆ”ja;jĆŗna;jĆŗla;augusta;septembra;októbra;novembra;decembra|1058=ŃŃ–Ń‡Š½Ń;Š»ŃŽŃ‚Š¾Š³Š¾;Š±ŠµŃ€ŠµŠ·Š½Ń;ŠŗŠ²Ń–Ń‚Š½Ń;Ń‚Ń€Š°Š²Š½Ń;Ń‡ŠµŃ€Š²Š½Ń;Š»ŠøŠæŠ½Ń;ŃŠµŃ€ŠæŠ½Ń;Š²ŠµŃ€ŠµŃŠ½Ń;Š¶Š¾Š²Ń‚Š½Ń;листопаГа;Š³Ń€ŃƒŠ“Š½Ń|8218=januar;februar;mart;april;maj;juni;juli;avgust;septembar;oktobar;novembar;decembar|1164=January;February;March;April;May;June;July;August;September;October;November;December|7194=Ń˜Š°Š½ŃƒŠ°Ń€;Ń„ŠµŠ±Ń€ŃƒŠ°Ń€;март;април;мај;јун;јул;Š°Š²Š³ŃƒŃŃ‚;септембар;октобар;новембар;Гецембар|12314=Ń˜Š°Š½ŃƒŠ°Ń€;Ń„ŠµŠ±Ń€ŃƒŠ°Ń€;март;април;мај;јун;јул;Š°Š²Š³ŃƒŃŃ‚;септембар;октобар;новембар;Гецембар"},{"id":561,"value":"{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_1193|{A3451E43-72DF-4DEE-BFFF-54DD4F76B889}_2222336362|{5B0C1EDE-DB41-41FE-98F2-17FF342847AD}_10201020|{5B0C1EDE-DB41-41FE-98F2-17FF342847AD}_1097|{A3451E43-72DF-4DEE-BFFF-54DD4F76B889}_2046313181|{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_3165353945|{5B0C1EDE-DB41-41FE-98F2-17FF342847AD}_1063|{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_1839700279"},{"id":562,"value":"0.0"},{"id":563,"value":"1052=e paradites;e pasdites|1098=ą°Ŗą±‚ą°°ą±ą°µą°¾ą°¹ą±ą°Ø;ą°…ą°Ŗą°°ą°¾ą°¹ą±ą°Ø"},{"id":564,"value":"8218=nedjelja;ponedjeljak;utorak;srijeda;četvrtak;petak;subota|1164=Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday|2068=sĆøndag;mandag;tirsdag;onsdag;torsdag;fredag;lĆørdag|7194=неГеља;понеГељак;ŃƒŃ‚Š¾Ń€Š°Šŗ;среГа;четвртак;петак;ŃŃƒŠ±Š¾Ń‚Š°|12314=неГеља;понеГељак;ŃƒŃ‚Š¾Ń€Š°Šŗ;среГа;четвртак;петак;ŃŃƒŠ±Š¾Ń‚Š°|6170=nedelja;ponedeljak;utorak;sreda;četvrtak;petak;subota|11290=nedelja;ponedeljak;utorak;sreda;četvrtak;petak;subota"},{"id":566,"value":"a5b7be8e-ef1e-404f-8930-3e88ea835d61|08485f1b-716b-48da-b475-1fae43ade4e0|2e394c55-0b61-4557-9062-e5a9677a9739"},{"id":567,"value":"8"},{"id":568,"value":"100,2"},{"id":57,"value":"200 "},{"id":572,"value":"RUS|BLR|"},{"id":575,"value":"850:650"},{"id":576,"value":"10"},{"id":577,"value":"0.01"},{"id":578,"value":"100000"},{"id":579,"value":"998"},{"id":58,"value":"5120"},{"id":580,"value":"50000"},{"id":582,"value":"Lists\/GetItemById\/Recycle|GetFolderById\/Recycle|SP.MoveCopyUtil.MoveFolderByPath|SP.MoveCopyUtil.MoveFileByPath|GetCopyJobProgress|GetFileByServerRelativePath\/CheckOut|GetFileByServerRelativePath\/CheckIn|GetFileByServerRelativePath\/UndoCheckOut|GetList\/Items\/ValidateUpdateFetchListItem"},{"id":583,"value":"25.0"},{"id":584,"value":"102400"},{"id":585,"value":"10240"},{"id":586,"value":"51200"},{"id":587,"value":"1.5"},{"id":588,"value":"10240"},{"id":589,"value":"2000"},{"id":59,"value":"64"},{"id":590,"value":"12000"},{"id":591,"value":"3600"},{"id":592,"value":"102400"},{"id":593,"value":"102400"},{"id":594,"value":"102400"},{"id":595,"value":"204800"},{"id":596,"value":"204800"},{"id":599,"value":"120"},{"id":60,"value":"172800"},{"id":601,"value":"10"},{"id":602,"value":"120"},{"id":603,"value":"20"},{"id":604,"value":"2"},{"id":607,"value":"22.217.1016"},{"id":608,"value":"9"},{"id":609,"value":"0"},{"id":61,"value":"350000"},{"id":610,"value":"0.00001"},{"id":611,"value":"0.0000001"},{"id":614,"value":"[\n{\"Req\": 1, \"Len\": 600, \"MC\": 960},\n{\"Req\": 3, \"Len\": 600, \"MC\": 480},\n{\"Req\": 4, \"Len\": 60, \"MC\": 180},\n{\"Req\": 11, \"Len\": 1800, \"MC\": 480},\n{\"Req\": 21, \"Len\": 60, \"MC\": 180}\n]"},{"id":615,"value":"50000"},{"id":616,"value":"50000"},{"id":617,"value":"32"},{"id":62,"value":"403"},{"id":620,"value":"3"},{"id":621,"value":"24"},{"id":625,"value":"7200000"},{"id":628,"value":"0.001"},{"id":635,"value":"2b0b9539-e749-436c-aa61-bd12acc9085d 2b0b9539e749436caa61bd12acc9085d_RNBoolSettingChanged|2b0b9539-e749-436c-aa61-bd12acc9085d 2b0b9539e749436caa61bd12acc9085d_RNNetworkSettingsChanged|2b0b9539-e749-436c-aa61-bd12acc9085d 2b0b9539e749436caa61bd12acc9085d_RNVaultSettingChanged|22bcab81-4b4c-4e52-81ac-cb41e0d8aa72 22bcab814b4c4e5281accb41e0d8aa72_OneDriveStorageProviderHandlerAPI|fa07b02c-55e1-4561-902c-e03204cc93e6 fa07b02c55e14561902ce03204cc93e6_OOBERequestHandlerClientEligibilityState|1d80fd3d-7eea-4a76-85b5-5ed80cd8275f 1d80fd3d7eea4a7685b55ed80cd8275f_KFMSilentFlowLauncherGPOState|fa07b02c-55e1-4561-902c-e03204cc93e6 fa07b02c55e14561902ce03204cc93e6_OOBERequestHandlerSetPreference|1d80fd3d-7eea-4a76-85b5-5ed80cd8275f 1d80fd3d7eea4a7685b55ed80cd8275f_SilentMoveControllerFlowComplete"},{"id":636,"value":"[{\"Req\":1,\"Cap\":8,\"NT\":8,\"P\":5000,\"RP\":300,\"T\":5},\n{\"Req\":3,\"Cap\":8,\"NT\":8,\"P\":10000,\"RP\":300,\"T\":5},\n{\"Req\":4,\"Cap\":3,\"NT\":3,\"P\":1000,\"RP\":300,\"T\":5},\n{\"Req\":11,\"Cap\":4,\"NT\":4,\"P\":15000,\"RP\":300,\"T\":5},\n{\"Req\":21,\"Cap\":3,\"NT\":3,\"P\":1000,\"RP\":300,\"T\":5}]"},{"id":639,"value":"5000"},{"id":643,"value":"168"},{"id":65,"value":"200"},{"id":652,"value":"86400"},{"id":653,"value":"7200"},{"id":656,"value":"300000"},{"id":657,"value":"150000"},{"id":66,"value":"60 "},{"id":67,"value":"60 "},{"id":670,"value":"31614,31617,31610"},{"id":671,"value":"31618,31609,31610"},{"id":672,"value":"1"},{"id":674,"value":"10560"},{"id":676,"value":"TypeG,TypeG,TypeG,false"},{"id":680,"value":"3,60000,300000"},{"id":681,"value":"5.0"},{"id":682,"value":"50000"},{"id":688,"value":"86400"},{"id":69,"value":"401Retry|OfficeConversion_NotSupported|BadArgument_CantGenerateThumbnail|FileTooLarge|OfficeConversion_RegionNotSupported|503Retry"},{"id":690,"value":"86400"},{"id":694,"value":"86400"},{"id":695,"value":"5"},{"id":698,"value":"5"},{"id":7,"value":"0x80080300|0x80070102|0x800704cf|0x00000102|0x80070002|0xcaa20005|0xcaa20008"},{"id":70,"value":"400 "},{"id":701,"value":"86400"},{"id":71,"value":"120 "},{"id":721,"value":"3600000"},{"id":723,"value":"1440"},{"id":726,"value":"5"},{"id":727,"value":"5"},{"id":729,"value":"30"},{"id":730,"value":"2,100"},{"id":731,"value":"2"},{"id":740,"value":"BlueCloudCritical_Win11.svg,1"},{"id":744,"value":"TypeG,TypeG,TypeG,false,RequireNoMSAPresent"},{"id":751,"value":"10080"},{"id":753,"value":"120"},{"id":757,"value":"1"},{"id":759,"value":"120"},{"id":760,"value":"1440"},{"id":761,"value":"2000 "},{"id":769,"value":"30000"},{"id":770,"value":"1,0"},{"id":772,"value":"5000 "},{"id":773,"value":"2621440 "},{"id":774,"value":"2621440 "},{"id":775,"value":"5242880 "},{"id":78,"value":"900"},{"id":780,"value":"3600"},{"id":781,"value":"120"},{"id":782,"value":"60"},{"id":787,"value":"0,1"},{"id":789,"value":"{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_1719712948|{BE6CBA05-11C2-42E8-88B2-7D4B3E3E8734}_2367113984"},{"id":79,"value":"30"},{"id":791,"value":"86400"},{"id":794,"value":"1"},{"id":796,"value":"86400"},{"id":797,"value":"0.03"},{"id":798,"value":"0.03"},{"id":799,"value":"0.09"},{"id":80,"value":"1296000"},{"id":800,"value":"0.09"},{"id":802,"value":"120"},{"id":803,"value":"Survey"},{"id":808,"value":"60"},{"id":81,"value":"10"},{"id":813,"value":"1,0"},{"id":82,"value":"120"},{"id":820,"value":"9000"},{"id":828,"value":"7"},{"id":829,"value":"3"},{"id":83,"value":"21600"},{"id":830,"value":"720"},{"id":832,"value":"300"},{"id":833,"value":"2100"},{"id":84,"value":"19.131.0704.0007"},{"id":844,"value":"50000"},{"id":85,"value":"05a0e69a-418a-47c1-9c25-9387261bf991|"},{"id":86,"value":"5 "},{"id":863,"value":"250000"},{"id":865,"value":"0.001"},{"id":866,"value":"0.1"},{"id":867,"value":"0.1"},{"id":87,"value":"10 "},{"id":872,"value":"100"},{"id":873,"value":"0.03"},{"id":874,"value":"0.03"},{"id":875,"value":"20"},{"id":876,"value":"https:\/\/clients.config.office.net\/odb\/v1.0\/synchealth"},{"id":88,"value":"Antler"},{"id":880,"value":"50"},{"id":881,"value":"10"},{"id":89,"value":"86400 "},{"id":90,"value":"1"},{"id":91,"value":"10000 "},{"id":93,"value":"604800"},{"id":96,"value":"GetSignature_HighFrequency,OpenUploadSession_HighFrequency,OpenUploadSession,GetSignature_FrequencyBackoff,OpenUploadSession_FrequencyBackoff,UploadBatch,DownloadBlock,InlineBatchUpload_FrequencyBackoff,DiffInlineUploadBatch_FrequencyBackoff"}]} \ No newline at end of file diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Install_2024-09-23_134806_21800-8040.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Install_2024-09-23_134806_21800-8040.log new file mode 100644 index 00000000..f43c22f4 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Install_2024-09-23_134806_21800-8040.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Update_2024-09-23_134749_19172-1452.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Update_2024-09-23_134749_19172-1452.log new file mode 100644 index 00000000..77878a08 Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Update_2024-09-23_134749_19172-1452.log differ diff --git a/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Update_2024-09-23_134825_7960-23192.log b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Update_2024-09-23_134825_7960-23192.log new file mode 100644 index 00000000..413940cc Binary files /dev/null and b/tests/test_data/DFIRArtifactMuseum/onedrive/24.175.0830.0001/setup/logs/Update_2024-09-23_134825_7960-23192.log differ diff --git a/tests/test_data/edge/v141/Bookmarks b/tests/test_data/edge/v141/Bookmarks new file mode 100644 index 00000000..833894fa --- /dev/null +++ b/tests/test_data/edge/v141/Bookmarks @@ -0,0 +1,51 @@ +{ + "checksum": "359879469ecb660a2fa6e05a3a5fe7f7", + "checksum_sha256": "4df1933136417896028f9cb9a3353a90305779b2194f74752bd5e44e80a0cb3b", + "roots": { + "bookmark_bar": { + "children": [ { + "date_added": "13406597261328535", + "date_last_used": "0", + "guid": "77fe6201-2001-45ec-b8a3-497f7f3a9742", + "id": "6", + "name": "Download the DuckDuckGo Browser for Mac", + "show_icon": false, + "source": "user_add", + "type": "url", + "url": "https://duckduckgo.com/mac?origin=funnel_home_bing__hero", + "visit_count": 1 + } ], + "date_added": "13406597214566635", + "date_last_used": "0", + "date_modified": "13406597261328535", + "guid": "0bc5d13f-2cba-5d74-951f-3f233fe6c908", + "id": "1", + "name": "Favorites Bar", + "source": "unknown", + "type": "folder" + }, + "other": { + "children": [ ], + "date_added": "13406597214566635", + "date_last_used": "0", + "date_modified": "0", + "guid": "82b081ec-3dd3-529c-8475-ab6c344590dd", + "id": "2", + "name": "Other Favorites", + "source": "unknown", + "type": "folder" + }, + "synced": { + "children": [ ], + "date_added": "13406597214566635", + "date_last_used": "0", + "date_modified": "0", + "guid": "4cf2e351-0e85-532b-bb37-df045d8f8d0f", + "id": "3", + "name": "Mobile Favorites", + "source": "unknown", + "type": "folder" + } + }, + "version": 1 +} diff --git a/tests/test_data/edge/v141/Cookies b/tests/test_data/edge/v141/Cookies new file mode 100644 index 00000000..9057d1b5 Binary files /dev/null and b/tests/test_data/edge/v141/Cookies differ diff --git a/tests/test_data/edge/v141/DIPS b/tests/test_data/edge/v141/DIPS new file mode 100644 index 00000000..9b9b33eb Binary files /dev/null and b/tests/test_data/edge/v141/DIPS differ diff --git a/tests/test_data/edge/v141/Extensions/ghbmnnjooekpmoecnnnilnnbdlolhkhi/1.97.1_0/manifest.json b/tests/test_data/edge/v141/Extensions/ghbmnnjooekpmoecnnnilnnbdlolhkhi/1.97.1_0/manifest.json new file mode 100644 index 00000000..90c4a761 --- /dev/null +++ b/tests/test_data/edge/v141/Extensions/ghbmnnjooekpmoecnnnilnnbdlolhkhi/1.97.1_0/manifest.json @@ -0,0 +1,38 @@ +{ + "author": { + "email": "docs-hosted-app-own@google.com" + }, + "background": { + "service_worker": "service_worker_bin_prod.js" + }, + "content_capabilities": { + "matches": [ "https://docs.google.com/*", "https://drive.google.com/*", "https://drive-autopush.corp.google.com/*", "https://drive-daily-0.corp.google.com/*", "https://drive-daily-1.corp.google.com/*", "https://drive-daily-2.corp.google.com/*", "https://drive-daily-3.corp.google.com/*", "https://drive-daily-4.corp.google.com/*", "https://drive-daily-5.corp.google.com/*", "https://drive-daily-6.corp.google.com/*", "https://drive-preprod.corp.google.com/*", "https://drive-staging.corp.google.com/*" ], + "permissions": [ "clipboardRead", "clipboardWrite", "unlimitedStorage" ] + }, + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'" + }, + "default_locale": "en_US", + "description": "__MSG_extDesc__", + "externally_connectable": { + "matches": [ "https://docs.google.com/*", "https://drive.google.com/*", "https://drive-autopush.corp.google.com/*", "https://drive-daily-0.corp.google.com/*", "https://drive-daily-1.corp.google.com/*", "https://drive-daily-2.corp.google.com/*", "https://drive-daily-3.corp.google.com/*", "https://drive-daily-4.corp.google.com/*", "https://drive-daily-5.corp.google.com/*", "https://drive-daily-6.corp.google.com/*", "https://drive-preprod.corp.google.com/*", "https://drive-staging.corp.google.com/*" ] + }, + "host_permissions": [ "https://docs.google.com/*", "https://drive.google.com/*" ], + "icons": { + "128": "128.png" + }, + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnF7RGLAxIon0/XeNZ4MLdP3DMkoORzEAKVg0sb89JpA/W2osTHr91Wqwdc9lW0mFcSpCYS9Y3e7cUMFo/M2ETASIuZncMiUzX2/0rrWtGQ3UuEj3KSe5PdaVZfisyJw/FebvHwirEWrhqcgzVUj9fL9YjE0G45d1zMKcc1umKvLqPyTznNuKBZ9GJREdGLRJCBmUgCkI8iwtwC+QZTUppmaD50/ksnEUXv+QkgGN07/KoNA5oAgo49Jf1XBoMv4QXtVZQlBYZl84zAsI82hb63a6Gu29U/4qMWDdI7+3Ne5TRvo6Zi3EI4M2NQNplJhik105qrz+eTLJJxvf4slrWwIDAQAB", + "manifest_version": 3, + "minimum_chrome_version": "88", + "name": "__MSG_extName__", + "permissions": [ "alarms", "storage", "unlimitedStorage", "offscreen" ], + "storage": { + "managed_schema": "dasherSettingSchema.json" + }, + "update_url": "https://clients2.google.com/service/update2/crx", + "version": "1.97.1", + "web_accessible_resources": [ { + "matches": [ "\u003Call_urls>" ], + "resources": [ "page_embed_script.js" ] + } ] +} diff --git a/tests/test_data/edge/v141/Extensions/jmjflgjpcpepeafmmgdpfkogkghcpiha/1.2.1_0/manifest.json b/tests/test_data/edge/v141/Extensions/jmjflgjpcpepeafmmgdpfkogkghcpiha/1.2.1_0/manifest.json new file mode 100644 index 00000000..fb6ca03b --- /dev/null +++ b/tests/test_data/edge/v141/Extensions/jmjflgjpcpepeafmmgdpfkogkghcpiha/1.2.1_0/manifest.json @@ -0,0 +1,15 @@ +{ + "content_scripts": [ { + "js": [ "content.js" ], + "matches": [ "https://chrome.google.com/webstore/*" ] + }, { + "js": [ "content_new.js" ], + "matches": [ "https://chromewebstore.google.com/*" ] + } ], + "description": "Edge relevant text changes on select websites to improve user experience and precisely surfaces the action they want to take.", + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu06p2Mjoy6yJDUUjCe8Hnqvtmjll73XqcbylxFZZWe+MCEAEK+1D0Nxrp0+IuWJL02CU3jbuR5KrJYoezA36M1oSGY5lIF/9NhXWEx5GrosxcBjxqEsdWv/eDoOOEbIvIO0ziMv7T1SUnmAA07wwq8DXWYuwlkZU/PA0Mxx0aNZ5+QyMfYqRmMpwxkwPG8gyU7kmacxgCY1v7PmmZo1vSIEOBYrxl064w5Q6s/dpalSJM9qeRnvRMLsszGY/J2bjQ1F0O2JfIlBjCOUg/89+U8ZJ1mObOFrKO4um8QnenXtH0WGmsvb5qBNrvbWNPuFgr2+w5JYlpSQ+O8zUCb8QZwIDAQAB", + "manifest_version": 3, + "name": "Edge relevant text changes", + "update_url": "https://edge.microsoft.com/extensionwebstorebase/v1/crx", + "version": "1.2.1" +} diff --git a/tests/test_data/edge/v141/Extensions/odfafepnkmbhccpbejgmiehpchacaeak/2025.1015.67.0_0/manifest.json b/tests/test_data/edge/v141/Extensions/odfafepnkmbhccpbejgmiehpchacaeak/2025.1015.67.0_0/manifest.json new file mode 100644 index 00000000..c40ae6aa --- /dev/null +++ b/tests/test_data/edge/v141/Extensions/odfafepnkmbhccpbejgmiehpchacaeak/2025.1015.67.0_0/manifest.json @@ -0,0 +1,82 @@ +{ + "author": "Raymond Hill & contributors", + "background": { + "page": "background.html" + }, + "browser_action": { + "default_icon": { + "16": "img/icon_16.png", + "32": "img/icon_32.png", + "64": "img/icon_64.png" + }, + "default_popup": "popup-fenix.html", + "default_title": "uBlock Origin" + }, + "commands": { + "launch-element-picker": { + "description": "__MSG_popupTipPicker__" + }, + "launch-element-zapper": { + "description": "__MSG_popupTipZapper__" + }, + "launch-logger": { + "description": "__MSG_popupTipLog__" + }, + "open-dashboard": { + "description": "__MSG_popupTipDashboard__" + }, + "relax-blocking-mode": { + "description": "__MSG_relaxBlockingMode__" + }, + "toggle-cosmetic-filtering": { + "description": "__MSG_toggleCosmeticFiltering__" + }, + "toggle-javascript": { + "description": "__MSG_toggleJavascript__" + } + }, + "content_scripts": [ { + "all_frames": true, + "js": [ "/js/vapi.js", "/js/vapi-client.js", "/js/contentscript.js" ], + "match_about_blank": true, + "matches": [ "http://*/*", "https://*/*" ], + "run_at": "document_start" + }, { + "all_frames": false, + "js": [ "/js/scriptlets/subscriber.js" ], + "matches": [ "https://easylist.to/*", "https://*.fanboy.co.nz/*", "https://filterlists.com/*", "https://forums.lanik.us/*", "https://github.com/*", "https://*.github.io/*" ], + "run_at": "document_idle" + }, { + "all_frames": false, + "js": [ "/js/scriptlets/updater.js" ], + "matches": [ "https://github.com/uBlockOrigin/*", "https://ublockorigin.github.io/*", "https://*.reddit.com/r/uBlockOrigin/*" ], + "run_at": "document_idle" + } ], + "content_security_policy": "script-src 'self'; object-src 'self'", + "default_locale": "en", + "description": "__MSG_extShortDesc__", + "icons": { + "128": "img/icon_128.png", + "16": "img/icon_16.png", + "32": "img/icon_32.png", + "64": "img/icon_64.png" + }, + "incognito": "split", + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtej8nZ6GDzzNjLD1WCjkbCf15gZlrgzMn9To0ef+6Tiyk6uDSePSaaiMG+8rNgTCQM1ES6Hy8XzTJf8o19ldg1GXHE4MAdjjzDNv3ya05Vj71r/dzI9OyL45DnshMYdW7lyzHp7nt1L5uWtmZs4MiOO43RrWzrGuvhhUdQm9rz4nOgu9q7FWqZP6kUYL42TJgQ6Sc0Qu25TshDdJME3uK5z/kV3BNlmQFDhuAXQZKP/KCV2ogG7R/VcHj1a2ETjRFMQxtQUaWtCmpDYw7URD4CuRNy9LBTylNASfFCHLAEc9MWqFD1Alj63o+WsqBP/h81Vs7nH6PnXQg9+fOCpMyQIDAQAB", + "manifest_version": 2, + "minimum_chrome_version": "93.0", + "name": "uBlock Origin", + "options_ui": { + "open_in_tab": true, + "page": "dashboard.html" + }, + "permissions": [ "alarms", "contextMenus", "privacy", "storage", "tabs", "unlimitedStorage", "webNavigation", "webRequest", "webRequestBlocking", "\u003Call_urls>" ], + "short_name": "uBlockā‚€", + "storage": { + "managed_schema": "managed_storage.json" + }, + "update_url": "https://edge.microsoft.com/extensionwebstorebase/v1/crx", + "version": "2025.1015.67.0", + "version_name": "1.67.0", + "web_accessible_resources": [ "/web_accessible_resources/*" ] +} diff --git a/tests/test_data/edge/v141/Favicons b/tests/test_data/edge/v141/Favicons new file mode 100644 index 00000000..9e1572b5 Binary files /dev/null and b/tests/test_data/edge/v141/Favicons differ diff --git a/tests/test_data/edge/v141/History b/tests/test_data/edge/v141/History new file mode 100644 index 00000000..6d718138 Binary files /dev/null and b/tests/test_data/edge/v141/History differ diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/000005.ldb b/tests/test_data/edge/v141/Local Storage/leveldb/000005.ldb new file mode 100644 index 00000000..f3fb7ac8 Binary files /dev/null and b/tests/test_data/edge/v141/Local Storage/leveldb/000005.ldb differ diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/000016.ldb b/tests/test_data/edge/v141/Local Storage/leveldb/000016.ldb new file mode 100644 index 00000000..07e71dac Binary files /dev/null and b/tests/test_data/edge/v141/Local Storage/leveldb/000016.ldb differ diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/000018.ldb b/tests/test_data/edge/v141/Local Storage/leveldb/000018.ldb new file mode 100644 index 00000000..be513d00 Binary files /dev/null and b/tests/test_data/edge/v141/Local Storage/leveldb/000018.ldb differ diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/000019.log b/tests/test_data/edge/v141/Local Storage/leveldb/000019.log new file mode 100644 index 00000000..225c271e Binary files /dev/null and b/tests/test_data/edge/v141/Local Storage/leveldb/000019.log differ diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/000020.ldb b/tests/test_data/edge/v141/Local Storage/leveldb/000020.ldb new file mode 100644 index 00000000..9e92f0f1 Binary files /dev/null and b/tests/test_data/edge/v141/Local Storage/leveldb/000020.ldb differ diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/CURRENT b/tests/test_data/edge/v141/Local Storage/leveldb/CURRENT new file mode 100644 index 00000000..7ed683d1 --- /dev/null +++ b/tests/test_data/edge/v141/Local Storage/leveldb/CURRENT @@ -0,0 +1 @@ +MANIFEST-000001 diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/LOCK b/tests/test_data/edge/v141/Local Storage/leveldb/LOCK new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/LOG b/tests/test_data/edge/v141/Local Storage/leveldb/LOG new file mode 100644 index 00000000..7b90bb40 --- /dev/null +++ b/tests/test_data/edge/v141/Local Storage/leveldb/LOG @@ -0,0 +1,36 @@ +2025/11/02-17:30:12.761 418c Reusing MANIFEST /Users/android/Library/Application Support/Microsoft Edge/Profile 1/Local Storage/leveldb/MANIFEST-000001 +2025/11/02-17:30:12.769 418c Recovering log #3 +2025/11/02-17:30:12.769 418c Reusing old log /Users/android/Library/Application Support/Microsoft Edge/Profile 1/Local Storage/leveldb/000003.log +2025/11/02-17:31:10.766 418f Level-0 table #5: started +2025/11/02-17:31:10.788 418f Level-0 table #5: 31387 bytes OK +2025/11/02-17:31:10.792 418f Delete type=0 #3 +2025/11/02-17:31:58.745 418f Level-0 table #7: started +2025/11/02-17:31:58.754 418f Level-0 table #7: 28218 bytes OK +2025/11/02-17:31:58.769 418f Delete type=0 #4 +2025/11/02-17:34:13.298 418f Level-0 table #9: started +2025/11/02-17:34:13.307 418f Level-0 table #9: 122687 bytes OK +2025/11/02-17:34:13.310 418f Delete type=0 #6 +2025/11/02-17:34:43.557 418f Level-0 table #11: started +2025/11/02-17:34:43.561 418f Level-0 table #11: 36554 bytes OK +2025/11/02-17:34:43.571 418f Delete type=0 #8 +2025/11/02-17:35:41.817 418f Level-0 table #13: started +2025/11/02-17:35:41.832 418f Level-0 table #13: 29479 bytes OK +2025/11/02-17:35:41.834 418f Delete type=0 #10 +2025/11/02-17:38:36.311 418f Level-0 table #15: started +2025/11/02-17:38:36.329 418f Level-0 table #15: 50105 bytes OK +2025/11/02-17:38:36.338 418f Delete type=0 #12 +2025/11/02-17:38:36.340 418f Compacting 4@0 + 1@1 files +2025/11/02-17:38:36.351 418f Generated table #16@0: 362 keys, 179583 bytes +2025/11/02-17:38:36.351 418f Compacted 4@0 + 1@1 files => 179583 bytes +2025/11/02-17:38:36.354 418f compacted to: files[ 0 1 1 0 0 0 0 ] +2025/11/02-17:38:36.356 418f Delete type=2 #15 +2025/11/02-17:38:36.356 418f Delete type=2 #7 +2025/11/02-17:38:36.356 418f Delete type=2 #13 +2025/11/02-17:38:36.356 418f Delete type=2 #11 +2025/11/02-17:38:36.356 418f Delete type=2 #9 +2025/11/02-17:39:36.314 418f Level-0 table #18: started +2025/11/02-17:39:36.327 418f Level-0 table #18: 41979 bytes OK +2025/11/02-17:39:36.334 418f Delete type=0 #14 +2025/11/02-17:40:12.140 418f Level-0 table #20: started +2025/11/02-17:40:12.163 418f Level-0 table #20: 38941 bytes OK +2025/11/02-17:40:12.166 418f Delete type=0 #17 diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/LOG.old b/tests/test_data/edge/v141/Local Storage/leveldb/LOG.old new file mode 100644 index 00000000..844779c4 --- /dev/null +++ b/tests/test_data/edge/v141/Local Storage/leveldb/LOG.old @@ -0,0 +1,2 @@ +2025/10/15-00:41:14.513 6f960 Creating DB /Users/android/Library/Application Support/Microsoft Edge/Profile 1/Local Storage/leveldb since it was missing. +2025/10/15-00:41:14.536 6f960 Reusing MANIFEST /Users/android/Library/Application Support/Microsoft Edge/Profile 1/Local Storage/leveldb/MANIFEST-000001 diff --git a/tests/test_data/edge/v141/Local Storage/leveldb/MANIFEST-000001 b/tests/test_data/edge/v141/Local Storage/leveldb/MANIFEST-000001 new file mode 100644 index 00000000..39fbb067 Binary files /dev/null and b/tests/test_data/edge/v141/Local Storage/leveldb/MANIFEST-000001 differ diff --git a/tests/test_data/edge/v141/Login Data b/tests/test_data/edge/v141/Login Data new file mode 100644 index 00000000..77f108df Binary files /dev/null and b/tests/test_data/edge/v141/Login Data differ diff --git a/tests/test_data/edge/v141/Preferences b/tests/test_data/edge/v141/Preferences new file mode 100644 index 00000000..9d75ae9e --- /dev/null +++ b/tests/test_data/edge/v141/Preferences @@ -0,0 +1 @@ +{"aadc_info":{"age_group":0},"accessibility":{"captions":{"headless_caption_enabled":false}},"account_tracker_service_last_update":"13406596213013064","ack_existing_ntp_extensions":true,"alternate_error_pages":{"backup":true},"apps":{"shortcuts_arch":"arm64","shortcuts_version":8},"arbitration_experiences":{"Nurturing.Global.EdgeOnMac_SetEdgeAsDefaultBrowserOnMac":{"ClickedCount":0,"Cohort":"DefaultCohort","DisableCount":0,"Disabled":false,"DismissedCount":1,"ExperienceEngagementHistory":1,"GlobalNSAT":0.0,"IgnoredCount":0,"IsGlobalExperience":false,"LastReservedTime":"11644473600000000","LastTriggeredTime":"13406596218094503","LastUndoShownTime":"11644473600000000","Loss":1,"ModelScore":1.0,"NSATTriggeredCount":1,"NSATUpperCI":1.1929646455628165,"OverallNSAT":0.5,"QuickDismissedCount":1,"Reserved":0,"SnoozeCount":0,"Triggered":1,"UndoShown":0,"Win":0},"Nurturing.Local.InterestFreCard":{"ClickedCount":0,"Cohort":"DefaultCohort","DisableCount":0,"Disabled":false,"DismissedCount":1,"ExperienceEngagementHistory":1,"GlobalNSAT":0.0,"IgnoredCount":0,"IsGlobalExperience":false,"LastReservedTime":"11644473600000000","LastTriggeredTime":"13406596233106750","LastUndoShownTime":"11644473600000000","Loss":1,"ModelScore":1.0,"NSATTriggeredCount":1,"NSATUpperCI":1.1929646455628165,"OverallNSAT":0.5,"QuickDismissedCount":1,"Reserved":0,"SnoozeCount":0,"Triggered":1,"UndoShown":0,"Win":0},"Nurturing.Local.locationAccuracyRevIP":{"ClickedCount":0,"Cohort":"DefaultCohort","DisableCount":0,"Disabled":false,"DismissedCount":0,"ExperienceEngagementHistory":0,"GlobalNSAT":0.0,"IgnoredCount":0,"IsGlobalExperience":false,"LastReservedTime":"11644473600000000","LastTriggeredTime":"13406596237224459","LastUndoShownTime":"11644473600000000","Loss":0,"ModelScore":1.0,"NSATTriggeredCount":1,"NSATUpperCI":1.0,"OverallNSAT":1.0,"QuickDismissedCount":0,"Reserved":0,"SnoozeCount":0,"Triggered":1,"UndoShown":0,"Win":0},"Nurturing.Local.personalizeManageText":{"ClickedCount":0,"Cohort":"DefaultCohort","DisableCount":0,"Disabled":false,"DismissedCount":1,"ExperienceEngagementHistory":1,"GlobalNSAT":0.0,"IgnoredCount":0,"IsGlobalExperience":false,"LastReservedTime":"11644473600000000","LastTriggeredTime":"13406596519318478","LastUndoShownTime":"11644473600000000","Loss":1,"ModelScore":1.0,"NSATTriggeredCount":1,"NSATUpperCI":1.1929646455628165,"OverallNSAT":0.5,"QuickDismissedCount":1,"Reserved":0,"SnoozeCount":0,"Triggered":1,"UndoShown":0,"Win":0}},"arbitration_last_notification_shown":"13406597261332127","arbitration_using_experiment_config":false,"autocomplete":{"retention_policy_last_version":142},"autofill":{"edge_autofill_purge_low_quality_profiles_by_timeline":false,"last_version_deduped":142},"bookmark":{"storage_computation_last_update":"13406596213012332"},"browser":{"available_dark_theme_options":"All","chat_v2":{"ip_eligibility_status":{"last_checked_time":"13406596213412185"}},"edge_sidebar_visibility":{"_game_assist_":{"order":{"8ac719c5-140b-4bf2-a0b7-c71617f1f377":2147483647}},"add_app_to_bottom":true,"order":{"8ac719c5-140b-4bf2-a0b7-c71617f1f377":2147483647}},"edge_sidebar_visibility_debug":{"order_list":["Search"],"order_raw_data":{"8ac719c5-140b-4bf2-a0b7-c71617f1f377":{"name":"Search","pos":"2147483647"}}},"editor_proofing_languages":{"en":{"Grammar":false,"Spelling":false},"en-US":{"Grammar":true,"Spelling":true}},"enable_text_prediction_v2":true,"history_visit_time":"13406596245752678","hub_app_non_synced_preferences":{"apps":{"06be1ebe-f23a-4bea-ae45-3120ad86cfea":{"last_path":""},"0c835d2d-9592-4c7a-8d0a-0e283c9ad3cd":{"last_path":""},"168a2510-04d5-473e-b6a0-828815a7ca5f":{"last_path":""},"1ec8a5a9-971c-4c82-a104-5e1a259456b8":{"last_path":""},"2354565a-f412-4654-b89c-f92eaa9dbd20":{"last_path":""},"25fe2d1d-e934-482a-a62f-ea1705db905d":{"last_path":""},"2caf0cf4-ea42-4083-b928-29b39da1182b":{"last_path":""},"3458dfd2-bf1b-4d00-a6dd-a74a59d523c7":{"last_path":""},"35a43603-bb38-4b53-ba20-932cb9117794":{"last_path":""},"380c71d3-10bf-4a5d-9a06-c932e4b7d1d8":{"last_path":""},"439642fc-998d-4a64-8bb6-940ecaf6b60b":{"last_path":""},"523b5ef3-0b10-4154-8b62-10b2ebd00921":{"last_path":""},"64be4f9b-3b81-4b6e-b354-0ba00d6ba485":{"last_path":""},"698b01b4-557a-4a3b-9af7-a7e8138e8372":{"last_path":""},"76b926d6-3738-46bf-82d7-2ab896ddf70b":{"last_path":""},"7b52ae05-ae84-4165-b083-98ba2031bc22":{"last_path":""},"8682d0fa-50b3-4ece-aa5b-e0b33f9919e2":{"last_path":""},"8ac719c5-140b-4bf2-a0b7-c71617f1f377":{"last_path":""},"92f1b743-e26b-433b-a1ec-912d1f0ad1fa":{"last_path":""},"96defd79-4015-4a32-bd09-794ff72183ef":{"last_path":""},"a1a78183-6db3-4789-9e7c-84d157846d55":{"last_path":""},"bacc3c12-ebff-44b4-a0f8-ce8b69c9e047":{"last_path":""},"c814ae4d-fa0a-4280-a444-cb8bd264828b":{"last_path":""},"cd4688a9-e888-48ea-ad81-76193d56b1be":{"last_path":""},"d3ff4c56-a2b8-4673-ad13-35e7706cc9d1":{"last_path":""},"da15ec1d-543d-41c9-94b8-eb2bd060f2c7":{"last_path":""},"dadd1f1c-380c-4871-9e09-7971b6b15069":{"last_path":""},"e6723537-66ff-4f4e-ab56-a4cbaddf4e0f":{"last_path":""}}},"hub_app_preferences":{},"hub_cleanup_candidate_list_for_debug":[{"cleanup_progress":"cleanup_start_v2"},{"cleanup_progress":"cleanup_done_v2"},{"cleanup_progress":"cleanup_start_v2"},{"cleanup_progress":"skipped_cleanup_v2_has_happened"},{"cleanup_progress":"cleanup_start_v2"},{"cleanup_progress":"skipped_cleanup_v2_has_happened"}],"hub_cleanup_context_v2":{"cleanup_debug_info_v2_adjusted_engaged_app_count":0,"cleanup_debug_info_v2_app_count_threshold":1,"cleanup_debug_info_v2_current_sidebar_visibility":0,"cleanup_debug_info_v2_discover_icon_enabled":true,"cleanup_debug_info_v2_dwell_time_in_secs":10,"cleanup_debug_info_v2_engaged_app_count":0,"cleanup_debug_info_v2_expected_sidebar_visibility":0,"cleanup_debug_info_v2_is_tower_off_by_user":false,"cleanup_debug_info_v2_skip_user_generated_apps_for_threshold":true,"cleanup_debug_info_v2_user_generated_app_count":0,"hub_app_cleanup_v2_done":true},"recent_theme_color_list":[4293914607.0,4293914607.0,4293914607.0,4293914607.0,4293914607.0],"show_hub_app_in_sidebar_buttons":{"8ac719c5-140b-4bf2-a0b7-c71617f1f377":0},"show_hub_app_in_sidebar_buttons_legacy":{"8ac719c5-140b-4bf2-a0b7-c71617f1f377":0},"show_hub_app_in_sidebar_buttons_legacy_update_time":"13406596333095299","show_toolbar_performance_center_button":0,"time_of_last_normal_window_close":"13406597266990530","underside_chat_bing_signed_in_status":false,"user_level_features_context":{},"window_placement":{"bottom":1104,"left":7,"maximized":false,"right":3847,"top":24,"work_area_bottom":1440,"work_area_left":0,"work_area_right":5120,"work_area_top":0}},"browser_content_container_height":1000,"browser_content_container_width":3840,"browser_content_container_x":0,"browser_content_container_y":80,"collections":{"prism_collections":{"enabled":0,"policy":{"cached":0}}},"commerce_daily_metrics_last_update_time":"13406596213014272","countryid_at_install":21843,"custom_links":{"list":[]},"default_apps_install_state":3,"devtools":{"preferences":{"EdgeDevToolsLayoutInfo":{"current_dock_state":0,"horizontal_size":300,"showEmulationMode":false,"vertical_size":555}}},"domain_diversity":{"last_reporting_timestamp":"13406596213012915"},"edge":{"bookmarks":{"last_dup_info_record_time":"13406596223013499"},"services":{"signin_scoped_device_id":"7620b5c1-47ae-437f-a84f-afd9adbd2e97"},"workspaces":{"state":"{\"edgeWorkspacePrefsVersion\":2,\"enableFluid\":true,\"failedRestartSpaceId\":\"\",\"failedToConnectToFluid\":false,\"fluidStatus\":0,\"fre_shown\":false,\"fromCache\":false,\"isFluidPreferencesConnected\":false,\"isSpaceOpening\":false,\"openingSpaceId\":\"\",\"statusForScreenReaders\":\"\",\"workspacePopupMode\":0,\"workspacesForExternalLinks\":[]}"}},"edge_history_hub_opened":true,"edge_journeys":{"latest_journeys_count":0},"edge_rewards":{"cache_data":"CAA=","coachmark_promotions":{},"hva_promotions":[],"hva_webui_action_status_dict":{},"refresh_status_muted_until":"13407201012721855"},"edge_ux_config":{"assignmentcontext":"YWcJE8v1QJqLkTG/OjG78Ab4pOBsMw4+G6IEW6fXeao=","dataversion":"254553710","experimentvariables":{"shopppdismisstreatment":{"edgeServerUX.shopping.msEdgeShoppingCashbackDismissTimeout2s":true}},"flights":{"eurwdph3t4":"31399517","shopppdismisstreatment":"31004791"},"latestcorrelationid":"Ref A: 572B1CE36DFA4B7CB663F88EF99FEFB0 Ref B: MNZ221060609019 Ref C: 2025-11-02T22:46:56Z"},"edge_vpn":{"available":true},"edge_wallet":{"checkout":{"global_config":"{\"common_config\":{\"auto_dimiss_count_threshold\":1,\"cooldown\":[1,24,168,720],\"coupons_off_threshold\":20000,\"disabled_features\":[],\"dsat_cooldown\":{\"-1\":168,\"0\":720,\"3\":168,\"4\":168,\"5\":24,\"6\":24,\"7\":24,\"8\":24},\"enabled_countries\":[\"CN\",\"US\",\"GB\",\"CA\",\"AU\",\"DK\",\"FR\",\"JP\",\"KR\",\"BR\",\"MX\",\"DE\",\"NL\",\"PL\",\"SE\",\"ES\",\"IT\",\"NO\",\"NZ\",\"SG\",\"HK\",\"TW\",\"PH\",\"TH\",\"VN\",\"MY\",\"AE\",\"PR\",\"CO\",\"CL\",\"AR\",\"IL\",\"SA\",\"PE\",\"TR\",\"IN\",\"DO\",\"ID\",\"CH\",\"ZA\",\"CR\",\"EC\",\"EG\",\"GT\",\"NG\",\"AT\",\"CZ\",\"BE\",\"IE\",\"PT\",\"AD\",\"AF\",\"AG\",\"AI\",\"AL\",\"AM\",\"AO\",\"AQ\",\"AS\",\"AW\",\"AX\",\"AZ\",\"BA\",\"BB\",\"BD\",\"BF\",\"BG\",\"BH\",\"BI\",\"BJ\",\"BL\",\"BM\",\"BN\",\"BO\",\"BQ\",\"BS\",\"BT\",\"BV\",\"BW\",\"BZ\",\"CC\",\"CD\",\"CF\",\"CG\",\"CI\",\"CK\",\"CM\",\"CV\",\"CW\",\"CX\",\"CY\",\"DJ\",\"DM\",\"DZ\",\"EE\",\"EH\",\"ER\",\"ET\",\"FI\",\"FJ\",\"FK\",\"FM\",\"FO\",\"GA\",\"GD\",\"GE\",\"GF\",\"GG\",\"GH\",\"GI\",\"GL\",\"GM\",\"GN\",\"GP\",\"GQ\",\"GR\",\"GS\",\"GU\",\"GW\",\"GY\",\"HM\",\"HN\",\"HR\",\"HT\",\"HU\",\"IM\",\"IO\",\"IQ\",\"IS\",\"JE\",\"JM\",\"JO\",\"KE\",\"KG\",\"KH\",\"KI\",\"KM\",\"KN\",\"KW\",\"KY\",\"KZ\",\"LA\",\"LB\",\"LC\",\"LI\",\"LK\",\"LR\",\"LS\",\"LT\",\"LU\",\"LV\",\"LY\",\"MA\",\"MC\",\"MD\",\"ME\",\"MF\",\"MG\",\"MH\",\"MK\",\"ML\",\"MM\",\"MN\",\"MO\",\"MP\",\"MQ\",\"MR\",\"MS\",\"MT\",\"MU\",\"MV\",\"MW\",\"MZ\",\"NA\",\"NC\",\"NE\",\"NF\",\"NI\",\"NP\",\"NR\",\"NU\",\"OM\",\"PA\",\"PF\",\"PG\",\"PK\",\"PM\",\"PN\",\"PS\",\"PW\",\"PY\",\"QA\",\"RE\",\"RO\",\"RS\",\"RW\",\"SB\",\"SC\",\"SD\",\"SH\",\"SI\",\"SJ\",\"SK\",\"SL\",\"SM\",\"SN\",\"SO\",\"SR\",\"SS\",\"ST\",\"SV\",\"SX\",\"SZ\",\"TC\",\"TD\",\"TF\",\"TG\",\"TJ\",\"TK\",\"TL\",\"TM\",\"TN\",\"TO\",\"TT\",\"TV\",\"TZ\",\"UA\",\"UG\",\"UM\",\"UY\",\"UZ\",\"VA\",\"VC\",\"VE\",\"VG\",\"VI\",\"VU\",\"WF\",\"WS\",\"YE\",\"YT\",\"ZM\",\"ZW\"],\"enabled_features\":[\"giftCardV2\",\"msWalletCheckoutCouponImprovement\",\"msWalletCheckoutECPaneDisableAutoDismiss:127.18082.18067.70_999.0.0.0\",\"msWalletCheckoutProfileCardRankByRecentUsage\"],\"export_card_timeout\":100,\"min_height\":300,\"min_version\":\"123.0.0.0\",\"min_width\":1000,\"wait_for_dom_loaded_before_trigger_ms\":4000},\"daf_config\":{\"allowed_url_keywords\":[\"checkout\",\"order\",\"book\",\"donate\",\"purchase\",\"cart\",\"buy\",\"shop\",\"reserve\",\"subscribe\",\"pay\",\"payment\",\"reservation\",\"billing\",\"invoice\",\"merchant\",\"secure\",\"transaction\",\"charge\",\"subscription\"],\"disabled_features\":[\"giftCardV2\"],\"disallowed_url_keywords\":[\"member\",\"membership\",\"account\",\"signup\",\"profile\"],\"enabled_features\":[],\"is_bloom_filter_base64_encoded\":true,\"is_empty_pool_skipped\":true,\"is_enabled\":false},\"ecommerce_config\":{\"disabled_features\":[\"giftCardV2\"],\"disallowed_sites\":{\"disallowed_filter_bytes\":\"lLMx0qG4N7YrIFdqEwrq6dGdN2Te7bSGGJfJdTUIbjIkuaFN8NSd8FfEy45NTR8T94Pi2rT00SXIcdC+AiWpf7JkIo2YqyjMKENnC3KoxIKvoZHsT1gGgSVFAWDFrOmt36cSZwCMEy3TmmeMsNfiFEUwtqTOPjg+Eq5qzQeBReqGNQdzQb0tLugkwnL4lQRvb5rUwUFoBlwyKp1YFyIjUG+09b3mzhtT6Gy2AeQX1uzHqu6+UYn4EGmrvE7jo03qtY+3oReaUzzge+5QBJEPCdshgWhDatMEOv2LMiI+YxQzjx9T+hvkhR0HC6hOqZ9XAuK4iShgXAQqgEElK+RusAJg463A9PeR5w4mSk0qsoMzXYvdSaXagNyRVpS453uwRVJARIxihCqnZAxtMgA+KbVGf/OWQ9VhO3QuBCn72Z/Lxnc2xt9hP8IG5JHhAWbhSZBPPMNUMSHMfakmq0PZovpi/pHe0Q8mOvpLIgHwKDy9+y637NXXBvmkrr+OOB8EdqTE+/RzDhIjds1UgBx8rIkVYylOo105EXCeaJlpQCCfboHtylBZ569VI5KCDERo5n1l9zKqCeAHqY/cMpbWgwQk4LiDAsyeCROQr+NRL0RP8ryai5Q/SrYu3r+txjghgfaNGl6UaIGvnQjRS5VYeg+YQ/SorW0+SEIp+uIS+argFMe5wsF01MAH5VNfZDIBkhq6gR36O9XJJ1jYgRFWL1oanpjuM2EmhKxhdy8IaY6VLie+89d+rjwtVb8vXJbLuY+jOm+aGskkQyoOOY8lsw5kQmBj/vCI5Hvlgo4zV4fadIuHNNg3hltP8RhsH9Djso6sPzo/2mWu08Wsjg/yXpJglddIiEI8Vx80eqS5gtDLe/osjIdVWbxd6E6fQlBjyZnuOTCG2x6IoiviMW1tRyNDMvqYS+k8Q0BoYS2ZlAMd/qweECXkwLKM2NVdXX0ZeC76ldVOFxy04Mg0Srhvng5/vMAN0S5DVCt9cKlAx3F5wJzaAuVN9u+EV6FEmW9XupKzJB5BPTSO1lOrAId4/xpwIXCRqlJhAC0mT2Qhy7VQucptPfwQSCSxix/q53G8HNmW7n2zCLR7B2MPbuK7LuIFMlvHMEF96mkTrfdWfSTXDw8BUaJCQdfCSu01MLBmO142j/ovPr6DZKd212oQygSOsXYAmvOIgkrjDuN+ANxWUbNscUKGvHk1cgACdEGNpcBw+CaPOXJDodtoKA6sUqyXmCc8ZmQJazOc45+nbOkaIBoG8TJY8QnoWhuxGDZYTAabRStH1TlVOLuGrrfEhBWNGfmL2/NU+BHLog/CpeilSzpIHQc8FrJSwQz2trBCyHgqKINf54zlBZL5NxdDPSETr+QOSwsZzZFdf5CyFhB9S0tg5KOknqa1j+KXVXJpQmKutKJI4f3oPdQb7yWkD5d0RAkKicvqzvCI6oYpBcZqpdbIqr52JxFk8uzRUywUp3dHp1chuTECkVrD5YzJEbH2lzFxknpvSMxemp8NAW+pDBoff0UENQpbJa05qeQJoG2l6ih5bwClDil3sZuCEAh8iJ7SSdH+0jih9Cw5/TjYSgzeiBYwMNbC7ZjIOu5l9jqqFB0PH1Z/HV1zo8PHizR1STADO9Y8LdW6nGhZXMltmJqHZBqxIIocZSVJ1V8RdjP3McTk8VrmE5+1ygWzAMyIoiV3vVh4GLrp9WXBHbY5ZXyt0+oaBhwbWIB6zqsYEGDiF4mJRNuay9r5zAzGneS8BEu3Od8cnDwaTW7bQ3k7PxJzzcGttnaUNSMuFDfUqsVHhnVUFp586s4WN/YqUikU83Y79JiY5/kK9unNPWk0qHh1vig3sjMMHEWdEToLvTvsryGIwm8YmNWnni3lO76IyvB1Pv+q+SVOCFUbUGk5+WBd5EEyWAX37E7VXVJg/lrJ9h0+2dLKExQESuvIeGgKDXjZwAyighjTrwdHgqEeOL0upxHgAp24Z6TTEO5ExRHMblKGJzgqGFh/y/74NdxD+RlbXp08mGV/xysAvoU+HPqD4CdHebP37DstlSxVBt18Tu+bPE3sbfPEkxsOfEk9I0fZJoR4kD6KXfyJphQkdLL14dpKb7lPT7uI9IGNSTbIlN8UYihLTadHkpADLrn2WB2hN29nIiZpMs1uswZzFdUxTS39CcDAOAUKtpLlb+mMZi8QUxpJy91pZ6/VCKLB0aLGoWiGw4BSavbLsGt4Yvv0JgUxrhgNLoBOGnS4sCoYkiVMRBl76TugAwhykLb8M9vJSVFC+LI1DBEERUTSvzaBZOTkcIBINI2QJZ/deoHQQ6sYaJWcnaV3ylhU53tVk9C1Fo2XHlkQKGKGLSl87zvFbNYivkeaPC8r/rRxcgqlxGNwni71YRaf/EoBx6soh/GBUHVUu5QylDhJFgVbJIdB0VE0SCto0aUJHzUj4fKT6onxWahsyOYU2iqQJSAP//33tK84OIeldqn04YN0Lp/X22e2n8FJaxJcjCe4b9y36sHfUnyU+piBEiAnfJ8d2V9YjstFO3abTqSRkd2fKxQOW/PFOJaNUTTBhLmAKmCZ1JgX7R8VwP8GH0ZWIF3EAohQyWWDJqKJfTZlsW1dkBm7WPEHNABmFUDZNsPcZEBMsOvT6YoslyBqZHc4n7egx4iAvfwLihu+hUdYAwvtUROnoAtB3KMAtkWlhigzgdb7qz6xMAiF+CFTUY/2shP86aOp+SHMcaBRMs2VrhHrHIET2TQE7AXcB9+nni3ERjHypPwpCxXH/ZkM1CJR1T0Oo2czVSHrQ1AcONS0vpjNOC2t0P5H9awhUuPvNf89KiO6A0sAHAYrfIlEkSg3BThdVQN6OhJVLQIN5NuDrdNoqFHO2q4Ns9I4J7bjmSXGy31Gxa8EWRS3aeebVW8g738Bp9MPJ0/pPNnfFWvY1CC0zBi9WDkERV+n8rk+8WM75dAbT56eTE7/M1i+gQWzIKeLdilg7/AvVwPXPhI8zgUWuWiCCZkZW0yLvUnuKBU93iohkUjdaRTdcl6IsvPLSy/sZEH+Hm/l9MTyguD7DeLEDxEVsCjrFVLtDto2bDn6ErBNsoKZI7iQRLF+j19Zezr7Q2GusOJ8iAyOL8ix9CmZMTAOXFHtqW7Y0daeoWnic413A2SfTY8YhwsWFoNSO1gEErvi1NiWZ7f0W812e2+ha9qRuIyUideyh+wZGKImBmZNUnRsTyY1BGJemuHL4wD0jWW4gk9Xb714dgTyGU3b4vDr8GzU+Ku+WALpY3LGFXJp2AS0MCfpbarbeBlV2TMmDCxrM9s4AVPRCOhux589bsBsJif1Ej8FIT6G1dEiop2Xo5ugDDd2Z5lZDXqkwSnWIlQiad8fmTeGrLajhm6K5lhWDiiAtg7W6HNUpqA/9cBEBUIYZu4wPLjjLVD05O7rGztjjMQSXeb9mjDAoJQYvvN+CYCQ3zNaSA3lMBrWEMZscsND6S9QrDi1Zx06XN2JHYUkZYMGRLQuzs1nIZ4u51+CwomVhU6a6cEdVM/k0mu0nkSP2ayVTgAZzh05FhFlXkSo4QFYzp1IIf7O+rOv3ni4/RDHY1iESmdO/EioeqGn99N32mWzSb3M+AscqrCS2M8t/8pCCYNDN4WHa4lIuBqbaMkImRbKTWIbSZz+1iEjDUb4QXwQmxLw3p6mWhJ7cjhn1a/GDcymigsFTvUKboN6rJQgGDjKoGGTdec6gfiyYXlZKpe7o7OrEp2VZO4UZJcWVQ+yq9ojJUzAesioNzdEIyaaKNy/9NkbEl/dRVbZw8a3bW2RERYf03GJ+4K8fNEO8QP6sf9riL7UduUUeE00iHwFJLUmDZyiwSJ5oi7GVPtWpgYQDqZt+vw2VoxappENGO5i8Iea3RqO1T0SGI8w0SM2GopgWY9Lbr5KALTujideljf8fHFPvpW4lVhmkaquCmxwlPgBY9uaZGxxnyymRmuEJG1B7Vd0j8MYyrJX50QJMipUseFdDFyuxd78KkrmuH9bzJ5gAqKOpJmNEKxwQ+ZxQnnp3Lu787AkYe4qTnlcsLDiMw==\",\"num_bits\":24270,\"seeds\":[0,1,2,3,4,5,6,7,8,9]},\"is_enabled\":true,\"platforms\":[{\"html_selectors\":[\"meta[name='serialized-api-client-id']\"],\"name\":\"shopify\",\"template_id\":1,\"url_path_regex\":\"/checkouts\"},{\"html_selectors\":[\"meta[name='shopify-checkout-api-token']\"],\"name\":\"shopify\",\"template_id\":2,\"url_path_regex\":\"/\\\\d+/checkouts\"},{\"html_selectors\":[\"body.woocommerce-checkout\"],\"name\":\"woocommerce\",\"template_id\":1,\"url_path_regex\":\"/checkout/\"},{\"html_selectors\":[\"meta[name='generator'][content='Wix.com Website Builder']\"],\"name\":\"wix\",\"template_id\":1,\"url_path_regex\":\"/checkout\"},{\"html_selectors\":[\"body#sqs-standard-checkout\"],\"name\":\"squarespace\",\"template_id\":1,\"url_path_regex\":\"/checkout\"},{\"html_selectors\":[\"meta[name='shopify-checkout-authorization-token']\"],\"name\":\"shopify\",\"template_id\":4,\"url_path_regex\":\"/checkouts\"},{\"html_selectors\":[\"meta[name='shopify-digital-wallet']\"],\"name\":\"shopify\",\"template_id\":4,\"url_path_regex\":\"/checkouts\"},{\"html_selectors\":[\"head link[href*='cdn.shopify.com/shopifycloud/checkout-web']\"],\"name\":\"shopify\",\"template_id\":1,\"url_path_regex\":\"/checkouts\"},{\"html_selectors\":[\"head > #woocommerce-inline-inline-css\"],\"name\":\"woocommerce\",\"template_id\":1,\"url_path_regex\":\"/checkout/\"},{\"html_selectors\":[\"script[data-requiremodule='magentoStorefrontEvents']\"],\"name\":\"adobe\",\"template_id\":1,\"url_path_regex\":\"/checkout/\"},{\"html_selectors\":[\"script[src*='bolt.com']\"],\"name\":\"bolt\",\"template_id\":1,\"url_path_regex\":\"/\"},{\"html_selectors\":[\"div.StripeElement > div[class*='PrivateStripeElement'] > iframe[title='Secure payment input frame']\"],\"name\":\"stripe\",\"template_id\":1,\"url_path_regex\":\"/\"}]},\"topsite_config\":{\"disabled_features\":[],\"eligible_sites\":[\"bedbathandbeyond.com\",\"fanatics.com\",\"roamingst.webxtsvc-int.microsoft.com\",\"dominos.com\",\"commerce.adobe.com\",\"hilton.com\",\"aa.com\",\"mcafee.com\",\"expedia.com\",\"paypal.com\",\"spotify.com\",\"netflix.com\",\"papajohns.com\",\"pay.openai.com\",\"bestbuy.com\",\"pay.ebay.com\",\"lowes.com\",\"checkout.stripe.com\",\"alaskaair.com\",\"pay.ebay.de\",\"bathandbodyworks.com\",\"walmart.com\",\"target.com\",\"pay.ebay.co.uk\",\"pay.gov\",\"secure.booking.com\",\"kohls.com\",\"marriott.com\",\"signup.hulu.com\",\"basket.step.rakuten.co.jp\",\"southwest.com\",\"hotels.com\",\"secure.wayfair.com\",\"jcpenney.com\",\"delta.com\",\"pay.usps.com\",\"secureacceptance.cybersource.com\",\"ihg.com\",\"amazon.com\",\"amazon.co.uk\",\"etsy.com\",\"homedepot.com\",\"pdffiller.com\",\"shop.app\",\"nike.com\",\"youtube.com\",\"checkout.microsoft365.com\",\"connect.intuit.com\",\"sis.redsys.es\",\"sbs.e-paycapita.com\",\"card.payments.service.gov.uk\",\"payments.worldpay.com\",\"app.squareup.com\",\"send.royalmail.com\",\"premierinn.com\",\"easyjet.com\",\"britishairways.com\",\"staples.com\",\"canva.com\",\"epayment.nets.eu\",\"hpp.worldpay.com\",\"temu.com\",\"saferpay.com\",\"secure.payzen.eu\",\"peacocktv.com\",\"sec.windcave.com\",\"ipg-online.com\",\"fep.sps-system.com\",\"account.microsoft.com\",\"checkout.globalgatewaye4.firstdata.com\",\"magic.collectorsolutions.com\",\"3dsecure.gpwebpay.com\",\"aliexpress.com\",\"ipn.paymentus.com\",\"commerce.cashnet.com\",\"payment-web.sips-services.com\",\"pizzahut.com\",\"p.monetico-services.com\",\"linkedin.com\",\"turbospn.com\",\"nbc.sbi.co.in\",\"rayexpress.raysigorta.com.tr\",\"cebs.prod.fedex.com\",\"authentication.td.com\",\"hwts.hilton.com\",\"step.soa.webapp.dst.baintern.de\",\"forms.office.com\",\"crm.izzi.mx\",\"rlms.sbi\",\"advisorpro.allstate.com\",\"sise.cjf.gob.mx\",\"qbo.intuit.com\",\"avantius.justizia.eus\",\"cibconline.cibc.com\",\"content.lifecycle.office.net\",\"reportes.interrapidisimo.com\",\"cashmanagement.barclays.net\",\"pstcdypisr.clouda.sat.gob.mx\",\"edus.ccss.sa.cr\",\"spoolnetng.axa-fr.intraxa\",\"adaptedmind.com\",\"stportal.bmi.intra.gv.at\",\"gab.com\",\"store.malwarebytes.com\",\"client-central.com\",\"apps.powerapps.com\",\"microsoft.com\",\"roblox.com\",\"e-menu.sunat.gob.pe\",\"usa.experian.com\",\"clover.com\",\"payment.smart-glocal.com\",\"wwwmat.sat.gob.mx\",\"sgp.justicia.aragon.es\",\"pheds.imss.gob.mx\",\"convergepay.com\",\"pay.hotmart.com\",\"pmu.fr\",\"login.pep.hilton.com\",\"sbiepay.sbi\",\"paytrace.com\",\"account.authorize.net\",\"farm3.sat.gob.gt\",\"sd20.finanze.it\",\"borjoperations.attijariwafa.net\",\"w2.seg-social.es\",\"eue.gde.gob.ar\",\"amazon.fr\",\"businesscentral.dynamics.com\",\"fedex.com\",\"pmb.rectanglehealth.com\",\"pgi.billdesk.com\",\"nfe.prefeitura.sp.gov.br\",\"sevenrooms.com\",\"wb.authentication.td.com\",\"genawmprod.generali.it\",\"application.littlehotelier.com\",\"mrkoll.se\",\"apps.facebook.com\",\"choiceadvantage.com\",\"pc-prod-gwcpprod.promutuel.delta2-butterfly.guidewire.net\",\"acente.magdeburger.com.tr\",\"crmnext.hbctxdom.com\",\"facebook.com\",\"servint.madrid.es\",\"openjet.inhealth.ae\",\"agentsm.spectrummobile.com\",\"sncf-connect.com\",\"bancanetempresarial.citibanamex.com.mx\",\"ryanair.com\",\"pbmdeapcsc01.bancolombia.corp\",\"m.skybet.com\",\"uline.com\",\"clients.mindbodyonline.com\",\"online.instamed.com\",\"hoc.bt.wan\",\"shop.win-rar.com\",\"qy96596.com\",\"app.pennylane.com\",\"checkout.ticketmaster.com\",\"servizi.mit.gov.it\",\"members.pscufs.com\",\"secure.athenahealthpayment.com\",\"app.hubspot.com\",\"es.intrallianz.com\",\"ins.crm.dynamics.com\",\"mcmeehr.me.hcnet.biz\",\"internet.speedpay.com\",\"vereda.cantabria.es\",\"091402wb236.infonavit.net\",\"flights.ctrip.com\",\"elcorteinglessa.lightning.force.com\",\"assure.ameli.fr\",\"elster.de\",\"kmart.com.au\",\"loginunico.viabcp.com\",\"portalgrupo.elcorteingles.int\",\"wz.skt.ccta.dk\",\"trak.ufh.com\",\"gestionprocesal.admon-cfnavarra.es\",\"vehicletax.service.gov.uk\",\"portal.sisbr.coop.br\",\"extranet.chie.junta-andalucia.es\",\"ryanair.com\",\"clientesviajeselcorteingles.lightning.force.com\",\"royalcaribbean.com\",\"hmsweb.hms.eu1.inforcloudsuite.com\",\"arsiv.mackolik.com\",\"adultfriendfinder.com\",\"dropbox.com\",\"sicop.go.cr\",\"paiement.systempay.fr\",\"husll-sisn2.ssib.es\",\"alogic.myeyedr.com\",\"securecheckout.cdc.nicusa.com\",\"united.com\",\"adquiramexico.com.mx\",\"wps.kessai.info\",\"payment.parchment.com\",\"us-east-2.turbotaxonline.intuit.com\",\"us-west-2.turbotaxonline.intuit.com\",\"freetaxusa.com\",\"tax.service.gov.uk\",\"taxes.hrblock.com\",\"securecheckout-fl.cdc.nicusa.com\",\"internet.speedpay.com\",\"facebook.com\"],\"enabled_features\":[],\"extra_sites\":{\"4th_extra_sites\":[],\"recovery_sites\":[\"easyjet.com\"]},\"inline_sites\":[\"amazon.com\",\"roamingst.webxtsvc-int.microsoft.com\",\"ihg.com\",\"mcafee.com\",\"hotels.com\",\"pay.ebay.de\",\"papajohns.com\",\"fanatics.com\",\"pay.ebay.co.uk\",\"pay.ebay.com\",\"bedbathandbeyond.com\",\"etsy.com\",\"secure.booking.com\",\"nike.com\",\"kohls.com\",\"staples.com\",\"paypal.com\",\"homedepot.com\",\"shop.app\",\"checkout.stripe.com\",\"securecheckout.cdc.nicusa.com\",\"expedia.com\",\"hilton.com\",\"marriott.com\",\"pizzahut.com\",\"delta.com\",\"lowes.com\",\"secure.wayfair.com\",\"target.com\",\"amazon.co.uk\",\"jcpenney.com\",\"britishairways.com\",\"bathandbodyworks.com\",\"ryanair.com\",\"dominos.com\",\"facebook.com\"],\"is_enabled\":true,\"recovering_sites\":[]},\"version\":256}","global_config_last_updated_time":"13406596515609202","global_daf_config_last_updated_time":"13406596515643198"},"passwords":{"password_lost_report_date":"13406596242724149"},"trigger_funnel":{"records":[]}},"enterprise_profile_guid":"57f523ac-5c53-412a-beef-654a44589f4f","extension":{"installed_extension_count":11,"ublock_extension_installed_days":0},"extensions":{"alerts":{"initialized":true},"chrome_url_overrides":{},"commands":{},"edge_default_installed_cws_extensions_update_frequency":9,"install_signature":{"expire_date":"2026-01-25","ids":["ghbmnnjooekpmoecnnnilnnbdlolhkhi"],"invalid_ids":["odfafepnkmbhccpbejgmiehpchacaeak"],"salt":"DZdhhSsczQDT4sHQGHUNH5OybTVlijpnk9wtAc9OhOI=","signature":"P5Qqyx2WS9zJX75Y+s+rl9zsyv5xDpJBz4HKcB0Vtm1qjT9edheL4EuMKpehcynQG5LSotNaJ7jif+gNiVAtyhksQRnbKVvGBE9Da+6TXX5UCRArfTnUrVKxR1Y46UlQdugJaBoRImOoMW+2RXq96jbdaioV8J6MxacXW0/avz+TxLjAtFPwDoySPl3I9Pkwlh3ShLG2EGtWHzAm8H3VM7lBmrscNan8oOye42j3GY2/3uhkPMKnAc75c6lQ3+3H/dLrF2jgGs26j7naQ6xU3IMi3E0AMOBm1adQCry9EZ4/LktNvI7AN/jNJooKyfF9CH2zkPwDCNDW98MRAcd+3A==","signature_format_version":2,"timestamp":"13406596449041768"},"last_chrome_version":"142.0.3595.53","microsoft_install_signature":{"expire_date":"2026-01-25","ids":["jmjflgjpcpepeafmmgdpfkogkghcpiha","odfafepnkmbhccpbejgmiehpchacaeak"],"invalid_ids":[],"salt":"FLP+4UaOtEk5fIHS+1+v4o83oevMo2N/ibfTPY3Y0o8=","signature":"FQr9FJB97y2qfvMxOLjA3MTT2vDn/JWcfe9SN17M/lOvNRb5/ef3V256NvTh+b/A8DgR6Hq2kXwc5P+pShVN1+ujJUZSeOdUmhFbBFkhj/XGRK4VZL5SLjOHobzxD8Yen0MLxpSbkpfmScZ4YyK6vJ9a0l2IRKut3VABcfXtDztnEuUZPo9yIAxVxQVE31TK6Lip4kFGClpTuT5bQGspfF9ix0hduC2YrGdA8OdGS22+SjgsMmH26cQw0sxLhzLCNO/SyKDCtnKr1nvTBPxUI4Log8xLAb8ESveAT/XhbzsdJiIatMf8yvBP8/Tx7ElgwhUerUejvgiduaW5fCkcTA==","signature_format_version":2,"timestamp":"13406596447163861"},"pdf_upsell_triggered":false,"pinned_extension_migration":true,"pinned_extensions":[]},"fsd":{"retention_policy_last_version":142},"gaia_cookie":{"periodic_report_time_2":"13406596212721691"},"history_hub":{"active_pivot_tab":"history-pivot"},"https_upgrade_navigations":{"2025-11-02":30},"intl":{"selected_languages":"en-US,en"},"language_dwell_time_average":{"en":21.263157894736842},"language_model_counters":{"en":22},"language_usage_count":{"en":19},"media":{"engagement":{"schema_version":5}},"media_router":{"receiver_id_hash_token":"R232aXSsIN9l04dEXqe6UCQWr67GFC5zjY7mRS+hWbyTfA5HwTe8teAv4fRI+tlDIEBQ0hlWE65hzRi+fG2HvQ=="},"muid":{"last_sync":"13406596213012735","values_seen":["0BFC81B90AF664D92DE2973F0BE265AD"]},"ntp":{"background_image":{"configIndex":39,"imageId":"BB1msyOc","provider":"CMSImage","userSelected":false},"dhp_last_creation_time":"13404976874523727","feed_engagement_time":"11646235722925000","next_site_suggestions_available":false,"ntp_last_creation_time_v2":"13406597214815302","num_personal_suggestions":1,"prerender_contents_height":996,"prerender_contents_width":3832,"record_user_choices":[{"setting":"ruby_cookie_change_history","source":"ntp","timestamp":1.760503275169e+12,"value":"2|1760503275169|0"},{"setting":"is_ruby_page","source":"ntp","timestamp":1.762123629894e+12,"value":"0"},{"setting":"ntp.is_ruby","source":"ntp","timestamp":1.762123630511e+12,"value":"false"},{"setting":"ruby_state_history","source":"ntp","timestamp":1.762123630511e+12,"value":"1_8->1_8|1762123630511"},{"setting":"breaking_news_dismissed","source":"ntp","timestamp":1.762123054637e+12,"value":{}},{"setting":"ruby_set_history","source":"ntp","timestamp":1.762123629826e+12,"value":"true"},{"setting":"ruby_ux_history","source":"ntp","timestamp":1.762123629826e+12,"value":"false"},{"setting":"seen_interest_fre_count","source":"ntp","timestamp":1.762122637223e+12,"value":3}],"selected_feed_pivot":"myFeed","user_nurturing":[{"key":"background_setting_preferences","value":{"changeBackgroundDaily":true,"selectedVideoSetting":"balanced"}},{"key":"wpo_nx","value":{"cpt":true,"lyp":{"fromFeed":"2","fromLayout":"1","isPr":true,"isRvert":false,"knobIdx":"p34000","knobIdxPrefix":"p","lypType":"promotion","muid":"m-0BFC81B90AF664D92DE2973F0BE265AD","proLayout":2,"rid":"6907dd3f53314546af3f28cbb04345f4","source":"","time":1.762123072941e+12,"tmpl":"prg-wpo-sptif"},"v":"2"}},{"key":"sptmarket","value":{"setting":"sptmarket","source":"ntp","timestamp":1.762123616424e+12,"value":"en-US||us|en-us|en-us|en||reason=RevIP:us|cf=9|RefA=68ef25ea89004dce92e373d2682fc52d.RefC=2025-10-15T04:41:14Z"}},{"key":"layoutPromotion"},{"key":"ruby_targeted_version","value":{"value":"null|6907df6dc4e2447c88ff951d76fdacbc|false|1762123630510"}},{"key":"viewport","value":{"height":996,"width":3832}},{"key":"ruby_flight_history","value":{"setting":"ruby_flight_history","source":"ntp","timestamp":1.762123629827e+12,"value":"prg-rubyntp9"}},{"key":"nurturing_campaigns","value":{"placementsInteractions":{"personalizeManageText":[{"ts":1.762122919339e+12,"type":"Viewed"},{"ts":1.762122921392e+12,"type":"Closed"}]},"trace_id":1.760503275737e+12,"version":0.2}}]},"nurturing":{"time_of_last_sync_consent_view":"13404976874973472"},"optimization_guide":{"hintsfetcher":{"hosts_successfully_fetched":{}},"previously_registered_optimization_types":{"ABOUT_THIS_SITE":true,"GLIC_ACTION_PAGE_BLOCK":true,"HISTORY_CLUSTERS":true,"LOADING_PREDICTOR":true,"MERCHANT_TRUST_SIGNALS_V2":true,"PAGE_ENTITIES":true,"PRICE_INSIGHTS":true,"PRICE_TRACKING":true,"SALIENT_IMAGE":true,"SAVED_TAB_GROUP":true,"SHOPPING_DISCOUNTS":true,"SHOPPING_PAGE_TYPES":true,"V8_COMPILE_HINTS":true}},"password_manager":{"account_store_backup_password_cleaning_last_timestamp":"13406596272721670","account_store_migrated_to_os_crypt_async":true,"profile_store_backup_password_cleaning_last_timestamp":"13406596272721517","profile_store_migrated_to_os_crypt_async":true,"relaunch_chrome_bubble_dismissed_counter":0},"personalization_data_consent":{"personalization_in_context_consent_can_prompt":true,"personalization_in_context_count":0},"privacy_sandbox":{"first_party_sets_data_access_allowed_initialized":true},"profile":{"avatar_index":20,"content_settings":{"exceptions":{"3pcd_heuristics_grants":{},"3pcd_support":{},"abusive_notification_permissions":{},"access_to_get_all_screens_media_in_session":{},"anti_abuse":{},"app_banner":{"https://cursor.com:443,*":{"last_modified":"13406596597929416","setting":{"https://cursor.com/":{"couldShowBannerEvents":1.3406596579434592e+16,"next_install_text_animation":{"last_shown":"13406596597929409","shown_count":1}}}},"https://github.com:443,*":{"last_modified":"13406596677577238","setting":{"https://github.com/":{"couldShowBannerEvents":1.3406596677577234e+16,"next_install_text_animation":{"last_shown":"13406596677576891","shown_count":1}}}}},"ar":{},"are_suspicious_notifications_allowlisted_by_user":{},"auto_picture_in_picture":{},"auto_select_certificate":{},"automatic_downloads":{},"automatic_fullscreen":{},"autoplay":{},"background_sync":{},"bluetooth_chooser_data":{},"bluetooth_guard":{},"bluetooth_scanning":{},"camera_pan_tilt_zoom":{},"captured_surface_control":{},"clear_browsing_data_cookies_exceptions":{},"client_hints":{"https://cursor.com:443,*":{"last_modified":"13406596578379066","setting":{"client_hints":[9,10,14,16]}},"https://ntp.msn.com:443,*":{"last_modified":"13406597229707237","setting":{"client_hints":[0,4,5,6,8,9,10,11,12,13,14,15,16,18,20,22,23]}},"https://www.bing.com:443,*":{"last_modified":"13406597244036354","setting":{"client_hints":[9,10,11,12,13,14,16,23]}},"https://www.microsoft.com:443,*":{"last_modified":"13406596213431553","setting":{"client_hints":[9,11,13,14,15,16]}}},"clipboard":{},"controlled_frame":{},"cookie_controls_metadata":{"https://[*.]arstechnica.com,*":{"last_modified":"13406596563378893","setting":{}},"https://[*.]bing.com,*":{"last_modified":"13406597244040368","setting":{}},"https://[*.]cnn.com,*":{"last_modified":"13406596270732801","setting":{}},"https://[*.]duckduckgo.com,*":{"last_modified":"13406597253723123","setting":{}},"https://[*.]github.com,*":{"last_modified":"13406596692737920","setting":{}},"https://[*.]microsoft.com,*":{"last_modified":"13406597216274135","setting":{}},"https://[*.]osquery.io,*":{"last_modified":"13406596660776596","setting":{}},"https://[*.]washingtonpost.com,*":{"last_modified":"13406596535078915","setting":{}}},"cookies":{},"direct_sockets":{},"direct_sockets_private_network_access":{},"display_media_system_audio":{},"disruptive_notification_permissions":{},"durable_storage":{},"edge_ad_targeting":{},"edge_ad_targeting_data":{},"edge_browser_action":{},"edge_sdsm":{},"edge_split_screen":{},"edge_tech_scam_detection":{},"edge_u2f_api_request":{},"edge_user_agent_token":{},"fedcm_idp_registration":{},"fedcm_idp_signin":{},"fedcm_share":{},"file_system_access_chooser_data":{},"file_system_access_extended_permission":{},"file_system_access_restore_permission":{},"file_system_last_picked_directory":{},"file_system_read_guard":{},"file_system_write_guard":{},"formfill_metadata":{},"geolocation":{},"geolocation_with_options":{},"hand_tracking":{},"hid_chooser_data":{},"hid_guard":{},"http_allowed":{},"https_enforced":{},"idle_detection":{},"images":{},"important_site_info":{},"initialized_translations":{},"intent_picker_auto_display":{},"javascript":{},"javascript_jit":{},"javascript_optimizer":{},"keyboard_lock":{},"legacy_cookie_access":{},"legacy_cookie_scope":{},"local_fonts":{},"local_network_access":{},"media_engagement":{"https://arstechnica.com:443,*":{"expiration":"13414372597934653","last_modified":"13406596597934656","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":1}},"https://cursor.com:443,*":{"expiration":"13414372653798219","last_modified":"13406596653798222","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":1}},"https://duckduckgo.com:443,*":{"expiration":"13414373266984256","last_modified":"13406597266984258","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":1}},"https://github.com:443,*":{"expiration":"13414372812128150","last_modified":"13406596812128152","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":2}},"https://microsoftedge.microsoft.com:443,*":{"expiration":"13414372470134070","last_modified":"13406596470134074","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":1}},"https://ntp.msn.com:443,*":{"expiration":"13414373266980654","last_modified":"13406597266980657","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":4}},"https://www.bing.com:443,*":{"expiration":"13414373266988630","last_modified":"13406597266988633","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":6}},"https://www.cnn.com:443,*":{"expiration":"13414372391982821","last_modified":"13406596391982823","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":1}},"https://www.microsoft.com:443,*":{"expiration":"13414373241301014","last_modified":"13406597241301015","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":2}},"https://www.osquery.io:443,*":{"expiration":"13414372674165536","last_modified":"13406596674165537","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":1}},"https://www.washingtonpost.com:443,*":{"expiration":"13414372540686067","last_modified":"13406596540686071","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":1}}},"media_stream_camera":{},"media_stream_mic":{},"midi_sysex":{},"mixed_script":{},"nfc_devices":{},"notification_interactions":{},"notification_permission_review":{},"notifications":{},"ondevice_languages_downloaded":{},"password_protection":{},"payment_handler":{},"permission_actions_history":{},"permission_autoblocking_data":{},"permission_autorevocation_data":{},"pointer_lock":{},"popups":{},"protocol_handler":{},"reduced_accept_language":{},"safe_browsing_url_check_data":{},"secure_network":{},"secure_network_sites":{},"sensors":{},"serial_chooser_data":{},"serial_guard":{},"site_engagement":{"edge://extensions/,*":{"last_modified":"13406596397510939","setting":{"lastEngagementTime":1.3406596397510936e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":3.0,"rawScore":3.0}},"edge://settings/,*":{"last_modified":"13406597222414454","setting":{"lastEngagementTime":1.3406597222414452e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":3.0,"rawScore":3.0}},"https://arstechnica.com:443,*":{"last_modified":"13406596595396826","setting":{"lastEngagementTime":1.3406596595396758e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":3.9000000000000004,"rawScore":3.9000000000000004}},"https://cursor.com:443,*":{"last_modified":"13406596643058569","setting":{"lastEngagementTime":1.3406596643058514e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":4.5,"rawScore":4.5}},"https://duckduckgo.com:443,*":{"last_modified":"13406597264310711","setting":{"lastEngagementTime":1.34065972643107e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":1.56,"rawScore":1.56}},"https://microsoftedge.microsoft.com:443,*":{"last_modified":"13406596445364462","setting":{"lastEngagementTime":1.3406596445364416e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":3.3000000000000003,"rawScore":3.3000000000000003}},"https://ntp.msn.com:443,*":{"last_modified":"13406597215974985","setting":{"lastEngagementTime":1.3406597215974968e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":5.1,"rawScore":8.022507}},"https://www.bing.com:443,*":{"last_modified":"13406597241301550","setting":{"lastEngagementTime":1.3406597241301532e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":10.5,"rawScore":10.5}},"https://www.cnn.com:443,*":{"last_modified":"13406596385736793","setting":{"lastEngagementTime":1.3406596385736748e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":8.459999999999996,"rawScore":8.459999999999996}},"https://www.microsoft.com:443,*":{"last_modified":"13406597216275199","setting":{"lastEngagementTime":1.340659721627518e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":5.1,"rawScore":5.1}},"https://www.washingtonpost.com:443,*":{"last_modified":"13406596503991101","setting":{"lastEngagementTime":1.3406596503991088e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":2.1,"rawScore":2.1}}},"sleeping_tabs":{},"sound":{},"speaker_selection":{},"ssl_cert_decisions":{},"storage_access":{},"storage_access_header_origin_trial":{},"subresource_filter":{},"subresource_filter_data":{},"suspicious_notification_ids":{},"suspicious_notification_show_original":{},"tech_scam_detection":{},"third_party_storage_partitioning":{},"top_level_3pcd_origin_trial":{},"top_level_3pcd_support":{},"top_level_storage_access":{},"trackers":{},"trackers_data":{"https://1f2e7.v.fwmrm.net:443,*":{"last_modified":"13406596265578463","setting":{"count":1}},"https://a.jsrdn.com:443,*":{"last_modified":"13406596273462397","setting":{"count":2}},"https://a.teads.tv:443,*":{"last_modified":"13406596284397749","setting":{"count":1}},"https://a.usbrowserspeed.com:443,*":{"last_modified":"13406596266026291","setting":{"allowed_tracker_count":1}},"https://a125375509.cdn.optimizely.com:443,*":{"last_modified":"13406596271887785","setting":{"allowed_tracker_count":2}},"https://a5586.casalemedia.com:443,*":{"last_modified":"13406596375855610","setting":{"count":1}},"https://a6115.casalemedia.com:443,*":{"last_modified":"13406596290396192","setting":{"count":1}},"https://aa.agkn.com:443,*":{"last_modified":"13406596266021941","setting":{"count":1}},"https://aax.amazon-adsystem.com:443,*":{"last_modified":"13406596275964045","setting":{"count":1}},"https://ad-us-west.ipredictive.com:443,*":{"last_modified":"13406596267799837","setting":{"count":1}},"https://ad.360yield.com:443,*":{"last_modified":"13406596266024317","setting":{"count":1}},"https://ad.doubleclick.net:443,*":{"last_modified":"13406596285267459","setting":{"count":1}},"https://ads.pubmatic.com:443,*":{"last_modified":"13406596270744303","setting":{"count":2}},"https://ads.stickyadstv.com:443,*":{"last_modified":"13406596265238768","setting":{"count":1}},"https://agent.intentiq.com:443,*":{"last_modified":"13406596264725782","setting":{"count":1}},"https://amplify.outbrain.com:443,*":{"last_modified":"13406596265584257","setting":{"count":1}},"https://apex.go.sonobi.com:443,*":{"last_modified":"13406596274193825","setting":{"count":1}},"https://api.hcaptcha.com:443,*":{"last_modified":"13406596563901020","setting":{"count":2}},"https://api.intentiq.com:443,*":{"last_modified":"13406596266029427","setting":{"count":1}},"https://api.rlcdn.com:443,*":{"last_modified":"13406596272303114","setting":{"count":2}},"https://as-sec.casalemedia.com:443,*":{"last_modified":"13406596274867962","setting":{"count":1}},"https://assets.bounceexchange.com:443,*":{"last_modified":"13406596272442457","setting":{"count":2}},"https://b1sync.outbrain.com:443,*":{"last_modified":"13406596285117927","setting":{"count":1}},"https://b1sync.zemanta.com:443,*":{"last_modified":"13406596285499868","setting":{"count":2}},"https://b81f0088b0e88572964cad80024b25c4.safeframe.googlesyndication.com:443,*":{"last_modified":"13406596266372587","setting":{"count":1}},"https://bea4.v.fwmrm.net:443,*":{"last_modified":"13406596277362233","setting":{"count":2}},"https://beacon-iad2.rubiconproject.com:443,*":{"last_modified":"13406596285094338","setting":{"count":1}},"https://bidder.criteo.com:443,*":{"last_modified":"13406596276021891","setting":{"count":1}},"https://btloader.com:443,*":{"last_modified":"13406596272317078","setting":{"count":2}},"https://bttrack.com:443,*":{"last_modified":"13406596285120403","setting":{"count":1}},"https://c.amazon-adsystem.com:443,*":{"last_modified":"13406596272302928","setting":{"count":2}},"https://c.clarity.ms:443,*":{"last_modified":"13406596215295065","setting":{"allowed_tracker_count":1}},"https://c.jsrdn.com:443,*":{"last_modified":"13406596273124609","setting":{"count":1}},"https://cdn.adsafeprotected.com:443,*":{"last_modified":"13406596265238459","setting":{"count":1}},"https://cdn.boomtrain.com:443,*":{"last_modified":"13406596265702337","setting":{"count":1}},"https://cdn.cookielaw.org:443,*":{"last_modified":"13406596535164103","setting":{"count":2}},"https://cdn.doubleverify.com:443,*":{"last_modified":"13406596285392119","setting":{"allowed_tracker_count":1}},"https://cdn.flashtalking.com:443,*":{"last_modified":"13406596376186635","setting":{"count":1}},"https://cdn.id5-sync.com:443,*":{"last_modified":"13406596264888147","setting":{"count":1}},"https://cdn.indexww.com:443,*":{"last_modified":"13406596275831296","setting":{"count":2}},"https://cdn.jsdelivr.net:443,*":{"last_modified":"13406596266979878","setting":{"allowed_tracker_count":1}},"https://cdn.ml314.com:443,*":{"last_modified":"13406596271876337","setting":{"allowed_tracker_count":2}},"https://cdn.optimizely.com:443,*":{"last_modified":"13406596270821855","setting":{"allowed_tracker_count":2}},"https://cdn3.optimizely.com:443,*":{"last_modified":"13406596271682270","setting":{"allowed_tracker_count":2}},"https://cdnjs.cloudflare.com:443,*":{"last_modified":"13406596261682438","setting":{"allowed_tracker_count":1}},"https://choices.trustarc.com:443,*":{"last_modified":"13406596378237850","setting":{"count":1}},"https://choices.truste.com:443,*":{"last_modified":"13406596375856225","setting":{"count":1}},"https://cm.g.doubleclick.net:443,*":{"last_modified":"13406596278040766","setting":{"count":2}},"https://cm.rtbsystem.com:443,*":{"last_modified":"13406596266025260","setting":{"count":1}},"https://cms.quantserve.com:443,*":{"last_modified":"13406596285119868","setting":{"count":2}},"https://cnn.bounceexchange.com:443,*":{"last_modified":"13406596272509557","setting":{"count":2}},"https://config.aps.amazon-adsystem.com:443,*":{"last_modified":"13406596275590427","setting":{"count":2}},"https://creativecdn.com:443,*":{"last_modified":"13406596285118602","setting":{"count":2}},"https://cs.admanmedia.com:443,*":{"last_modified":"13406596266026084","setting":{"count":1}},"https://cs.media.net:443,*":{"last_modified":"13406596266025993","setting":{"count":1}},"https://csync.loopme.me:443,*":{"last_modified":"13406596266026191","setting":{"count":1}},"https://d9.flashtalking.com:443,*":{"last_modified":"13406596376185937","setting":{"count":1}},"https://dc6d9b88116cb6269060afcf43a2079b.safeframe.googlesyndication.com:443,*":{"last_modified":"13406596271964724","setting":{"count":1}},"https://direct.adsrvr.org:443,*":{"last_modified":"13406596272281729","setting":{"count":2}},"https://dis.criteo.com:443,*":{"last_modified":"13406596266022831","setting":{"count":1}},"https://distroscale-d.openx.net:443,*":{"last_modified":"13406596277521215","setting":{"count":1}},"https://dpm.demdex.net:443,*":{"last_modified":"13406596275692305","setting":{"count":2}},"https://dsp.adfarm1.adition.com:443,*":{"last_modified":"13406596285119468","setting":{"count":1}},"https://dt.adsafeprotected.com:443,*":{"last_modified":"13406596273858556","setting":{"count":2}},"https://eb2.3lift.com:443,*":{"last_modified":"13406596275680137","setting":{"count":2}},"https://ep1.adtrafficquality.google:443,*":{"last_modified":"13406596279995987","setting":{"allowed_tracker_count":1}},"https://ep2.adtrafficquality.google:443,*":{"last_modified":"13406596277481902","setting":{"allowed_tracker_count":1}},"https://eq97f.publishers.tremorhub.com:443,*":{"last_modified":"13406596277365913","setting":{"count":2}},"https://eus.rubiconproject.com:443,*":{"last_modified":"13406596275680062","setting":{"count":2}},"https://events.bouncex.net:443,*":{"last_modified":"13406596272637838","setting":{"count":2}},"https://exchange.postrelease.com:443,*":{"last_modified":"13406596272279747","setting":{"count":2}},"https://fastlane.rubiconproject.com:443,*":{"last_modified":"13406596272281787","setting":{"count":2}},"https://g.t.dyntrk.com:443,*":{"last_modified":"13406596285323847","setting":{"count":1}},"https://get.s-onetag.com:443,*":{"last_modified":"13406596271478054","setting":{"count":2}},"https://ghent-gce-or.bidswitch.net:443,*":{"last_modified":"13406596267798590","setting":{"count":1}},"https://googleads.g.doubleclick.net:443,*":{"last_modified":"13406596290394752","setting":{"count":1}},"https://grid-bidder.criteo.com:443,*":{"last_modified":"13406596272282251","setting":{"count":2}},"https://gum.criteo.com:443,*":{"last_modified":"13406596272760676","setting":{"count":2}},"https://hblg-nv.media.net:443,*":{"last_modified":"13406596268942827","setting":{"count":1}},"https://hblg.media.net:443,*":{"last_modified":"13406596267796218","setting":{"count":1}},"https://hbopenbid.pubmatic.com:443,*":{"last_modified":"13406596272284639","setting":{"count":2}},"https://hbx.media.net:443,*":{"last_modified":"13406596275679857","setting":{"count":2}},"https://htlb.casalemedia.com:443,*":{"last_modified":"13406596272282758","setting":{"count":2}},"https://i.jsrdn.com:443,*":{"last_modified":"13406596273463746","setting":{"count":2}},"https://ib.adnxs.com:443,*":{"last_modified":"13406596274694429","setting":{"allowed_tracker_count":2}},"https://id.crwdcntrl.net:443,*":{"last_modified":"13406596264888450","setting":{"allowed_tracker_count":1}},"https://id.geistm.com:443,*":{"last_modified":"13406596266023388","setting":{"count":1}},"https://id.rlcdn.com:443,*":{"last_modified":"13406596266024694","setting":{"count":1}},"https://id.sv.rkdms.com:443,*":{"last_modified":"13406596265591298","setting":{"count":1}},"https://id5-sync.com:443,*":{"last_modified":"13406596264887724","setting":{"count":1}},"https://idr.cdnwidget.com:443,*":{"last_modified":"13406596272856888","setting":{"count":2}},"https://ids.cdnwidget.com:443,*":{"last_modified":"13406596266825305","setting":{"count":1}},"https://idsync.rlcdn.com:443,*":{"last_modified":"13406596266019930","setting":{"count":1}},"https://idx.liadm.com:443,*":{"last_modified":"13406596272737944","setting":{"count":2}},"https://image2.pubmatic.com:443,*":{"last_modified":"13406596278263223","setting":{"count":1}},"https://image8.pubmatic.com:443,*":{"last_modified":"13406596270744703","setting":{"count":2}},"https://images.outbrainimg.com:443,*":{"last_modified":"13406596375546537","setting":{"count":1}},"https://jadserve.postrelease.com:443,*":{"last_modified":"13406596264728847","setting":{"count":1}},"https://js-sec.indexww.com:443,*":{"last_modified":"13406596273695947","setting":{"count":2}},"https://jsconfig.adsafeprotected.com:443,*":{"last_modified":"13406596273767086","setting":{"count":2}},"https://krk2.kargo.com:443,*":{"last_modified":"13406596272282451","setting":{"count":2}},"https://lexicon.33across.com:443,*":{"last_modified":"13406596266728497","setting":{"count":1}},"https://live.rezync.com:443,*":{"last_modified":"13406596271888898","setting":{"count":2}},"https://loadus.exelator.com:443,*":{"last_modified":"13406596266023826","setting":{"count":1}},"https://mabping.chartbeat.net:443,*":{"last_modified":"13406596265295315","setting":{"allowed_tracker_count":1}},"https://match.adsrvr.org:443,*":{"last_modified":"13406596272265767","setting":{"count":2}},"https://match.sharethrough.com:443,*":{"last_modified":"13406596266025424","setting":{"count":1}},"https://media-cdn.ipredictive.com:443,*":{"last_modified":"13406596267799401","setting":{"count":1}},"https://metrics.getrockerbox.com:443,*":{"last_modified":"13406596375855916","setting":{"count":1}},"https://ml314.com:443,*":{"last_modified":"13406596271928583","setting":{"allowed_tracker_count":2}},"https://mug.criteo.com:443,*":{"last_modified":"13406596272810660","setting":{"count":2}},"https://mv.outbrain.com:443,*":{"last_modified":"13406596272294860","setting":{"count":2}},"https://newassets.hcaptcha.com:443,*":{"last_modified":"13406596563834334","setting":{"count":2}},"https://p.alcmpn.com:443,*":{"last_modified":"13406596285778367","setting":{"count":1}},"https://p.rfihub.com:443,*":{"last_modified":"13406596277522296","setting":{"count":1}},"https://pagead2.googlesyndication.com:443,*":{"last_modified":"13406596273125339","setting":{"count":2}},"https://ping.chartbeat.net:443,*":{"last_modified":"13406596271940062","setting":{"allowed_tracker_count":2}},"https://pippio.com:443,*":{"last_modified":"13406596272938724","setting":{"allowed_tracker_count":2}},"https://pix.cdnwidget.com:443,*":{"last_modified":"13406596272856607","setting":{"count":2}},"https://pixel-sync.sitescout.com:443,*":{"last_modified":"13406596277521809","setting":{"count":2}},"https://pixel-us-east.rubiconproject.com:443,*":{"last_modified":"13406596277365646","setting":{"count":2}},"https://pixel.adsafeprotected.com:443,*":{"last_modified":"13406596273228441","setting":{"count":2}},"https://pixel.rubiconproject.com:443,*":{"last_modified":"13406596266023552","setting":{"count":1}},"https://postrelease.com:443,*":{"last_modified":"13406596264837203","setting":{"count":1}},"https://prebid-server.rubiconproject.com:443,*":{"last_modified":"13406596274696323","setting":{"count":1}},"https://prebid.media.net:443,*":{"last_modified":"13406596272281950","setting":{"count":2}},"https://privacyportal-eu.onetrust.com:443,*":{"last_modified":"13406596264070440","setting":{"count":1}},"https://ps.eyeota.net:443,*":{"last_modified":"13406596266023181","setting":{"allowed_tracker_count":1}},"https://pubads.g.doubleclick.net:443,*":{"last_modified":"13406596277253004","setting":{"count":2}},"https://pxl.iqm.com:443,*":{"last_modified":"13406596266025696","setting":{"count":1}},"https://reachms.bfmio.com:443,*":{"last_modified":"13406596274205884","setting":{"count":1}},"https://rp.liadm.com:443,*":{"last_modified":"13406596273229446","setting":{"count":2}},"https://rp4.liadm.com:443,*":{"last_modified":"13406596273241918","setting":{"count":2}},"https://rtb.adentifi.com:443,*":{"last_modified":"13406596266025328","setting":{"count":1}},"https://rtb.mfadsrvr.com:443,*":{"last_modified":"13406596266022264","setting":{"count":1}},"https://rtb.openx.net:443,*":{"last_modified":"13406596274193052","setting":{"count":1}},"https://s.ad.smaato.net:443,*":{"last_modified":"13406596266024422","setting":{"count":1}},"https://s.amazon-adsystem.com:443,*":{"last_modified":"13406596276400833","setting":{"count":1}},"https://s.jsrdn.com:443,*":{"last_modified":"13406596273281289","setting":{"count":1}},"https://s.ntv.io:443,*":{"last_modified":"13406596264338067","setting":{"count":1}},"https://s0.2mdn.net:443,*":{"last_modified":"13406596274026794","setting":{"count":1}},"https://s8t.teads.tv:443,*":{"last_modified":"13406596285269800","setting":{"count":1}},"https://sb.scorecardresearch.com:443,*":{"last_modified":"13406596654535658","setting":{"allowed_tracker_count":9}},"https://secure-us.imrworldwide.com:443,*":{"last_modified":"13406596271888609","setting":{"count":2}},"https://secure.adnxs.com:443,*":{"last_modified":"13406596377365716","setting":{"allowed_tracker_count":1}},"https://secure.flashtalking.com:443,*":{"last_modified":"13406596377189607","setting":{"count":1}},"https://securepubads.g.doubleclick.net:443,*":{"last_modified":"13406596271955264","setting":{"count":2}},"https://servedby.flashtalking.com:443,*":{"last_modified":"13406596375854828","setting":{"count":1}},"https://ssbsync.smartadserver.com:443,*":{"last_modified":"13406596266024564","setting":{"count":1}},"https://ssp.wknd.ai:443,*":{"last_modified":"13406596274969830","setting":{"count":1}},"https://ssum-sec.casalemedia.com:443,*":{"last_modified":"13406596275750227","setting":{"count":2}},"https://static.adsafeprotected.com:443,*":{"last_modified":"13406596273856318","setting":{"count":2}},"https://static.chartbeat.com:443,*":{"last_modified":"13406596271552806","setting":{"allowed_tracker_count":2}},"https://static.criteo.net:443,*":{"last_modified":"13406596274865548","setting":{"count":1}},"https://static.teads.tv:443,*":{"last_modified":"13406596284583428","setting":{"count":1}},"https://staticjs.adsafeprotected.com:443,*":{"last_modified":"13406596273281910","setting":{"count":2}},"https://sync-jp.im-apps.net:443,*":{"last_modified":"13406596266021370","setting":{"count":1}},"https://sync-tm.everesttech.net:443,*":{"last_modified":"13406596285118927","setting":{"count":1}},"https://sync.1rx.io:443,*":{"last_modified":"13406596266025797","setting":{"count":1}},"https://sync.crwdcntrl.net:443,*":{"last_modified":"13406596266023748","setting":{"allowed_tracker_count":1}},"https://sync.go.sonobi.com:443,*":{"last_modified":"13406596277613459","setting":{"count":1}},"https://sync.graph.bluecava.com:443,*":{"last_modified":"13406596285269425","setting":{"allowed_tracker_count":1}},"https://sync.intentiq.com:443,*":{"last_modified":"13406596264890172","setting":{"count":1}},"https://sync.outbrain.com:443,*":{"last_modified":"13406596273375729","setting":{"count":2}},"https://sync.springserve.com:443,*":{"last_modified":"13406596285143591","setting":{"count":1}},"https://sync.srv.stackadapt.com:443,*":{"last_modified":"13406596266026524","setting":{"count":1}},"https://sync.teads.tv:443,*":{"last_modified":"13406596285038589","setting":{"count":2}},"https://syncv4.intentiq.com:443,*":{"last_modified":"13406596265002285","setting":{"count":1}},"https://t.pubmatic.com:443,*":{"last_modified":"13406596264983310","setting":{"count":1}},"https://t.teads.tv:443,*":{"last_modified":"13406596285038663","setting":{"count":1}},"https://t.us1.v6.dyntrk.com:443,*":{"last_modified":"13406596285093345","setting":{"count":1}},"https://t3.teads.tv:443,*":{"last_modified":"13406596285079702","setting":{"count":1}},"https://tag.wknd.ai:443,*":{"last_modified":"13406596265182824","setting":{"count":1}},"https://targeting.unrulymedia.com:443,*":{"last_modified":"13406596274311039","setting":{"count":1}},"https://teads-match.dotomi.com:443,*":{"last_modified":"13406596285119216","setting":{"count":1}},"https://tlx.3lift.com:443,*":{"last_modified":"13406596272282598","setting":{"count":2}},"https://token.rubiconproject.com:443,*":{"last_modified":"13406596275776965","setting":{"count":2}},"https://tpc.googlesyndication.com:443,*":{"last_modified":"13406596273487475","setting":{"count":2}},"https://tps.doubleverify.com:443,*":{"last_modified":"13406596285268636","setting":{"allowed_tracker_count":1}},"https://tpsc-ue1.doubleverify.com:443,*":{"last_modified":"13406596285413849","setting":{"allowed_tracker_count":1}},"https://tr.outbrain.com:443,*":{"last_modified":"13406596265749749","setting":{"count":1}},"https://trace.mediago.io:443,*":{"last_modified":"13406596266025142","setting":{"count":1}},"https://trc.taboola.com:443,*":{"last_modified":"13406596218253430","setting":{"count":1}},"https://u.openx.net:443,*":{"last_modified":"13406596266024177","setting":{"count":1}},"https://ups.analytics.yahoo.com:443,*":{"last_modified":"13406596266024250","setting":{"allowed_tracker_count":1}},"https://us-west-sync.bidswitch.net:443,*":{"last_modified":"13406596267800731","setting":{"count":1}},"https://user-sync.fwmrm.net:443,*":{"last_modified":"13406596285148619","setting":{"count":1}},"https://vat-bid.adsrvr.org:443,*":{"last_modified":"13406596375855676","setting":{"count":1}},"https://vi.ml314.com:443,*":{"last_modified":"13406596271887852","setting":{"allowed_tracker_count":2}},"https://warp.media.net:443,*":{"last_modified":"13406596267789816","setting":{"count":1}},"https://wave.outbrain.com:443,*":{"last_modified":"13406596265749649","setting":{"count":1}},"https://widget-pixels.outbrain.com:443,*":{"last_modified":"13406596272293794","setting":{"count":2}},"https://widgets.outbrain.com:443,*":{"last_modified":"13406596273371351","setting":{"count":2}},"https://widgets.outbrainimg.com:443,*":{"last_modified":"13406596273370253","setting":{"count":2}},"https://www.clarity.ms:443,*":{"last_modified":"13406596215294620","setting":{"allowed_tracker_count":1}},"https://www.datadoghq-browser-agent.com:443,*":{"last_modified":"13406596313592398","setting":{"allowed_tracker_count":1}},"https://www.dianomi.com:443,*":{"last_modified":"13406596272258459","setting":{"count":1}},"https://www.google-analytics.com:443,*":{"last_modified":"13406596313792482","setting":{"allowed_tracker_count":1}},"https://x.bidswitch.net:443,*":{"last_modified":"13406596277520630","setting":{"count":2}}},"tracking_org_exceptions":{},"tracking_org_relationships":{"https://at_t.test:443,*":{"last_modified":"13406596293809456","setting":{"https://www|cnn|com/":true}},"https://microsoft.test:443,*":{"last_modified":"13406597216275236","setting":{"https://ntp|msn|com/":true,"https://www|bing|com/":true,"https://www|microsoft|com/":true}}},"tracking_protection":{},"unused_site_permissions":{},"usb_chooser_data":{},"usb_guard":{},"vr":{},"web_app_installation":{},"webid_api":{},"webid_auto_reauthn":{},"window_placement":{}},"pref_version":1},"created_by_version":"140.0.3485.81","creation_time":"13404976874435639","edge_crash_exit_count":0,"edge_password_is_using_new_login_db_path":false,"edge_password_login_db_path_flip_flop_count":0,"edge_profile_id":"4cf5f931-c51d-4496-83ca-c64a1e5d5793","edge_user_with_non_zero_passwords":false,"exit_type":"Normal","has_seen_signin_fre":true,"is_relative_to_aad":false,"isolated_web_app":{"install":{"pending_initialization_count":0}},"last_engagement_time":"13406597264310699","last_time_obsolete_http_credentials_removed":1762122672.721548,"last_time_password_store_metrics_reported":1762122642.722334,"managed_user_id":"","name":"Profile 2","observed_session_time":{"feedback_rating_in_product_help_observed_session_time_key_140.0.3485.81":20.0,"feedback_rating_in_product_help_observed_session_time_key_141.0.3537.71":511.0,"feedback_rating_in_product_help_observed_session_time_key_142.0.3595.53":51.0},"password_hash_data_list":[],"signin_fre_seen_time":"13404976874537978","were_old_google_logins_removed":true},"reset_prepopulated_engines":false,"safebrowsing":{"extension_telemetry_file_data":{}},"safety_hub":{"unused_site_permissions_revocation":{"migration_completed":true}},"saved_tab_groups":{"did_enable_shared_tab_groups_in_last_session":false,"specifics_to_data_migration":true},"sessions":{"event_log":[{"crashed":false,"time":"13404976874474577","type":0},{"did_schedule_command":true,"first_session_service":true,"tab_count":1,"time":"13404976878610035","type":2,"window_count":1},{"crashed":false,"time":"13406596212723032","type":0},{"did_schedule_command":true,"first_session_service":true,"tab_count":4,"time":"13406596812065309","type":2,"window_count":1},{"crashed":false,"time":"13406597214577222","type":0},{"did_schedule_command":true,"first_session_service":true,"tab_count":3,"time":"13406597266976349","type":2,"window_count":1}],"session_data_status":3},"shopping":{"contextual_features_enabled":true,"dma_telemetry_expiration_time":"13406682612907953","last_pwilo_api_fetch_time":"13406596512907799","mute_auto_show":{},"pcb_supported":true},"signin":{"accounts_metadata_dict":{},"allowed":true,"cookie_clear_on_exit_migration_notice_complete":true},"spellcheck":{"dictionaries":["en-US"],"dictionary":""},"sync":{"apps":true,"autofill":true,"bookmarks":true,"collections":true,"collections_edge_re_evaluated":true,"collections_edge_supported":true,"edge_account_type":0,"edge_wallet":true,"edge_wallet_edge_supported":true,"encryption_bootstrap_token_per_account_migration_done":true,"extensions":true,"extensions_edge_supported":true,"history_edge_supported":true,"keep_everything_synced":false,"passwords":true,"preferences":true,"tabs":true,"tabs_edge_supported":true,"typed_urls":true},"syncing_theme_prefs_migrated_to_non_syncing":true,"tab_groups":[],"toolbar":{"pinned_cast_migration_complete":true,"pinned_chrome_labs_migration_complete":true},"total_passwords_available_for_account":0,"total_passwords_available_for_profile":0,"translate_site_blacklist":[],"translate_site_blocklist_with_time":{},"updateclientdata":{"apps":{"ghbmnnjooekpmoecnnnilnnbdlolhkhi":{"cohort":"1::","cohortname":"","dlrc":6880,"fp":"2.1.96.1","installdate":6880,"max_pv":"1.96.1","pf":"8c85dd89-6002-46dc-8689-d20dc850d7dc","pv":"1.97.1"},"jmjflgjpcpepeafmmgdpfkogkghcpiha":{"cohort":"rrf@0.98","dlrc":6880,"installdate":6880,"pf":"4bfdb0fb-bedc-4c99-ae84-b094e4a1622f"},"odfafepnkmbhccpbejgmiehpchacaeak":{"cohort":"rrf@0.30","dlrc":6880,"installdate":6880,"pf":"9d73b74f-f75b-408d-85e1-81dcf807a7b3"}}},"user_experience_metrics":{"personalization_data_consent_enabled_last_known_value":false},"web_apps":{"daily_metrics":{"https://cursor.com/":{"background_duration_sec":0,"browser_app_background_duration_sec":0,"browser_app_foreground_duration_sec":0,"captures_links":false,"effective_display_mode":3,"foreground_duration_sec":0,"installed":false,"num_sessions":0,"promotable":true,"store_app_background_duration_sec":0,"store_app_foreground_duration_sec":0},"https://github.com/":{"background_duration_sec":0,"browser_app_background_duration_sec":0,"browser_app_foreground_duration_sec":0,"captures_links":false,"effective_display_mode":3,"foreground_duration_sec":0,"installed":false,"num_sessions":0,"promotable":true,"store_app_background_duration_sec":0,"store_app_foreground_duration_sec":0}},"daily_metrics_date":"13406529600000000","did_migrate_default_chrome_apps":["MigrateDefaultChromeAppToWebAppsGSuite","MigrateDefaultChromeAppToWebAppsNonGSuite"],"last_preinstall_synchronize_version":"142","link_handling_info":{"enabled_for_installed_apps":true}},"zerosuggest":{"cachedresults":"[\"\",[\"Hugh Freeze\",\"sydney sweeney silver dress\",\"World Series\",\"David Harbour\",\"Green Bay Packers\",\"nfl games today\",\"snap benefits\",\"new york marathon 2025\"],[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[],{\"google:clientdata\":{\"bcp\":false,\"phi\":0,\"tlw\":false},\"google:suggestdetail\":[{\"t\":\"Hugh Freeze\",\"a\":\"American football coach\",\"i\":\"https://th.bing.com/th/id/OSK.YKQz0NriQK3xlnbFhZVK-ENYA4wUy_KyINVGtKg1res?w=120\\u0026h=120\\u0026c=6\\u0026p=0\\u0026pid=RS\",\"q\":\"qs=MB\\u0026sc=8-0\\u0026asbe=PN\\u0026filters=ufn%3a%22Hugh+Freeze%22+sid%3a%22af4a4fc2-7e4b-3067-2457-063a8b9a359c%22\"},{\"q\":\"qs=PN\\u0026sk=PN1\\u0026sc=8-0\"},{\"t\":\"World Series\",\"a\":\"Major League Baseball series\",\"i\":\"https://th.bing.com/th/id/OSK.4f4a5012107b303ab42d65463027c451?w=120\\u0026h=120\\u0026c=6\\u0026p=0\\u0026pid=RS\",\"q\":\"qs=MB\\u0026sk=PN2\\u0026sc=8-0\\u0026asbe=PN\\u0026filters=ufn%3a%22World+Series%22+sid%3a%2213a1e4cf-f342-4c9b-cbae-de93d568bf50%22\"},{\"t\":\"David Harbour\",\"a\":\"American actor\",\"i\":\"https://th.bing.com/th/id/OSK.Wi-IieMlRYhBU_VtPIhgqKYcRuX3h4IF-ummECUeSXU?w=120\\u0026h=120\\u0026c=6\\u0026p=0\\u0026pid=RS\",\"q\":\"qs=MB\\u0026sk=PN3\\u0026sc=8-0\\u0026asbe=PN\\u0026filters=ufn%3a%22David+Harbour%22+sid%3a%22834b2a44-b380-96b6-1b4f-65fef7fd5fac%22\"},{\"t\":\"Green Bay Packers\",\"a\":\"American football team\",\"i\":\"https://th.bing.com/th/id/OSK.UvZf8hVn8ncaKmXrlz78PUN03Fa9Yvs-uaiVXw6bQRM?w=80\\u0026h=80\\u0026c=6\\u0026p=0\\u0026pid=RS\",\"q\":\"qs=MB\\u0026sk=PN4\\u0026sc=8-0\\u0026asbe=PN\\u0026filters=ufn%3a%22Green+Bay+Packers%22+sid%3a%2211a3d903-0660-c9cb-3cf9-fe2d3deffea1%22\"},{\"q\":\"qs=PN\\u0026sk=PN5\\u0026sc=8-0\"},{\"q\":\"qs=PN\\u0026sk=PN6\\u0026sc=8-0\"},{\"q\":\"qs=PN\\u0026sk=PN7\\u0026sc=8-0\"}],\"google:suggestrelevance\":[99,99,99,99,99,99,99,99],\"google:suggestsubtypes\":[[143],[143],[143],[143],[143],[143],[143],[143]],\"google:suggesttype\":[\"ENTITY\",\"TRENDING_NOW\",\"ENTITY\",\"ENTITY\",\"ENTITY\",\"TRENDING_NOW\",\"TRENDING_NOW\",\"TRENDING_NOW\"],\"google:verbatimrelevance\":799}]","cachedresults_with_url":{"https://www.bing.com/search?q=duckdcukgo+browser&cvid=d336ac0e7c144e918c1581973a6fbfd6&gs_lcrp=EgRlZGdlKgYIABBFGDkyBggAEEUYOTIGCAEQABhAMgYIAhAAGEAyBggDEAAYQDIGCAQQABhAMgYIBRAAGEAyBggGEAAYQDIGCAcQABhAMgYICBAAGEDSAQgzMzM5ajBqNKgCBbACAQ&FORM=ANAB01&PC=U531":"[\"\",[\"Hugh Freeze\",\"sydney sweeney silver dress\",\"World Series\",\"David Harbour\",\"Green Bay Packers\",\"nfl games today\",\"snap benefits\",\"new york marathon 2025\"],[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[],{\"google:clientdata\":{\"bcp\":false,\"phi\":0,\"tlw\":false},\"google:suggestdetail\":[{\"t\":\"Hugh Freeze\",\"a\":\"American football coach\",\"i\":\"https://th.bing.com/th/id/OSK.YKQz0NriQK3xlnbFhZVK-ENYA4wUy_KyINVGtKg1res?w=120\\u0026h=120\\u0026c=6\\u0026p=0\\u0026pid=RS\",\"q\":\"qs=MB\\u0026sc=8-0\\u0026asbe=PN\\u0026filters=ufn%3a%22Hugh+Freeze%22+sid%3a%22af4a4fc2-7e4b-3067-2457-063a8b9a359c%22\"},{\"q\":\"qs=PN\\u0026sk=PN1\\u0026sc=8-0\"},{\"t\":\"World Series\",\"a\":\"Major League Baseball series\",\"i\":\"https://th.bing.com/th/id/OSK.4f4a5012107b303ab42d65463027c451?w=120\\u0026h=120\\u0026c=6\\u0026p=0\\u0026pid=RS\",\"q\":\"qs=MB\\u0026sk=PN2\\u0026sc=8-0\\u0026asbe=PN\\u0026filters=ufn%3a%22World+Series%22+sid%3a%2213a1e4cf-f342-4c9b-cbae-de93d568bf50%22\"},{\"t\":\"David Harbour\",\"a\":\"American actor\",\"i\":\"https://th.bing.com/th/id/OSK.Wi-IieMlRYhBU_VtPIhgqKYcRuX3h4IF-ummECUeSXU?w=120\\u0026h=120\\u0026c=6\\u0026p=0\\u0026pid=RS\",\"q\":\"qs=MB\\u0026sk=PN3\\u0026sc=8-0\\u0026asbe=PN\\u0026filters=ufn%3a%22David+Harbour%22+sid%3a%22834b2a44-b380-96b6-1b4f-65fef7fd5fac%22\"},{\"t\":\"Green Bay Packers\",\"a\":\"American football team\",\"i\":\"https://th.bing.com/th/id/OSK.UvZf8hVn8ncaKmXrlz78PUN03Fa9Yvs-uaiVXw6bQRM?w=80\\u0026h=80\\u0026c=6\\u0026p=0\\u0026pid=RS\",\"q\":\"qs=MB\\u0026sk=PN4\\u0026sc=8-0\\u0026asbe=PN\\u0026filters=ufn%3a%22Green+Bay+Packers%22+sid%3a%2211a3d903-0660-c9cb-3cf9-fe2d3deffea1%22\"},{\"q\":\"qs=PN\\u0026sk=PN5\\u0026sc=8-0\"},{\"q\":\"qs=PN\\u0026sk=PN6\\u0026sc=8-0\"},{\"q\":\"qs=PN\\u0026sk=PN7\\u0026sc=8-0\"}],\"google:suggestrelevance\":[99,99,99,99,99,99,99,99],\"google:suggestsubtypes\":[[143],[143],[143],[143],[143],[143],[143],[143]],\"google:suggesttype\":[\"ENTITY\",\"TRENDING_NOW\",\"ENTITY\",\"ENTITY\",\"ENTITY\",\"TRENDING_NOW\",\"TRENDING_NOW\",\"TRENDING_NOW\"],\"google:verbatimrelevance\":799}]"}}} \ No newline at end of file diff --git a/tests/test_data/edge/v141/Sessions/Session_13404976876976421 b/tests/test_data/edge/v141/Sessions/Session_13404976876976421 new file mode 100644 index 00000000..631fd41e Binary files /dev/null and b/tests/test_data/edge/v141/Sessions/Session_13404976876976421 differ diff --git a/tests/test_data/edge/v141/Sessions/Session_13406596486318013 b/tests/test_data/edge/v141/Sessions/Session_13406596486318013 new file mode 100644 index 00000000..7dcb8821 Binary files /dev/null and b/tests/test_data/edge/v141/Sessions/Session_13406596486318013 differ diff --git a/tests/test_data/edge/v141/Sessions/Session_13406596695873160 b/tests/test_data/edge/v141/Sessions/Session_13406596695873160 new file mode 100644 index 00000000..84efb5ed Binary files /dev/null and b/tests/test_data/edge/v141/Sessions/Session_13406596695873160 differ diff --git a/tests/test_data/edge/v141/Sessions/Tabs_13406596236011012 b/tests/test_data/edge/v141/Sessions/Tabs_13406596236011012 new file mode 100644 index 00000000..deadde86 Binary files /dev/null and b/tests/test_data/edge/v141/Sessions/Tabs_13406596236011012 differ diff --git a/tests/test_data/edge/v141/Shortcuts b/tests/test_data/edge/v141/Shortcuts new file mode 100644 index 00000000..ba6fc676 Binary files /dev/null and b/tests/test_data/edge/v141/Shortcuts differ diff --git a/tests/test_data/edge/v141/raw/tab_url.raw b/tests/test_data/edge/v141/raw/tab_url.raw new file mode 100644 index 00000000..24f01056 Binary files /dev/null and b/tests/test_data/edge/v141/raw/tab_url.raw differ diff --git a/tests/test_data/linux/gnome/gvfs.raw b/tests/test_data/linux/gnome/gvfs.raw new file mode 100644 index 00000000..a164abeb Binary files /dev/null and b/tests/test_data/linux/gnome/gvfs.raw differ diff --git a/tests/test_data/linux/gnome/usage.xml b/tests/test_data/linux/gnome/usage.xml new file mode 100644 index 00000000..02cf477d --- /dev/null +++ b/tests/test_data/linux/gnome/usage.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_data/linux/wtmp/wtmp.db b/tests/test_data/linux/wtmp/wtmp.db new file mode 100644 index 00000000..3ecb592d Binary files /dev/null and b/tests/test_data/linux/wtmp/wtmp.db differ diff --git a/tests/test_data/macos/bom/bom.json b/tests/test_data/macos/bom/bom.json new file mode 100644 index 00000000..2ca1b141 --- /dev/null +++ b/tests/test_data/macos/bom/bom.json @@ -0,0 +1 @@ +{"1":{"bom_file":{"parent":0,"name":"."},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":160,"checksum":"","dev_type":0,"link_name":"","parent":0}},"2":{"bom_file":{"parent":1,"name":"usr"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":1}},"3":{"bom_file":{"parent":2,"name":"local"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":2}},"4":{"bom_file":{"parent":3,"name":"bin"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":128,"checksum":"","dev_type":0,"link_name":"","parent":3}},"5":{"bom_file":{"parent":4,"name":"osqueryi"},"bom_info":{"type":"LINK","architecture":15,"mode":41453,"user":0,"group":0,"modified":1755120727,"size":52,"checksum":"2346157590","dev_type":53,"link_name":"","parent":4}},"6":{"bom_file":{"parent":4,"name":"osqueryctl"},"bom_info":{"type":"LINK","architecture":15,"mode":41453,"user":0,"group":0,"modified":1755120727,"size":58,"checksum":"3228668635","dev_type":59,"link_name":"","parent":4}},"7":{"bom_file":{"parent":1,"name":"private"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":1}},"8":{"bom_file":{"parent":7,"name":"var"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":128,"checksum":"","dev_type":0,"link_name":"","parent":7}},"9":{"bom_file":{"parent":8,"name":"osquery"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":256,"checksum":"","dev_type":0,"link_name":"","parent":8}},"10":{"bom_file":{"parent":9,"name":"io.osquery.agent.plist"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":588,"checksum":"2622418926","dev_type":0,"link_name":"","parent":9}},"11":{"bom_file":{"parent":9,"name":"osquery.example.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":5705,"checksum":"1870839846","dev_type":0,"link_name":"","parent":9}},"12":{"bom_file":{"parent":9,"name":"io.osquery.agent.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":186,"checksum":"2265089030","dev_type":0,"link_name":"","parent":9}},"13":{"bom_file":{"parent":9,"name":"packs"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":384,"checksum":"","dev_type":0,"link_name":"","parent":9}},"14":{"bom_file":{"parent":13,"name":"osx-attacks.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":30328,"checksum":"3207750042","dev_type":0,"link_name":"","parent":13}},"15":{"bom_file":{"parent":13,"name":"incident-response.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":13881,"checksum":"2718241147","dev_type":0,"link_name":"","parent":13}},"16":{"bom_file":{"parent":13,"name":"vuln-management.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":7474,"checksum":"1569318672","dev_type":0,"link_name":"","parent":13}},"17":{"bom_file":{"parent":13,"name":"osquery-monitoring.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1162,"checksum":"2011487972","dev_type":0,"link_name":"","parent":13}},"18":{"bom_file":{"parent":13,"name":"hardware-monitoring.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4968,"checksum":"3626493973","dev_type":0,"link_name":"","parent":13}},"19":{"bom_file":{"parent":13,"name":"windows-attacks.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":5917,"checksum":"51355881","dev_type":0,"link_name":"","parent":13}},"20":{"bom_file":{"parent":13,"name":"unwanted-chrome-extensions.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4513,"checksum":"423122675","dev_type":0,"link_name":"","parent":13}},"21":{"bom_file":{"parent":13,"name":"ossec-rootkit.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":18004,"checksum":"79942740","dev_type":0,"link_name":"","parent":13}},"22":{"bom_file":{"parent":13,"name":"windows-hardening.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":12857,"checksum":"1406929483","dev_type":0,"link_name":"","parent":13}},"23":{"bom_file":{"parent":13,"name":"it-compliance.conf"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":10142,"checksum":"2935140044","dev_type":0,"link_name":"","parent":13}},"24":{"bom_file":{"parent":9,"name":"certs"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":9}},"25":{"bom_file":{"parent":24,"name":"certs.pem"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":224085,"checksum":"3329711587","dev_type":0,"link_name":"","parent":24}},"26":{"bom_file":{"parent":9,"name":"lenses"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":7232,"checksum":"","dev_type":0,"link_name":"","parent":9}},"27":{"bom_file":{"parent":26,"name":"properties.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2359,"checksum":"1642115471","dev_type":0,"link_name":"","parent":26}},"28":{"bom_file":{"parent":26,"name":"authorized_keys.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1883,"checksum":"1281424511","dev_type":0,"link_name":"","parent":26}},"29":{"bom_file":{"parent":26,"name":"ethers.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":663,"checksum":"2695632171","dev_type":0,"link_name":"","parent":26}},"30":{"bom_file":{"parent":26,"name":"monit.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2182,"checksum":"2896981516","dev_type":0,"link_name":"","parent":26}},"31":{"bom_file":{"parent":26,"name":"nagiosobjects.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1604,"checksum":"174445648","dev_type":0,"link_name":"","parent":26}},"32":{"bom_file":{"parent":26,"name":"gtkbookmarks.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":855,"checksum":"2148726852","dev_type":0,"link_name":"","parent":26}},"33":{"bom_file":{"parent":26,"name":"jettyrealm.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1552,"checksum":"989993499","dev_type":0,"link_name":"","parent":26}},"34":{"bom_file":{"parent":26,"name":"services.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2887,"checksum":"3415666051","dev_type":0,"link_name":"","parent":26}},"35":{"bom_file":{"parent":26,"name":"squid.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":16330,"checksum":"3805924957","dev_type":0,"link_name":"","parent":26}},"36":{"bom_file":{"parent":26,"name":"bootconf.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3736,"checksum":"3584607822","dev_type":0,"link_name":"","parent":26}},"37":{"bom_file":{"parent":26,"name":"dns_zone.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2963,"checksum":"1336277743","dev_type":0,"link_name":"","parent":26}},"38":{"bom_file":{"parent":26,"name":"xorg.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":10679,"checksum":"2071800226","dev_type":0,"link_name":"","parent":26}},"39":{"bom_file":{"parent":26,"name":"koji.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":898,"checksum":"1795797996","dev_type":0,"link_name":"","parent":26}},"40":{"bom_file":{"parent":26,"name":"dput.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2213,"checksum":"4107472739","dev_type":0,"link_name":"","parent":26}},"41":{"bom_file":{"parent":26,"name":"qpid.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":670,"checksum":"646798593","dev_type":0,"link_name":"","parent":26}},"42":{"bom_file":{"parent":26,"name":"puppetfile.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2327,"checksum":"2302570814","dev_type":0,"link_name":"","parent":26}},"43":{"bom_file":{"parent":26,"name":"puppet.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1558,"checksum":"3876013391","dev_type":0,"link_name":"","parent":26}},"44":{"bom_file":{"parent":26,"name":"shellvars_list.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1779,"checksum":"1207773548","dev_type":0,"link_name":"","parent":26}},"45":{"bom_file":{"parent":26,"name":"webmin.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1257,"checksum":"925966126","dev_type":0,"link_name":"","parent":26}},"46":{"bom_file":{"parent":26,"name":"rmt.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":788,"checksum":"2712317911","dev_type":0,"link_name":"","parent":26}},"47":{"bom_file":{"parent":26,"name":"openshift_quickstarts.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1044,"checksum":"2002058110","dev_type":0,"link_name":"","parent":26}},"48":{"bom_file":{"parent":26,"name":"pbuilder.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":638,"checksum":"3709739657","dev_type":0,"link_name":"","parent":26}},"49":{"bom_file":{"parent":26,"name":"xml.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":6481,"checksum":"2759057286","dev_type":0,"link_name":"","parent":26}},"50":{"bom_file":{"parent":26,"name":"avahi.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1417,"checksum":"963656422","dev_type":0,"link_name":"","parent":26}},"51":{"bom_file":{"parent":26,"name":"radicale.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1518,"checksum":"3249404897","dev_type":0,"link_name":"","parent":26}},"52":{"bom_file":{"parent":26,"name":"cyrus_imapd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1546,"checksum":"1083376824","dev_type":0,"link_name":"","parent":26}},"53":{"bom_file":{"parent":26,"name":"channels.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3929,"checksum":"2184630058","dev_type":0,"link_name":"","parent":26}},"54":{"bom_file":{"parent":26,"name":"modules_conf.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1068,"checksum":"3030251308","dev_type":0,"link_name":"","parent":26}},"55":{"bom_file":{"parent":26,"name":"aptpreferences.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1831,"checksum":"255592221","dev_type":0,"link_name":"","parent":26}},"56":{"bom_file":{"parent":26,"name":"login_defs.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":615,"checksum":"3178474459","dev_type":0,"link_name":"","parent":26}},"57":{"bom_file":{"parent":26,"name":"rancid.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":927,"checksum":"1784392569","dev_type":0,"link_name":"","parent":26}},"58":{"bom_file":{"parent":26,"name":"fuse.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":871,"checksum":"2033257045","dev_type":0,"link_name":"","parent":26}},"59":{"bom_file":{"parent":26,"name":"puppetfileserver.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3190,"checksum":"1529468410","dev_type":0,"link_name":"","parent":26}},"60":{"bom_file":{"parent":26,"name":"anaconda.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":775,"checksum":"2264275584","dev_type":0,"link_name":"","parent":26}},"61":{"bom_file":{"parent":26,"name":"postfix_access.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":771,"checksum":"1595195929","dev_type":0,"link_name":"","parent":26}},"62":{"bom_file":{"parent":26,"name":"sysconfig_route.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2615,"checksum":"310554869","dev_type":0,"link_name":"","parent":26}},"63":{"bom_file":{"parent":26,"name":"cups.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":459,"checksum":"3965231476","dev_type":0,"link_name":"","parent":26}},"64":{"bom_file":{"parent":26,"name":"activemq_xml.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":864,"checksum":"2490549804","dev_type":0,"link_name":"","parent":26}},"65":{"bom_file":{"parent":26,"name":"httpd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":7527,"checksum":"2847998815","dev_type":0,"link_name":"","parent":26}},"66":{"bom_file":{"parent":26,"name":"networkmanager.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2047,"checksum":"611533256","dev_type":0,"link_name":"","parent":26}},"67":{"bom_file":{"parent":26,"name":"devfsrules.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":619,"checksum":"3432430990","dev_type":0,"link_name":"","parent":26}},"68":{"bom_file":{"parent":26,"name":"rsyslog.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3245,"checksum":"1744659441","dev_type":0,"link_name":"","parent":26}},"69":{"bom_file":{"parent":26,"name":"mdadm_conf.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":10289,"checksum":"3730282595","dev_type":0,"link_name":"","parent":26}},"70":{"bom_file":{"parent":26,"name":"netmasks.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1732,"checksum":"2468720517","dev_type":0,"link_name":"","parent":26}},"71":{"bom_file":{"parent":26,"name":"wine.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1966,"checksum":"3965526393","dev_type":0,"link_name":"","parent":26}},"72":{"bom_file":{"parent":26,"name":"mailscanner.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1699,"checksum":"136726221","dev_type":0,"link_name":"","parent":26}},"73":{"bom_file":{"parent":26,"name":"gshadow.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2240,"checksum":"588721901","dev_type":0,"link_name":"","parent":26}},"74":{"bom_file":{"parent":26,"name":"nslcd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":10111,"checksum":"1299397551","dev_type":0,"link_name":"","parent":26}},"75":{"bom_file":{"parent":26,"name":"nsswitch.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2386,"checksum":"207567418","dev_type":0,"link_name":"","parent":26}},"76":{"bom_file":{"parent":26,"name":"openvpn.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":22817,"checksum":"3314571891","dev_type":0,"link_name":"","parent":26}},"77":{"bom_file":{"parent":26,"name":"masterpasswd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4468,"checksum":"1890241494","dev_type":0,"link_name":"","parent":26}},"78":{"bom_file":{"parent":26,"name":"oz.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1384,"checksum":"2344499983","dev_type":0,"link_name":"","parent":26}},"79":{"bom_file":{"parent":26,"name":"postfix_sasl_smtpd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":697,"checksum":"1412776802","dev_type":0,"link_name":"","parent":26}},"80":{"bom_file":{"parent":26,"name":"ceph.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":719,"checksum":"2162537918","dev_type":0,"link_name":"","parent":26}},"81":{"bom_file":{"parent":26,"name":"aptcacherngsecurity.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":726,"checksum":"1218730469","dev_type":0,"link_name":"","parent":26}},"82":{"bom_file":{"parent":26,"name":"dhcpd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":21379,"checksum":"2704695893","dev_type":0,"link_name":"","parent":26}},"83":{"bom_file":{"parent":26,"name":"ldif.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":7833,"checksum":"189331074","dev_type":0,"link_name":"","parent":26}},"84":{"bom_file":{"parent":26,"name":"lvm.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2079,"checksum":"2239916838","dev_type":0,"link_name":"","parent":26}},"85":{"bom_file":{"parent":26,"name":"backuppchosts.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1014,"checksum":"545952914","dev_type":0,"link_name":"","parent":26}},"86":{"bom_file":{"parent":26,"name":"access.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3669,"checksum":"932514044","dev_type":0,"link_name":"","parent":26}},"87":{"bom_file":{"parent":26,"name":"ntp.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":5419,"checksum":"2019821511","dev_type":0,"link_name":"","parent":26}},"88":{"bom_file":{"parent":26,"name":"semanage.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":859,"checksum":"516018560","dev_type":0,"link_name":"","parent":26}},"89":{"bom_file":{"parent":26,"name":"iscsid.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":684,"checksum":"1612020472","dev_type":0,"link_name":"","parent":26}},"90":{"bom_file":{"parent":26,"name":"erlang.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4432,"checksum":"4213975077","dev_type":0,"link_name":"","parent":26}},"91":{"bom_file":{"parent":26,"name":"subversion.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2817,"checksum":"3789091304","dev_type":0,"link_name":"","parent":26}},"92":{"bom_file":{"parent":26,"name":"dpkg.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2851,"checksum":"3098260780","dev_type":0,"link_name":"","parent":26}},"93":{"bom_file":{"parent":26,"name":"sshd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4105,"checksum":"1025190335","dev_type":0,"link_name":"","parent":26}},"94":{"bom_file":{"parent":26,"name":"slapd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":5327,"checksum":"1882509467","dev_type":0,"link_name":"","parent":26}},"95":{"bom_file":{"parent":26,"name":"sudoers.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":20512,"checksum":"1622385589","dev_type":0,"link_name":"","parent":26}},"96":{"bom_file":{"parent":26,"name":"sysctl.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":923,"checksum":"910182811","dev_type":0,"link_name":"","parent":26}},"97":{"bom_file":{"parent":26,"name":"yum.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2240,"checksum":"230340010","dev_type":0,"link_name":"","parent":26}},"98":{"bom_file":{"parent":26,"name":"desktop.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1422,"checksum":"1077957316","dev_type":0,"link_name":"","parent":26}},"99":{"bom_file":{"parent":26,"name":"postfix_master.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1941,"checksum":"2561787437","dev_type":0,"link_name":"","parent":26}},"100":{"bom_file":{"parent":26,"name":"ldso.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1085,"checksum":"2728523807","dev_type":0,"link_name":"","parent":26}},"101":{"bom_file":{"parent":26,"name":"group.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1703,"checksum":"1307126422","dev_type":0,"link_name":"","parent":26}},"102":{"bom_file":{"parent":26,"name":"samba.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1755,"checksum":"614833751","dev_type":0,"link_name":"","parent":26}},"103":{"bom_file":{"parent":26,"name":"openshift_http.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1052,"checksum":"2231248691","dev_type":0,"link_name":"","parent":26}},"104":{"bom_file":{"parent":26,"name":"pg_hba.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3043,"checksum":"2559292199","dev_type":0,"link_name":"","parent":26}},"105":{"bom_file":{"parent":26,"name":"krb5.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":6310,"checksum":"2118863872","dev_type":0,"link_name":"","parent":26}},"106":{"bom_file":{"parent":26,"name":"resolv.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3963,"checksum":"218465137","dev_type":0,"link_name":"","parent":26}},"107":{"bom_file":{"parent":26,"name":"aptconf.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3989,"checksum":"3887667317","dev_type":0,"link_name":"","parent":26}},"108":{"bom_file":{"parent":26,"name":"shellvars.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":12259,"checksum":"4023083369","dev_type":0,"link_name":"","parent":26}},"109":{"bom_file":{"parent":26,"name":"json.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2198,"checksum":"1257974587","dev_type":0,"link_name":"","parent":26}},"110":{"bom_file":{"parent":26,"name":"exports.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2424,"checksum":"2367514518","dev_type":0,"link_name":"","parent":26}},"111":{"bom_file":{"parent":26,"name":"getcap.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1610,"checksum":"500963563","dev_type":0,"link_name":"","parent":26}},"112":{"bom_file":{"parent":26,"name":"openshift_config.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2524,"checksum":"3866471773","dev_type":0,"link_name":"","parent":26}},"113":{"bom_file":{"parent":26,"name":"known_hosts.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1979,"checksum":"4049065777","dev_type":0,"link_name":"","parent":26}},"114":{"bom_file":{"parent":26,"name":"inetd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":6365,"checksum":"3609820237","dev_type":0,"link_name":"","parent":26}},"115":{"bom_file":{"parent":26,"name":"hosts.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":485,"checksum":"2860719728","dev_type":0,"link_name":"","parent":26}},"116":{"bom_file":{"parent":26,"name":"hostname.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":435,"checksum":"3658639242","dev_type":0,"link_name":"","parent":26}},"117":{"bom_file":{"parent":26,"name":"mongodbserver.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1201,"checksum":"2705347730","dev_type":0,"link_name":"","parent":26}},"118":{"bom_file":{"parent":26,"name":"keepalived.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":10958,"checksum":"2552412611","dev_type":0,"link_name":"","parent":26}},"119":{"bom_file":{"parent":26,"name":"modprobe.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3420,"checksum":"547347523","dev_type":0,"link_name":"","parent":26}},"120":{"bom_file":{"parent":26,"name":"postfix_transport.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1513,"checksum":"1713386411","dev_type":0,"link_name":"","parent":26}},"121":{"bom_file":{"parent":26,"name":"bbhosts.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4342,"checksum":"2156814975","dev_type":0,"link_name":"","parent":26}},"122":{"bom_file":{"parent":26,"name":"tmpfiles.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3107,"checksum":"837142311","dev_type":0,"link_name":"","parent":26}},"123":{"bom_file":{"parent":26,"name":"carbon.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1574,"checksum":"2950198966","dev_type":0,"link_name":"","parent":26}},"124":{"bom_file":{"parent":26,"name":"hosts_access.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4426,"checksum":"2556498746","dev_type":0,"link_name":"","parent":26}},"125":{"bom_file":{"parent":26,"name":"build.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":17045,"checksum":"2176322981","dev_type":0,"link_name":"","parent":26}},"126":{"bom_file":{"parent":26,"name":"mailscanner_rules.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2911,"checksum":"84551013","dev_type":0,"link_name":"","parent":26}},"127":{"bom_file":{"parent":26,"name":"crypttab.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3087,"checksum":"1997312344","dev_type":0,"link_name":"","parent":26}},"128":{"bom_file":{"parent":26,"name":"dovecot.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4073,"checksum":"2418671006","dev_type":0,"link_name":"","parent":26}},"129":{"bom_file":{"parent":26,"name":"dnsmasq.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2209,"checksum":"3071841289","dev_type":0,"link_name":"","parent":26}},"130":{"bom_file":{"parent":26,"name":"postfix_main.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1555,"checksum":"4131903598","dev_type":0,"link_name":"","parent":26}},"131":{"bom_file":{"parent":26,"name":"util.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4963,"checksum":"840978178","dev_type":0,"link_name":"","parent":26}},"132":{"bom_file":{"parent":26,"name":"toml.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4161,"checksum":"570884520","dev_type":0,"link_name":"","parent":26}},"133":{"bom_file":{"parent":26,"name":"phpvars.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3947,"checksum":"2994199034","dev_type":0,"link_name":"","parent":26}},"134":{"bom_file":{"parent":26,"name":"passwd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3609,"checksum":"930627844","dev_type":0,"link_name":"","parent":26}},"135":{"bom_file":{"parent":26,"name":"anacron.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2545,"checksum":"4062363856","dev_type":0,"link_name":"","parent":26}},"136":{"bom_file":{"parent":26,"name":"trapperkeeper.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4110,"checksum":"3320119395","dev_type":0,"link_name":"","parent":26}},"137":{"bom_file":{"parent":26,"name":"mcollective.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1112,"checksum":"3223213726","dev_type":0,"link_name":"","parent":26}},"138":{"bom_file":{"parent":26,"name":"jmxpassword.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1375,"checksum":"3585934591","dev_type":0,"link_name":"","parent":26}},"139":{"bom_file":{"parent":26,"name":"smbusers.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":781,"checksum":"3989942230","dev_type":0,"link_name":"","parent":26}},"140":{"bom_file":{"parent":26,"name":"sssd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":861,"checksum":"3981449584","dev_type":0,"link_name":"","parent":26}},"141":{"bom_file":{"parent":26,"name":"logrotate.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4326,"checksum":"1138159586","dev_type":0,"link_name":"","parent":26}},"142":{"bom_file":{"parent":26,"name":"mke2fs.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4783,"checksum":"2035818192","dev_type":0,"link_name":"","parent":26}},"143":{"bom_file":{"parent":26,"name":"opendkim.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3149,"checksum":"2689461213","dev_type":0,"link_name":"","parent":26}},"144":{"bom_file":{"parent":26,"name":"inifile.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":15859,"checksum":"1844021622","dev_type":0,"link_name":"","parent":26}},"145":{"bom_file":{"parent":26,"name":"stunnel.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2260,"checksum":"1734671192","dev_type":0,"link_name":"","parent":26}},"146":{"bom_file":{"parent":26,"name":"collectd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":869,"checksum":"1836865612","dev_type":0,"link_name":"","parent":26}},"147":{"bom_file":{"parent":26,"name":"shadow.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2404,"checksum":"1536422345","dev_type":0,"link_name":"","parent":26}},"148":{"bom_file":{"parent":26,"name":"host_conf.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1941,"checksum":"1087329232","dev_type":0,"link_name":"","parent":26}},"149":{"bom_file":{"parent":26,"name":"star.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":941,"checksum":"3811059767","dev_type":0,"link_name":"","parent":26}},"150":{"bom_file":{"parent":26,"name":"aptsources.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2023,"checksum":"3914409939","dev_type":0,"link_name":"","parent":26}},"151":{"bom_file":{"parent":26,"name":"interfaces.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4733,"checksum":"938915306","dev_type":0,"link_name":"","parent":26}},"152":{"bom_file":{"parent":26,"name":"debctrl.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3701,"checksum":"4198510601","dev_type":0,"link_name":"","parent":26}},"153":{"bom_file":{"parent":26,"name":"php.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2393,"checksum":"311056319","dev_type":0,"link_name":"","parent":26}},"154":{"bom_file":{"parent":26,"name":"htpasswd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1043,"checksum":"257222163","dev_type":0,"link_name":"","parent":26}},"155":{"bom_file":{"parent":26,"name":"thttpd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1345,"checksum":"998322958","dev_type":0,"link_name":"","parent":26}},"156":{"bom_file":{"parent":26,"name":"lokkit.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2216,"checksum":"1814587920","dev_type":0,"link_name":"","parent":26}},"157":{"bom_file":{"parent":26,"name":"simplelines.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1155,"checksum":"2043472422","dev_type":0,"link_name":"","parent":26}},"158":{"bom_file":{"parent":26,"name":"up2date.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2264,"checksum":"136580252","dev_type":0,"link_name":"","parent":26}},"159":{"bom_file":{"parent":26,"name":"jmxaccess.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1386,"checksum":"1034012591","dev_type":0,"link_name":"","parent":26}},"160":{"bom_file":{"parent":26,"name":"rtadvd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":854,"checksum":"4241172384","dev_type":0,"link_name":"","parent":26}},"161":{"bom_file":{"parent":26,"name":"systemd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":6019,"checksum":"989707583","dev_type":0,"link_name":"","parent":26}},"162":{"bom_file":{"parent":26,"name":"gdm.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1841,"checksum":"2037780621","dev_type":0,"link_name":"","parent":26}},"163":{"bom_file":{"parent":26,"name":"activemq_conf.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1509,"checksum":"1833261056","dev_type":0,"link_name":"","parent":26}},"164":{"bom_file":{"parent":26,"name":"dhclient.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":6850,"checksum":"3822642844","dev_type":0,"link_name":"","parent":26}},"165":{"bom_file":{"parent":26,"name":"xinetd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4120,"checksum":"3211082373","dev_type":0,"link_name":"","parent":26}},"166":{"bom_file":{"parent":26,"name":"schroot.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1832,"checksum":"4018206288","dev_type":0,"link_name":"","parent":26}},"167":{"bom_file":{"parent":26,"name":"grub.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":11309,"checksum":"2341427959","dev_type":0,"link_name":"","parent":26}},"168":{"bom_file":{"parent":26,"name":"rabbitmq.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4804,"checksum":"3097396655","dev_type":0,"link_name":"","parent":26}},"169":{"bom_file":{"parent":26,"name":"apt_update_manager.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1135,"checksum":"2560853430","dev_type":0,"link_name":"","parent":26}},"170":{"bom_file":{"parent":26,"name":"grubenv.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":508,"checksum":"2884835965","dev_type":0,"link_name":"","parent":26}},"171":{"bom_file":{"parent":26,"name":"odbc.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1450,"checksum":"2469762774","dev_type":0,"link_name":"","parent":26}},"172":{"bom_file":{"parent":26,"name":"darkice.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":773,"checksum":"3634873254","dev_type":0,"link_name":"","parent":26}},"173":{"bom_file":{"parent":26,"name":"pythonpaste.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2035,"checksum":"584798917","dev_type":0,"link_name":"","parent":26}},"174":{"bom_file":{"parent":26,"name":"csv.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1212,"checksum":"880177392","dev_type":0,"link_name":"","parent":26}},"175":{"bom_file":{"parent":26,"name":"afs_cellalias.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1602,"checksum":"3440520219","dev_type":0,"link_name":"","parent":26}},"176":{"bom_file":{"parent":26,"name":"automounter.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4148,"checksum":"859632673","dev_type":0,"link_name":"","parent":26}},"177":{"bom_file":{"parent":26,"name":"fai_diskconfig.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":9502,"checksum":"1327844007","dev_type":0,"link_name":"","parent":26}},"178":{"bom_file":{"parent":26,"name":"puppet_auth.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2001,"checksum":"2231782672","dev_type":0,"link_name":"","parent":26}},"179":{"bom_file":{"parent":26,"name":"pagekite.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2663,"checksum":"3860768345","dev_type":0,"link_name":"","parent":26}},"180":{"bom_file":{"parent":26,"name":"approx.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1286,"checksum":"3569186213","dev_type":0,"link_name":"","parent":26}},"181":{"bom_file":{"parent":26,"name":"cachefilesd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2051,"checksum":"1468984803","dev_type":0,"link_name":"","parent":26}},"182":{"bom_file":{"parent":26,"name":"xendconfsxp.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1097,"checksum":"3233629277","dev_type":0,"link_name":"","parent":26}},"183":{"bom_file":{"parent":26,"name":"postfix_passwordmap.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1312,"checksum":"304974209","dev_type":0,"link_name":"","parent":26}},"184":{"bom_file":{"parent":26,"name":"pgbouncer.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1462,"checksum":"2308812942","dev_type":0,"link_name":"","parent":26}},"185":{"bom_file":{"parent":26,"name":"solaris_system.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3228,"checksum":"4054693522","dev_type":0,"link_name":"","parent":26}},"186":{"bom_file":{"parent":26,"name":"soma.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1167,"checksum":"3543794920","dev_type":0,"link_name":"","parent":26}},"187":{"bom_file":{"parent":26,"name":"fstab.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1257,"checksum":"3181600951","dev_type":0,"link_name":"","parent":26}},"188":{"bom_file":{"parent":26,"name":"cgrules.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2432,"checksum":"362902401","dev_type":0,"link_name":"","parent":26}},"189":{"bom_file":{"parent":26,"name":"sip_conf.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1651,"checksum":"1226111112","dev_type":0,"link_name":"","parent":26}},"190":{"bom_file":{"parent":26,"name":"xymon_alerting.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":6259,"checksum":"2561568","dev_type":0,"link_name":"","parent":26}},"191":{"bom_file":{"parent":26,"name":"termcap.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1050,"checksum":"2930749360","dev_type":0,"link_name":"","parent":26}},"192":{"bom_file":{"parent":26,"name":"device_map.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":620,"checksum":"2329725828","dev_type":0,"link_name":"","parent":26}},"193":{"bom_file":{"parent":26,"name":"multipath.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4311,"checksum":"2952971012","dev_type":0,"link_name":"","parent":26}},"194":{"bom_file":{"parent":26,"name":"sysconfig.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2550,"checksum":"118685690","dev_type":0,"link_name":"","parent":26}},"195":{"bom_file":{"parent":26,"name":"securetty.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":450,"checksum":"3056911106","dev_type":0,"link_name":"","parent":26}},"196":{"bom_file":{"parent":26,"name":"cgconfig.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3447,"checksum":"2685931845","dev_type":0,"link_name":"","parent":26}},"197":{"bom_file":{"parent":26,"name":"postgresql.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2151,"checksum":"1964490837","dev_type":0,"link_name":"","parent":26}},"198":{"bom_file":{"parent":26,"name":"kdump.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2977,"checksum":"4184876044","dev_type":0,"link_name":"","parent":26}},"199":{"bom_file":{"parent":26,"name":"pamconf.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1256,"checksum":"3644499786","dev_type":0,"link_name":"","parent":26}},"200":{"bom_file":{"parent":26,"name":"rhsm.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1130,"checksum":"1976487539","dev_type":0,"link_name":"","parent":26}},"201":{"bom_file":{"parent":26,"name":"cron_user.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1290,"checksum":"3736994138","dev_type":0,"link_name":"","parent":26}},"202":{"bom_file":{"parent":26,"name":"lightdm.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1793,"checksum":"1726020549","dev_type":0,"link_name":"","parent":26}},"203":{"bom_file":{"parent":26,"name":"vfstab.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1756,"checksum":"2134104013","dev_type":0,"link_name":"","parent":26}},"204":{"bom_file":{"parent":26,"name":"spacevars.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1449,"checksum":"3574279500","dev_type":0,"link_name":"","parent":26}},"205":{"bom_file":{"parent":26,"name":"nginx.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3740,"checksum":"4067391478","dev_type":0,"link_name":"","parent":26}},"206":{"bom_file":{"parent":26,"name":"cron.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4143,"checksum":"1036828229","dev_type":0,"link_name":"","parent":26}},"207":{"bom_file":{"parent":26,"name":"nrpe.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1789,"checksum":"13077199","dev_type":0,"link_name":"","parent":26}},"208":{"bom_file":{"parent":26,"name":"xymon.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2314,"checksum":"3194273730","dev_type":0,"link_name":"","parent":26}},"209":{"bom_file":{"parent":26,"name":"fonts.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":819,"checksum":"1814190277","dev_type":0,"link_name":"","parent":26}},"210":{"bom_file":{"parent":26,"name":"inputrc.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1662,"checksum":"2266203717","dev_type":0,"link_name":"","parent":26}},"211":{"bom_file":{"parent":26,"name":"rx.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4158,"checksum":"2133839065","dev_type":0,"link_name":"","parent":26}},"212":{"bom_file":{"parent":26,"name":"limits.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2065,"checksum":"3196340440","dev_type":0,"link_name":"","parent":26}},"213":{"bom_file":{"parent":26,"name":"quote.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":6871,"checksum":"2355474674","dev_type":0,"link_name":"","parent":26}},"214":{"bom_file":{"parent":26,"name":"cpanel.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":824,"checksum":"1775075686","dev_type":0,"link_name":"","parent":26}},"215":{"bom_file":{"parent":26,"name":"mysql.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1994,"checksum":"2196549960","dev_type":0,"link_name":"","parent":26}},"216":{"bom_file":{"parent":26,"name":"protocols.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1080,"checksum":"3050419290","dev_type":0,"link_name":"","parent":26}},"217":{"bom_file":{"parent":26,"name":"aliases.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2231,"checksum":"3994378454","dev_type":0,"link_name":"","parent":26}},"218":{"bom_file":{"parent":26,"name":"pylonspaste.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2359,"checksum":"2572396458","dev_type":0,"link_name":"","parent":26}},"219":{"bom_file":{"parent":26,"name":"strongswan.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1671,"checksum":"2386419668","dev_type":0,"link_name":"","parent":26}},"220":{"bom_file":{"parent":26,"name":"postfix_virtual.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1347,"checksum":"3325377030","dev_type":0,"link_name":"","parent":26}},"221":{"bom_file":{"parent":26,"name":"ssh.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4001,"checksum":"446922193","dev_type":0,"link_name":"","parent":26}},"222":{"bom_file":{"parent":26,"name":"updatedb.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1159,"checksum":"2919622962","dev_type":0,"link_name":"","parent":26}},"223":{"bom_file":{"parent":26,"name":"rsyncd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2017,"checksum":"2579001444","dev_type":0,"link_name":"","parent":26}},"224":{"bom_file":{"parent":26,"name":"networks.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1116,"checksum":"2328314469","dev_type":0,"link_name":"","parent":26}},"225":{"bom_file":{"parent":26,"name":"syslog.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":7501,"checksum":"3727931487","dev_type":0,"link_name":"","parent":26}},"226":{"bom_file":{"parent":26,"name":"clamav.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1570,"checksum":"1875129285","dev_type":0,"link_name":"","parent":26}},"227":{"bom_file":{"parent":26,"name":"cobblermodules.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":398,"checksum":"1269121974","dev_type":0,"link_name":"","parent":26}},"228":{"bom_file":{"parent":26,"name":"tuned.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":387,"checksum":"1935210175","dev_type":0,"link_name":"","parent":26}},"229":{"bom_file":{"parent":26,"name":"modules.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":741,"checksum":"2628909754","dev_type":0,"link_name":"","parent":26}},"230":{"bom_file":{"parent":26,"name":"redis.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":5084,"checksum":"2680565063","dev_type":0,"link_name":"","parent":26}},"231":{"bom_file":{"parent":26,"name":"iproute2.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":323,"checksum":"1767943546","dev_type":0,"link_name":"","parent":26}},"232":{"bom_file":{"parent":26,"name":"jaas.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1612,"checksum":"4253238892","dev_type":0,"link_name":"","parent":26}},"233":{"bom_file":{"parent":26,"name":"splunk.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1677,"checksum":"3573808648","dev_type":0,"link_name":"","parent":26}},"234":{"bom_file":{"parent":26,"name":"iptables.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2703,"checksum":"510192493","dev_type":0,"link_name":"","parent":26}},"235":{"bom_file":{"parent":26,"name":"ntpd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":4861,"checksum":"4019241521","dev_type":0,"link_name":"","parent":26}},"236":{"bom_file":{"parent":26,"name":"vsftpd.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2785,"checksum":"539900797","dev_type":0,"link_name":"","parent":26}},"237":{"bom_file":{"parent":26,"name":"reprepro_uploaders.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":5604,"checksum":"909765065","dev_type":0,"link_name":"","parent":26}},"238":{"bom_file":{"parent":26,"name":"shells.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":745,"checksum":"2605399048","dev_type":0,"link_name":"","parent":26}},"239":{"bom_file":{"parent":26,"name":"logwatch.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1473,"checksum":"960191337","dev_type":0,"link_name":"","parent":26}},"240":{"bom_file":{"parent":26,"name":"simplevars.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1377,"checksum":"1916761156","dev_type":0,"link_name":"","parent":26}},"241":{"bom_file":{"parent":26,"name":"sep.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1306,"checksum":"506640985","dev_type":0,"link_name":"","parent":26}},"242":{"bom_file":{"parent":26,"name":"yaml.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1581,"checksum":"4036263138","dev_type":0,"link_name":"","parent":26}},"243":{"bom_file":{"parent":26,"name":"inittab.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":780,"checksum":"1602157802","dev_type":0,"link_name":"","parent":26}},"244":{"bom_file":{"parent":26,"name":"automaster.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":3391,"checksum":"2124689391","dev_type":0,"link_name":"","parent":26}},"245":{"bom_file":{"parent":26,"name":"chrony.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":13176,"checksum":"765814262","dev_type":0,"link_name":"","parent":26}},"246":{"bom_file":{"parent":26,"name":"memcached.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":1272,"checksum":"2691451291","dev_type":0,"link_name":"","parent":26}},"247":{"bom_file":{"parent":26,"name":"pam.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2637,"checksum":"2659576135","dev_type":0,"link_name":"","parent":26}},"248":{"bom_file":{"parent":26,"name":"cobblersettings.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2295,"checksum":"832274089","dev_type":0,"link_name":"","parent":26}},"249":{"bom_file":{"parent":26,"name":"vmware_config.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":702,"checksum":"3646055705","dev_type":0,"link_name":"","parent":26}},"250":{"bom_file":{"parent":26,"name":"nagioscfg.aug"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":2138,"checksum":"1101283282","dev_type":0,"link_name":"","parent":26}},"251":{"bom_file":{"parent":8,"name":"log"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":8}},"252":{"bom_file":{"parent":251,"name":"osquery"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":64,"checksum":"","dev_type":0,"link_name":"","parent":251}},"253":{"bom_file":{"parent":1,"name":"opt"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":1}},"254":{"bom_file":{"parent":253,"name":"osquery"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":253}},"255":{"bom_file":{"parent":254,"name":"lib"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":254}},"256":{"bom_file":{"parent":255,"name":"osquery.app"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":255}},"257":{"bom_file":{"parent":256,"name":"Contents"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":256,"checksum":"","dev_type":0,"link_name":"","parent":256}},"258":{"bom_file":{"parent":257,"name":"_CodeSignature"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":257}},"259":{"bom_file":{"parent":258,"name":"CodeResources"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755120710,"size":2589,"checksum":"3550180736","dev_type":0,"link_name":"","parent":258}},"260":{"bom_file":{"parent":257,"name":"MacOS"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":257}},"261":{"bom_file":{"parent":260,"name":"osqueryd"},"bom_info":{"type":"FILE","architecture":8207,"mode":33261,"user":0,"group":0,"modified":1755120711,"size":108937904,"checksum":"2610111542","dev_type":16777216,"link_name":"","parent":260}},"262":{"bom_file":{"parent":257,"name":"Resources"},"bom_info":{"type":"DIRECTORY","architecture":15,"mode":16877,"user":0,"group":0,"modified":1755120727,"size":96,"checksum":"","dev_type":0,"link_name":"","parent":257}},"263":{"bom_file":{"parent":262,"name":"osqueryctl"},"bom_info":{"type":"FILE","architecture":15,"mode":33261,"user":0,"group":0,"modified":1755119050,"size":3671,"checksum":"1000299713","dev_type":0,"link_name":"","parent":262}},"264":{"bom_file":{"parent":257,"name":"embedded.provisionprofile"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":7880,"checksum":"3065739627","dev_type":0,"link_name":"","parent":257}},"265":{"bom_file":{"parent":257,"name":"Info.plist"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":600,"checksum":"3742027903","dev_type":0,"link_name":"","parent":257}},"266":{"bom_file":{"parent":257,"name":"PkgInfo"},"bom_info":{"type":"FILE","architecture":15,"mode":33188,"user":0,"group":0,"modified":1755119050,"size":8,"checksum":"742937289","dev_type":0,"link_name":"","parent":257}}} \ No newline at end of file diff --git a/tests/test_data/macos/bom/io.osquery.agent.bom b/tests/test_data/macos/bom/io.osquery.agent.bom new file mode 100644 index 00000000..6693f16b Binary files /dev/null and b/tests/test_data/macos/bom/io.osquery.agent.bom differ diff --git a/tests/test_data/macos/bom/io.osquery.agent.plist b/tests/test_data/macos/bom/io.osquery.agent.plist new file mode 100644 index 00000000..caa46496 Binary files /dev/null and b/tests/test_data/macos/bom/io.osquery.agent.plist differ diff --git a/tests/test_data/macos/bom/pointers.raw b/tests/test_data/macos/bom/pointers.raw new file mode 100644 index 00000000..ddd1386d Binary files /dev/null and b/tests/test_data/macos/bom/pointers.raw differ diff --git a/tests/test_data/macos/bom/tree_index.raw b/tests/test_data/macos/bom/tree_index.raw new file mode 100644 index 00000000..31c44278 Binary files /dev/null and b/tests/test_data/macos/bom/tree_index.raw differ diff --git a/tests/test_data/macos/bom/vars.raw b/tests/test_data/macos/bom/vars.raw new file mode 100644 index 00000000..45222a3a Binary files /dev/null and b/tests/test_data/macos/bom/vars.raw differ diff --git a/tests/test_data/windows/eventlogs/System.evtx b/tests/test_data/windows/eventlogs/System.evtx new file mode 100644 index 00000000..e2d94fa1 Binary files /dev/null and b/tests/test_data/windows/eventlogs/System.evtx differ diff --git a/tests/windows/compile_tests.ps1 b/tests/windows/compile_tests.ps1 index 3fd5dc04..df1e7ebc 100644 --- a/tests/windows/compile_tests.ps1 +++ b/tests/windows/compile_tests.ps1 @@ -1,17 +1,51 @@ -# AI took my simple 15 line batch script and turned it into a nice ~180 line PowerShell script XD +param( + [string]$test = "" +) + +# If a folder name is provided, run tests only for that subdirectory of the current directory +# If empty, run tests for all immediate subdirectories +$cwd = Get-Location + +if ($test -ne "") { + $targetDir = Get-ChildItem -Directory | Where-Object { $_.Name -ieq $test } + if (-not $targetDir) { + Write-Host "Error: No subdirectory named '$test' found in $($cwd.Path)" -ForegroundColor Red + exit 2 + } + $dirs = @($targetDir) +} else { + $dirs = Get-ChildItem -Directory + if ($dirs.Count -eq 0) { + Write-Host "No subdirectories found in $($cwd.Path)" -ForegroundColor Yellow + } +} # Record start time $startTime = Get-Date -# Compile and test all TypeScript files in subdirectories +# Compile and test all TypeScript files in selected subdirectories $results = @() -foreach ($dir in Get-ChildItem -Directory) { +foreach ($dir in $dirs) { $projStart = Get-Date Write-Host "šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„ Running test for $($dir.Name) šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„šŸ”„" + $inTs = Join-Path $dir.FullName "main.ts" + $outJs = Join-Path $dir.FullName "main.js" + + if (-not (Test-Path -LiteralPath $inTs)) { + Write-Host "āš ļø Skipping $($dir.Name): $inTs not found" -ForegroundColor Yellow + $projEnd = Get-Date + $results += [PSCustomObject]@{ + Project = $dir.Name + Status = "No Source" + Duration = $projEnd - $projStart + } + continue + } + # Compile TypeScript with esbuild - esbuild --log-level=silent --bundle --outfile="$($dir.FullName)\main.js" "$($dir.FullName)\main.ts" + esbuild --log-level=silent --bundle --outfile="$outJs" "$inTs" $compileExit = $LASTEXITCODE if ($compileExit -ne 0) { @@ -26,7 +60,7 @@ foreach ($dir in Get-ChildItem -Directory) { } # Run the tester only if compile succeeded - & .\script_tester.exe "$($dir.FullName)\main.js" + & .\script_tester.exe "$outJs" $testExit = $LASTEXITCODE $projEnd = Get-Date @@ -61,9 +95,11 @@ $sortedResults = $results | Sort-Object Duration -Descending foreach ($r in $sortedResults) { $line = "{0,-20} {1,-15} {2:hh\:mm\:ss}" -f $r.Project, $r.Status, $r.Duration switch ($r.Status) { - "Passed" { Write-Host $line -ForegroundColor Green } - "Test Failed" { Write-Host $line -ForegroundColor Red } - "Compile Failed"{ Write-Host $line -ForegroundColor Yellow } + "Passed" { Write-Host $line -ForegroundColor Green } + "Test Failed" { Write-Host $line -ForegroundColor Red } + "Compile Failed" { Write-Host $line -ForegroundColor Yellow } + "No Source" { Write-Host $line -ForegroundColor DarkYellow } + default { Write-Host $line } } } @@ -77,7 +113,7 @@ if ($results.Status -contains "Compile Failed" -or $results.Status -contains "Te # --- Elapsed Time --- Write-Host ("ā±ļø Total elapsed time: {0:hh\:mm\:ss}" -f $elapsed) -ForegroundColor Magenta -# --- Highlight Slowest & Fastest Projects --- +# --- Highlight Slowest & Fastest tests --- $slowest = $sortedResults | Select-Object -First 1 $fastest = $sortedResults | Select-Object -Last 1 @@ -139,9 +175,11 @@ if ($results.Count -gt 0) { } $line = "{0,-20} {1,-15} {2,6:N1}% (Cumulative: {3,6:N1}%){4}" -f $r.Project, $bar, $percent, $cumulative, $marker switch ($r.Status) { - "Passed" { Write-Host $line -ForegroundColor Green } - "Test Failed" { Write-Host $line -ForegroundColor Red } - "Compile Failed"{ Write-Host $line -ForegroundColor Yellow } + "Passed" { Write-Host $line -ForegroundColor Green } + "Test Failed" { Write-Host $line -ForegroundColor Red } + "Compile Failed" { Write-Host $line -ForegroundColor Yellow } + "No Source" { Write-Host $line -ForegroundColor DarkYellow } + default { Write-Host $line } } if ($cumulative -le 80) { @@ -149,7 +187,7 @@ if ($results.Count -gt 0) { } } - # --- Top 80% Projects List --- + # --- Top 80% tests List --- if ($top80List.Count -gt 0) { Write-Host "`n⭐ Top 80% tests (cumulative runtime)" -ForegroundColor Cyan foreach ($proj in $top80List) { diff --git a/tests/windows/onedrive/main.ts b/tests/windows/onedrive/main.ts index 8f51379b..97db7efe 100644 --- a/tests/windows/onedrive/main.ts +++ b/tests/windows/onedrive/main.ts @@ -1,12 +1,32 @@ -import { ApplicationError } from "../../../src/applications/errors"; -import { onedriveDetails } from "../../../src/applications/onedrive/parser"; -import { PlatformType } from "../../../src/system/systeminfo"; +import { OneDrive, PlatformType } from "../../../mod"; +import { testExtractSyncEngine, testOneDrive, testReadOdlFiles } from "../../test"; function main() { - const results = onedriveDetails(PlatformType.Windows); - if (results instanceof ApplicationError) { - throw results; + console.log('Running Windows OneDrive tests....'); + console.log(' Starting live test....'); + const client = new OneDrive(PlatformType.Windows); + if (client.oneDriveProfiles().length === 0) { + console.info('No OneDrive application!'); } + const keys = client.oneDriveKeys(); + if(client.oneDriveProfiles().length !== 0 && keys.length === 0) { + throw console.error(`No keys found?`); + } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting OneDrive Mock tests....'); + testOneDrive(); + console.log(' All OneDrive Mock tests passed! 🄳\n'); + + console.log(' Starting OneDrive ODL tests....'); + testReadOdlFiles(); + console.log(' All OneDrive ODL tests passed! 🄳\n'); + + console.log(' Starting OneDrive Sync Database tests....'); + testExtractSyncEngine(); + console.log(' All OneDrive Sync Database tests passed! 🄳\n'); + + console.log('All Windows OneDrive tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); } main(); diff --git a/tests/windows/providers/main.ts b/tests/windows/providers/main.ts new file mode 100644 index 00000000..22667acb --- /dev/null +++ b/tests/windows/providers/main.ts @@ -0,0 +1,17 @@ +import { getEventlogProviders } from "../../../mod"; + +function main() { + console.log('Running Windows EventLog provider tests....'); + console.log(' Starting live test....'); + + const results = getEventlogProviders(); + if (results.length === 0) { + throw `Did not get any providers?`; + } + console.log(' Live test passed! 🄳\n'); + + + console.log('All Windows EventLog provider tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +main(); diff --git a/tests/windows/run/main.ts b/tests/windows/run/main.ts new file mode 100644 index 00000000..18c3e6b8 --- /dev/null +++ b/tests/windows/run/main.ts @@ -0,0 +1,21 @@ +import { getRunKeys } from "../../../mod"; +import { WindowsError } from "../../../src/windows/errors"; +import { testGetRunKeys } from "../../test"; + +function main() { + console.log('Running Windows Registry Run Key tests....'); + console.log(' Starting live test....'); + const results = getRunKeys(); + if (results instanceof WindowsError) { + throw results; + } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting Windows Registry Run Key test....'); + testGetRunKeys(); + + console.log(' Windows Registry Run Key test passed! 🄳'); + console.log('All Windows Registry Run Key tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +main(); diff --git a/tests/windows/services/main.ts b/tests/windows/services/main.ts new file mode 100644 index 00000000..0c5c483e --- /dev/null +++ b/tests/windows/services/main.ts @@ -0,0 +1,21 @@ +import { serviceInstalls } from "../../../mod"; +import { WindowsError } from "../../../src/windows/errors"; +import { testServiceInstalls } from "../../test"; + +function main() { + console.log('Running Windows Service install tests....'); + console.log(' Starting live test....'); + const results = serviceInstalls(); + if (results instanceof WindowsError) { + throw results; + } + console.log(' Live test passed! 🄳\n'); + + console.log(' Starting Windows Service install test....'); + testServiceInstalls(); + + console.log(' Windows Service install test passed! 🄳'); + console.log('All Windows Service install tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +main(); diff --git a/tests/windows/updates/main.ts b/tests/windows/updates/main.ts index 6dbdace1..d6cdffee 100644 --- a/tests/windows/updates/main.ts +++ b/tests/windows/updates/main.ts @@ -3,6 +3,8 @@ import { Updates } from "../../../src/windows/ese/updates"; function main() { const client = new Updates(); + console.log('Running Windows Update History tests....'); + console.log(' Starting live test....'); const results = client.updateHistory(client.pages); if (results instanceof WindowsError) { @@ -12,6 +14,9 @@ function main() { throw results; } + console.log(' Live test passed! 🄳\n'); + console.log('All Windows Update History tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); + } main(); diff --git a/tests/windows/usbs/main.ts b/tests/windows/usbs/main.ts index afc9bf81..3ed63bb1 100644 --- a/tests/windows/usbs/main.ts +++ b/tests/windows/usbs/main.ts @@ -2,11 +2,15 @@ import { listUsbDevices } from "../../../mod"; import { WindowsError } from "../../../src/windows/errors"; function main() { + console.log('Running Windows USB devices tests....'); + console.log(' Starting live test....'); const results = listUsbDevices(); if (results instanceof WindowsError) { throw results; } + console.log(' Live test passed! 🄳\n'); + console.log('All Windows USB devices tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); } main(); diff --git a/tests/windows/wifi/main.ts b/tests/windows/wifi/main.ts new file mode 100644 index 00000000..7c8c42da --- /dev/null +++ b/tests/windows/wifi/main.ts @@ -0,0 +1,21 @@ +import { wifiNetworksWindows } from "../../../mod"; +import { WindowsError } from "../../../src/windows/errors"; +import { testWindowsWifiNetworks } from "../../test"; + +function main() { + console.log('Running Windows WiFi networks tests....'); + console.log(' Starting live test....'); + const results = wifiNetworksWindows(); + + if (results instanceof WindowsError) { + throw results; + } + + console.log(' Live test passed! 🄳\n'); + console.log(' Starting Windows Wifi network test....'); + testWindowsWifiNetworks(); + + console.log('All Windows WiFi networks tests passed! šŸ„³šŸ’ƒšŸ•ŗ'); +} + +main(); diff --git a/tsconfig.json b/tsconfig.json index 55bf77be..b26e743e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ /* Visit https://aka.ms/tsconfig to read more about this file */ /* Language and Environment */ "target": "es2024", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "module": "nodenext", /* JavaScript Support */ "allowJs": false, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ diff --git a/types/applications/chromium.ts b/types/applications/chromium.ts index adbb5bb7..9c41465b 100644 --- a/types/applications/chromium.ts +++ b/types/applications/chromium.ts @@ -45,6 +45,12 @@ export interface ChromiumHistory { db_path: string; /**Browser version */ version: string; + message: string; + datetime: string; + timestamp_desc: "URL Visited"; + artifact: "URL History"; + data_type: string; + browser: BrowserType; } /** @@ -113,6 +119,12 @@ export interface ChromiumDownloads { db_path: string; /**Browser version */ version: string; + message: string; + datetime: string; + timestamp_desc: "File Download Start"; + artifact: "File Download"; + data_type: string; + browser: BrowserType; } export interface ChromiumCookies { @@ -139,6 +151,92 @@ export interface ChromiumCookies { db_path: string; /**Browser version */ version: string; + message: string; + datetime: string; + timestamp_desc: "Cookie Expires"; + artifact: "Website Cookie"; + data_type: string; + browser: BrowserType; +} + +export interface ChromiumFavicons { + last_update: string; + url: string; + db_path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Favicon Updated"; + artifact: "Website Favicon"; + data_type: string; + browser: BrowserType; +} + +export interface ChromiumShortcuts { + last_update: string; + url: string; + text: string; + contents: string; + fill_into_edit: string; + shortcut_id: string; + keyword: string; + shortcut_type: ShortcutType; + db_path: string; + description: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Shortcut Last Access"; + artifact: "Website Shortcut"; + data_type: string; + browser: BrowserType; +} + +/// From: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/omnibox/browser/autocomplete_match_type.h#30 +export enum ShortcutType { + Typed = "URL Typed", + History = "URL History", + HistoryTitle = "History Title", + HistoryBody = "History Body", + HistoryKeyword = "History Keyword", + Suggest = "Suggested URL", + SearchUrl = "URL Searched", + SearchHistory = "Search History", + SearchSuggest = "Search Suggestion", + SearchTail = "Search Suggestion Tail", + SearchPersonalized = "Search Personalization", + SearchProfile = "Search Google+", // lol + SearchEngine = "Search with other Engine", + ExtensionApp = "Extension Application", + UserContact = "User Contact", + Bookmark = "Browser bookmark", + SuggestPersonalized = "Personlized Suggestion", + Calculator = "Calculator", + Clipboard = "Clipboard URL", + Voice = "Voice Suggestion", + Physical = "Physical Web", + PhysicalOverflow = "Multiple physical web", + Tab = "Tab Search", + Document = "Document Suggestion", + Pedal = "Pedal Match", + ClipboardText = "Clipboard text", + ClipboardImage = "Clipboard image", + TitleSuggest = "Suggested query title", + TitleNavSuggest = "Suggested navigation title", + OpenTab = "Opened Tab", + HistoryCluster = "History cluster suggestion", + Null = "Null suggestion", + Starter = "URL suggestion for starter keyword", + MostVisited = "Most visited site", + Repeatable = "Organic Repeatable Query", + HistoryEmbed = "Past page embedded in query", + Enterprise = "Search Enterprise policy", + TabGroup = "Tab group", + HistoryEmbedAnswers = "History embedded answers", + SearchSuggestEntity = "Search suggestion for entity", + Unkonwn = "Unknown", } export interface ChromiumAutofill { @@ -152,18 +250,15 @@ export interface ChromiumAutofill { db_path: string; /**Browser version */ version: string; + message: string; + datetime: string; + timestamp_desc: "Autofill Created"; + artifact: "Website Autofill"; + data_type: string; + browser: BrowserType; } export interface ChromiumBookmarks { - bookmark_bar: ChromiumBookmarkChildren[]; - other: ChromiumBookmarkChildren[]; - synced: ChromiumBookmarkChildren[]; - path: string; - /**Browser version */ - version: string; -} - -export interface ChromiumBookmarkChildren { date_added: string; date_last_used: string; guid: string; @@ -171,8 +266,25 @@ export interface ChromiumBookmarkChildren { name: string; type: string; url: string; - meta_info: Record; + bookmark_type: BookmarkType; + path: string; + /**Browser version */ + version: string; + message: string; + datetime: string; + timestamp_desc: "Bookmark Added"; + artifact: "Browser Bookmark"; + data_type: string; + browser: BrowserType; +} + +export enum BookmarkType { + Bar = "Bookmark Bar", + Sync = "Synced", + Other = "Other", + Unknown = "Unknown", } + export interface ChromiumLogins { origin_url: string; action_url?: string; @@ -207,6 +319,12 @@ export interface ChromiumLogins { db_path: string; /**Browser version */ version: string; + message: string; + datetime: string; + timestamp_desc: "Last Login"; + artifact: "Website Login"; + data_type: string; + browser: BrowserType; } /** @@ -228,6 +346,12 @@ export interface ChromiumDips { path: string; /**Browser version */ version: string; + message: string; + datetime: string; + timestamp_desc: "First Interaction"; + artifact: "Browser DIPS"; + data_type: string; + browser: BrowserType; } export interface ChromiumProfiles { @@ -257,8 +381,143 @@ export interface ChromiumLocalStorage extends LevelDbEntry { version: string; message: string; datetime: string; - browser: BrowserType + browser: BrowserType; timestamp_desc: "Local Storage Entry Write" | "Local Storage Write Ahead Log"; artifact: "Level Database"; data_type: "applications:leveldb:entry"; +} + +export interface ChromiumSession { + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Last Active"; + artifact: "Browser Session"; + data_type: string; + session_id: string; + last_active: string; + url: string; + title: string; + session_type: SessionType; + path: string; +} + +export enum SessionType { + Session = "Session", + Tab = "Tab", +} + +/** + * Browsers developers can add more + * Default list is at: https://source.chromium.org/chromium/chromium/src/+/main:components/sessions/core/session_service_commands.cc;l=28;drc=38321ee39cd73ac2d9d4400c56b90613dee5fe29 + */ +export enum SessionCommand { + WindowType = "WindowType", + UpdateTabNavigation = "UpdateTabNavigation", + TabWindow = "TabWindow", + WindowBounds = "WindowBounds", + TabIndexInWindow = "TabIndexInWindow", + TabNavigationPathPrunedFromBack = "TabNavigationPathPrunedFromBack", + SelectedNavigationIndex = "SelectedNavigationIndex", + SelectedTabInIndex = "SelectedTabInIndex", + WindowBounds2 = "WindowBounds2", + TabNavigationPathPrunedFromFront = "TabNavigationPathPrunedFromFront", + PinnedState = "PinnedState", + ExtensionAppID = "ExtensionAppID", + WindowBounds3 = "WindowBounds3", + WindowAppName = "WindowAppName", + TabClosed = "TabClosed", + WindowClosed = "WindowClosed", + TabUserAgentOverride = "TabUserAgentOverride", + SessionStorageAssociated = "SessionStorageAssociated", + ActiveWindow = "ActiveWindow", + LastActiveTime = "LastActiveTime", + WindowWorkspace = "WindowWorkspace", + WindowWorkspace2 = "WindowWorkspace2", + TabNavigationPathPruned = "TabNavigationPathPruned", + TabGroup = "TabGroup", + TabGroupMetadata = "TabGroupMetadata", + TabGroupMetadata2 = "TabGroupMetadata2", + TabGuid = "TabGuid", + TabUserAgentOverride2 = "TabUserAgentOverride2", + TabData = "TabData", + WindowUserTitle = "WindowUserTitle", + WindowVisibleOnAllWorkspaces = "WindowVisibleOnAllWorkspaces", + AddTabExtraData = "AddTabExtraData", + AddWindowExtraData = "AddWindowExtraData", + PlatformSessionId = "PlatformSessionId", + SplitTab = "SplitTab", + SplitTabData = "SplitTabData", + Unknown = "Unknown", + CommandStorageBackend = "CommandStorageBackend", + EdgeCommand = "EdgeCommand", + EdgeCommand2 = "EdgeCommand2", + EdgeCommand3 = "EdgeCommand3", + EdgeCommand4 = "EdgeCommand4", +} + +/// https://github.com/cclgroupltd/ccl_chromium_reader/blob/552516720761397c4d482908b6b8b08130b313a1/ccl_chromium_reader/ccl_chromium_snss2.py#L39 +export enum SessionTabCommand { + SelectedNavigtionInTab = "SelectedNavigationInTab", + UpdateTabNavigation = "UpdateTabNavigation", + RestoredEntry = "RestoredEntry", + WindowDeprecated = "WindowDeprecated", + PinnedState = "PinnedState", + ExtensionAppID = "ExtensionAppID", + WindowAppName = "WindowAppName", + TabUserAgentOverride = "TabUserAgentOverride", + Window = "Window", + TabGroupData = "TabGroupData", + TabUserAgentOverride2 = "TabUserAgentOverride2", + WindowUserTitle = "WindowUserTitle", + CreateGroup = "CreateGroup", + AddTabExtraData = "AddTabExtraData", + Unknown = "Unknown", + CommandStorageBackend = "CommandStorageBackend", +} + +export interface Preferences { + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Last Modified"; + artifact: "User Preferences"; + data_type: string; + path: string; + exception_category: ExceptionCategory; + created_version: string; + profile_id: string; + preferences_created: string; + name: string; + url: string; + last_modified: string; +} + +export enum ExceptionCategory { + AppBanner = "App Banner", + ClientHints = "Client Hints", + CookieControls = "Cookie Controls", + HttpsEnforced = "HTTPS Enforced", + MediaEngagement = "Media Engagement", + SiteEngagement = "Site Engagement", + SslCert = "SSL Cert Desicions", + Zoom = "Zoom Level", +} + +export interface Extension { + /**Browser version */ + version: string; + message: string; + datetime: string; + browser: BrowserType; + timestamp_desc: "Extension Created"; + artifact: "Browser Extension"; + data_type: string; + name: string; + author: string; + description: string; + manifest: string; + extension_version: string; } \ No newline at end of file diff --git a/types/applications/firefox.ts b/types/applications/firefox.ts index 600a648a..a7d7fea5 100644 --- a/types/applications/firefox.ts +++ b/types/applications/firefox.ts @@ -46,6 +46,11 @@ export interface FirefoxHistory { host: string; unfold: Url | undefined; db_path: string; + message: string; + datetime: string; + timestamp_desc: "URL Visited"; + artifact: "URL History"; + data_type: "application:firefox:history:entry"; } /** @@ -72,32 +77,74 @@ export interface FirefoxDownloads { last_modified: string; /**Downloaded file name */ name: string; + /**SQLITE row id */ + moz_places_id: number; + /**Page URL */ + url: string; + /**Page title */ + title: string; + /**URL in reverse */ + rev_host: string; + /**Page visit count */ + visit_count: number; + /**Hidden value */ + hidden: number; + /**Typed value */ + typed: number; + /**Frequency value */ + frequency: number; + /**Last visit time */ + last_visit_date: string; + /**GUID for entry */ + guid: string; + /**Foreign count value */ + foreign_count: number; + /**Hash of URL */ + url_hash: number; + /**Page description */ + description: string; + /**Preview image URL value */ + preview_image_url: string; db_path: string; + message: string; + datetime: string; + timestamp_desc: "File Download Start"; + artifact: "File Download"; + data_type: "application:firefox:downloads:entry"; } export interface FirefoxCookies { id: number; origin_attributes: string; - name?: string; - value?: string; - host?: string; - path?: string; - expiry?: number; - last_accessed?: string; - creation_time?: string; - is_secure?: boolean; - is_http_only?: boolean; + name: string; + value: string; + host: string; + path: string; + expiry: string; + last_accessed: string; + creation_time: string; + is_secure: boolean; + is_http_only: boolean; in_browser_element: boolean; same_site: boolean; - raw_same_site: boolean; scheme_map: number; db_path: string; + message: string; + datetime: string; + timestamp_desc: "Cookie Expires"; + artifact: "Website Cookie"; + data_type: "application:firefox:cookies:entry"; } export interface FirefoxFavicons { icon_url: string; expires: string; db_path: string; + message: string; + datetime: string; + timestamp_desc: "Favicon Expires"; + artifact: "URL Favicon"; + data_type: "application:firefox:favicons:entry"; } export interface FirefoxProfiles { @@ -115,6 +162,11 @@ export interface FirefoxStorage { accessed: number; persisted: number; db_path: string; + message: string; + datetime: string; + timestamp_desc: "Website Storage Last Accessed"; + artifact: "Website Storage"; + data_type: "application:firefox:storage:entry"; } export enum Respository { @@ -123,4 +175,23 @@ export enum Respository { Private = "Private", Unknown = "Unknown", Temporary = "Temporary", +} + +export interface FirefoxAddons { + installed: string; + updated: string; + active: boolean; + visible: boolean; + author: string; + version: string; + path: string; + db_path: string; + message: string; + datetime: string; + name: string; + description: string; + creator: string; + timestamp_desc: "Extension Installed"; + artifact: "Browser Extension"; + data_type: "application:firefox:extension:entry"; } \ No newline at end of file diff --git a/types/applications/libreoffice.ts b/types/applications/libreoffice.ts index 8e3c666e..a68433d3 100644 --- a/types/applications/libreoffice.ts +++ b/types/applications/libreoffice.ts @@ -18,4 +18,9 @@ export interface RecentFilesLibreOffice { thumbnail: string; /**Path to registrymodifications.xcu */ source: string; + message: string; + datetime: "1970-01-01T00:00:00Z"; + timestamp_desc: "N/A"; + artifact: "LibreOffice Recent Files", + data_type: "application:libreoffice:recentfiles:entry", } diff --git a/types/applications/onedrive.ts b/types/applications/onedrive.ts index fdab491b..c3e5cf84 100644 --- a/types/applications/onedrive.ts +++ b/types/applications/onedrive.ts @@ -1,10 +1,3 @@ -export interface OneDriveDetails { - logs: OneDriveLog[]; - files: OneDriveSyncEngineRecord[]; - accounts: OneDriveAccount[]; - keys: KeyInfo[]; -} - export interface OneDriveLog { path: string; filename: string; @@ -16,23 +9,11 @@ export interface OneDriveLog { version: string; os_version: string; description: string; -} - -export interface OneDriveSyncEngine { - scopes: OneDriveSyncEngineScope[]; - records: OneDriveSyncEngineRecord[]; -} - -export interface OneDriveSyncEngineScope { - scope_id: string; - site_id?: string; - web_id?: string; - list_id?: string; - tenant_id?: string; - url?: string; - remote_path?: string; - permissions?: number; - library_type?: number; + message: string; + datetime: string; + timestamp_desc: "OneDrive Log Entry Created"; + artifact: "OneDrive Log"; + data_type: "applications:onedrive:logs:entry"; } export interface OneDriveSyncEngineRecord { @@ -60,6 +41,11 @@ export interface OneDriveSyncEngineRecord { modified_by: string; last_write_count: number; db_path: string; + message: string; + datetime: string; + timestamp_desc: "OneDrive Sync Last Change"; + artifact: "OneDrive Sync Record"; + data_type: "applications:onedrive:sync:entry"; } export interface OneDriveSyncEngineFolder { @@ -79,11 +65,24 @@ export interface OneDriveAccount { email: string; device_id: string; account_id: string; + /**Not available on macOS */ last_signin: string; cid: string; + message: string; + datetime: string; + timestamp_desc: "OneDrive Last Signin"; + artifact: "OneDrive Account Info"; + data_type: "applications:onedrive:account:entry"; } export interface KeyInfo { path: string; key: string; } + +export interface OnedriveProfile { + sync_db: string[]; + odl_files: string[]; + key_file: string[]; + config_file: string[]; +} \ No newline at end of file diff --git a/types/applications/syncthing.ts b/types/applications/syncthing.ts new file mode 100644 index 00000000..ec42c670 --- /dev/null +++ b/types/applications/syncthing.ts @@ -0,0 +1,14 @@ +export interface SyncthingClient { + full_path: string; +} + +export interface SyncthingLogs { + full_path: string; + tag: string; + datetime: string; + timestamp_desc: "Syncthing Log Entry"; + level: string; + message: string; + artifact: "Syncthing Log"; + data_type: "application:syncthing:log:entry"; +} \ No newline at end of file diff --git a/types/applications/vscode.ts b/types/applications/vscode.ts index 01f5a459..56942e10 100644 --- a/types/applications/vscode.ts +++ b/types/applications/vscode.ts @@ -6,16 +6,28 @@ export interface FileHistory { path?: string; /**Path to source file */ resource: string; - /**History of source file */ - entries: Entries[]; /**Path to history source */ history_path: string; + message: string; + datetime: string; + timestamp_desc: "File Saved"; + artifact: "File History"; + data_type: "applications:vscode:filehistory:entry"; + /**Name of history file */ + id: string; + /**Time when file was saved */ + file_saved: number | string; + /**Based64 encoded file content */ + content?: string; + source?: string; + sourceDescription?: string; + [ key: string ]: unknown; } /** * Metadata related to file history entry */ -interface Entries { +export interface Entries { /**Name of history file */ id: string; /**Time when file was saved */ diff --git a/types/freebsd/packages.ts b/types/freebsd/packages.ts index 2fcc7742..67555638 100644 --- a/types/freebsd/packages.ts +++ b/types/freebsd/packages.ts @@ -9,7 +9,7 @@ export interface Pkg { comment: string; desc: string; mtree_id: number | null; - message: string | null; + pkg_message: string | null; arch: string; maintainer: string; www: string | null; @@ -23,4 +23,9 @@ export interface Pkg { dep_formula: string | null; vital: boolean; manifest_digest: string | null; + message: string; + datetime: string; + timestamp_desc: "Package Installed"; + artifact: "FreeBSD PKG"; + data_type: "freebsd:pkg:entry"; } \ No newline at end of file diff --git a/types/http/circlu.ts b/types/http/circlu.ts index e0cb101f..811febec 100644 --- a/types/http/circlu.ts +++ b/types/http/circlu.ts @@ -12,17 +12,28 @@ export interface HashlookupResponse { "tar:gnome"?: string; "tar:uname"?: string; TLSH?: string; - PackageDescription?: string; - PackageMaintainer?: string; - PackageName?: string; - PackageSection?: string; - PackageVersion?: string; + ProductCode?: { + PackageDescription?: string; + PackageMaintainer?: string; + ProductName?: string; + PackageSection?: string; + PackageVersion?: string; + ApplicationType?: string; + MfgCode?: string; + Language?: string; + }; + "hashlookup:children-total"?: number; "hashlookup:parent-total"?: number; mimetype?: string; parents?: Record[]; children?: Record[]; - [key: string]: unknown; + [ key: string ]: unknown; +} + +export interface MissingHash { + message: string; + query: string; } export enum HashType { diff --git a/types/linux/abrt.ts b/types/linux/abrt.ts index 513a6797..c94b12a3 100644 --- a/types/linux/abrt.ts +++ b/types/linux/abrt.ts @@ -10,4 +10,9 @@ export interface Abrt { backtrace: string | Record; environment: string; home: string; + message: string; + datetime: string; + timestamp_desc: "Abrt Last Occurrence"; + artifact: "Abrt"; + data_type: "linux:abrt:entry"; } \ No newline at end of file diff --git a/types/linux/ext4.ts b/types/linux/ext4.ts new file mode 100644 index 00000000..04d90f15 --- /dev/null +++ b/types/linux/ext4.ts @@ -0,0 +1,16 @@ +export interface FileEntry { + full_path: string; + inode: number; + file_type: FileType; +} + +export enum FileType { + File = "File", + Directory = "Directory", + Device = "Device", + Block = "Block", + FifoQueue = "FifoQueue", + Socket = "Socket", + SymbolicLink = "SymbolicLink", + Unknown = "Unknown", +} \ No newline at end of file diff --git a/types/linux/gnome/epiphany.ts b/types/linux/gnome/epiphany.ts index 68f2ff50..80c72ed1 100644 --- a/types/linux/gnome/epiphany.ts +++ b/types/linux/gnome/epiphany.ts @@ -15,6 +15,11 @@ export interface EpiphanyHistory { referring_visit: string | null; db_path: string; unfold?: Url; + message: string; + datetime: string; + timestamp_desc: "URL Visited"; + artifact: "URL History"; + data_type: "linux:gnome:epiphany:history:entry", } /** @@ -32,12 +37,22 @@ export interface EpiphanyCookies { is_http_only: boolean | null; same_site: boolean | null; db_path: string; + message: string; + datetime: string; + timestamp_desc: "Cookie Expires"; + artifact: "Website Cookie"; + data_type: "linux:browser:epiphany:cookie:entry", } export interface EpiphanyPermissions { url: string; permissions: Record; file_path: string; + message: string; + datetime: "1970-01-01T00:00:00.000Z", + timestamp_desc: "N/A"; + artifact: "GNOME Epiphany Site Permission"; + data_type: "linux:browser:epiphany:permissions:entry", } export enum VisitType { @@ -65,6 +80,11 @@ export interface EpiphanyPrint { pages: string | number; collate: boolean; file_path: string; + message: string; + datetime: "1970-01-01T00:00:00.000Z", + timestamp_desc: "N/A"; + artifact: "GNOME Epiphany Last Print"; + data_type: "linux:browser:epiphany:cookie:entry", } export interface EpiphanySessions { @@ -73,4 +93,9 @@ export interface EpiphanySessions { /**Base64 blob */ history: string; session_path: string; + message: string; + datetime: "1970-01-01T00:00:00.000Z", + timestamp_desc: "N/A"; + artifact: "GNOME Epiphany Session"; + data_type: "linux:browser:epiphany:session:entry", } \ No newline at end of file diff --git a/types/linux/gnome/extensions.ts b/types/linux/gnome/extensions.ts index 832e9981..617326d8 100644 --- a/types/linux/gnome/extensions.ts +++ b/types/linux/gnome/extensions.ts @@ -17,7 +17,7 @@ export interface Extension { /**Extension Type: User or System */ extension_type: ExtensionType; /**Other JSON key entries */ - [key: string]: unknown; + [ key: string ]: unknown; /**metadata.json created */ created: string; /**metadata.json modified */ @@ -26,6 +26,11 @@ export interface Extension { accessed: string; /**metadata.json changed */ changed: string; + message: string; + datetime: string; + timestamp_desc: "Created"; + artifact: "GNOME Extension"; + data_type: "linux:gnome:extensions:entry", } export enum ExtensionType { diff --git a/types/linux/gnome/gvfs.ts b/types/linux/gnome/gvfs.ts index 6b94c417..3b3aba21 100644 --- a/types/linux/gnome/gvfs.ts +++ b/types/linux/gnome/gvfs.ts @@ -25,4 +25,9 @@ export interface GvfsEntry { last_change: string; /**GFVS file source */ source: string; + message: string; + datetime: string; + timestamp_desc: "Last Changed"; + artifact: "GNOME Virtual Filesystem"; + data_type: "linux:gnome:gvfs:entry", } diff --git a/types/linux/gnome/usage.ts b/types/linux/gnome/usage.ts index e0c30997..44894ed7 100644 --- a/types/linux/gnome/usage.ts +++ b/types/linux/gnome/usage.ts @@ -10,4 +10,9 @@ export interface AppUsage { "last-seen": string; /**Path to the parsed application_state file */ source: string; + message: string; + datetime: string; + timestamp_desc: "Last Seen"; + artifact: "GNOME Application Usage"; + data_type: "linux:gnome:usage:entry", } diff --git a/types/linux/rpm.ts b/types/linux/rpm.ts index e822d1f6..f3a2a032 100644 --- a/types/linux/rpm.ts +++ b/types/linux/rpm.ts @@ -11,4 +11,9 @@ export interface RpmPackages { package_group: string; summary: string; url: string; + message: string; + datetime: string; + timestamp_desc: "RPM Package Installed"; + artifact: "RPM Package"; + data_type: "linux:rpm:entry"; } diff --git a/types/linux/sqlite/wtmpdb.ts b/types/linux/sqlite/wtmpdb.ts new file mode 100644 index 00000000..a01667b4 --- /dev/null +++ b/types/linux/sqlite/wtmpdb.ts @@ -0,0 +1,15 @@ +export interface LastLogons { + id: number; + type: number; + user: string; + login: string; + logout: string; + tty: string; + remote: string; + service: string; + message: string; + datetime: string; + timestamp_desc: "User Logon"; + artifact: "wtmpdb Logons"; + data_type: "linux:wtmpdb:entry"; +} \ No newline at end of file diff --git a/types/macos/safari.ts b/types/macos/safari.ts index 5d4ef759..5086e17d 100644 --- a/types/macos/safari.ts +++ b/types/macos/safari.ts @@ -147,7 +147,7 @@ export interface Cookie { timestamp_desc: string; artifact: string; data_type: string; - [key: string]: any; + [ key: string ]: unknown; } export enum CookieFlag { diff --git a/types/system/systeminfo.ts b/types/system/systeminfo.ts index 6aae01f5..87aa484f 100644 --- a/types/system/systeminfo.ts +++ b/types/system/systeminfo.ts @@ -66,6 +66,8 @@ export interface Disks { available_space: number; /**If disk is removable */ removable: boolean; + /**Path to the disk. Ex: /dev/sda1 */ + name: string; } /** diff --git a/types/timesketch/timeline.ts b/types/timesketch/timeline.ts index 872905f5..10252a46 100644 --- a/types/timesketch/timeline.ts +++ b/types/timesketch/timeline.ts @@ -30,10 +30,7 @@ export enum TimesketchArtifact { USERS_MACOS = "users-macos", GROUPS_MACOS = "groups-macos", EXECPOLICY = "execpolicy", - /**Use `FILES_WINDOWS` for Windows filelistings */ FILES = "files", - /**Use `FILES` for macOS or Linux filelistings */ - FILES_WINDOWS = "files", SUDOLOGS_MACOS = "sudologs-macos", EMOND = "emond", SPOTLIGHT = "spotlight", diff --git a/types/windows/ese/certs.ts b/types/windows/ese/certs.ts new file mode 100644 index 00000000..ebb03332 --- /dev/null +++ b/types/windows/ese/certs.ts @@ -0,0 +1,64 @@ +export interface Certificates { + common_name: string; + request_id: number; + /** Base64 encoded */ + raw_cert: string; + hash: string; + serial_number: string; + distinguished_name: string; + domain: string; +} + +export interface Requests { + request_id: number; + request_type: RequestType; + status_code_number: number; + status_code: StatusCode; + disposition_message: string; + requester_name: string; + caller_name: string; + request_attributes: string; + submitted: string; + resolved: string; +} + +export interface RequestAttributes { + request_id: number; + name: string; + value: string; +} + +export enum RequestType { + PKCS10_Full = "PKCS10, Full Response", + PKCS10 = "PKCS10", + Unknown = "Unknown", +} + +/** + * Various status codes for certificate requests + * There are [alot](https://github.com/fox-it/dissect.database/pull/7/files#diff-60ccdb935072fd3aa71d6810f7c3aa7ca8ef42aadc6ce9e39ed5f54c5cc36d31R28) + * Only some listed so far + */ +export enum StatusCode { + Completed = "Operation Completed Successfully", + BadRequestSubject = "Bad Request Subject", + NoRequest = "No Request", + Empty = "Property Empty", + InvalidCA = "Invalid CA Certificte", + Suspended = "Server Suspended", + EncodingLength = "Encoding Length", + Conflict = "Role Conflict", + Restrict = "Restricted Officer", + NotConfigured = "Key Archival Not Configured", + Kra = "No Valid KRA", + BadRequest = "Bad Request Key Archival", + NoAdmin = "No CA Admin Defined", + BadRenewal = "Bad Renewal Cert Attribute", + NoSessions = "No DB Sessions", + Fault = "Alignment Fault", + Denied = "Enroll Denied", + TemplateDenied = "Template Denied", + Downlevel = "Downlevel DC SSL or Upgrade", + NoPolicy = "No Policy Server", + Unknown = "Unknown", +} \ No newline at end of file diff --git a/types/windows/eventlogs/services.ts b/types/windows/eventlogs/services.ts index 3b5ca689..ca1450a6 100644 --- a/types/windows/eventlogs/services.ts +++ b/types/windows/eventlogs/services.ts @@ -9,6 +9,11 @@ export interface ServiceInstalls { process_id: number; thread_id: number; sid: string; + message: string; + datetime: string; + timestamp_desc: "Windows Service Installed"; + artifact: "EventLog Service 7045"; + data_type: "windows:eventlog:system:service"; } export interface RawService7045 { diff --git a/types/windows/registry/eventlog_providers.ts b/types/windows/registry/eventlog_providers.ts new file mode 100644 index 00000000..6b9c4649 --- /dev/null +++ b/types/windows/registry/eventlog_providers.ts @@ -0,0 +1,20 @@ +export interface RegistryEventlogProviders { + registry_file: string; + key_path: string; + name: string; + channel_names: string[]; + message_file: string; + last_modified: string; + parameter_file: string; + guid: string; + enabled: boolean; + channel_types: ChannelType[]; +} + +export enum ChannelType { + Admin = "Admin", + Operational = "Operational", + Analytic = "Analytic", + Debug = "Debug", + Unknown = "Unknown", +} \ No newline at end of file diff --git a/types/windows/registry/run.ts b/types/windows/registry/run.ts new file mode 100644 index 00000000..9d0e3078 --- /dev/null +++ b/types/windows/registry/run.ts @@ -0,0 +1,15 @@ +export interface RegistryRunKey { + key_modified: string; + key_path: string; + registry_path: string; + registry_file: string; + path: string; + /**When file was created */ + created: string; + has_signature: boolean; + md5: string; + sha1: string; + sha256: string; + value: string; + name: string; +} \ No newline at end of file diff --git a/types/windows/registry/wifi.ts b/types/windows/registry/wifi.ts new file mode 100644 index 00000000..81762ce7 --- /dev/null +++ b/types/windows/registry/wifi.ts @@ -0,0 +1,36 @@ +export interface Wifi { + name: string; + description: string; + managed: boolean; + category: WifiCategory; + created_local_time: string; + name_type: NameType; + id: string; + last_connected_local_time: string; + registry_path: string; + registry_file: string; + message: string; + datetime: string; + timestamp_desc: "Registry Key Modified"; + artifact: "WiFi Network"; + data_type: "windows:registry:wifi:entry"; +} + +export enum WifiCategory { + Public = "Public", + Private = "Private", + Domain = "Domain", + Unknown = "Unknown", +} + +/** + * From: https://community.spiceworks.com/t/what-are-the-nametype-values-for-the-networklist-registry-keys/526112/6 + */ +export enum NameType { + Wired = "Wired", + Vpn = "VPN", + Wireless = "Wireless", + Mobile = "Mobile", + Unknown = "Unknown", + +} \ No newline at end of file