Files
windows95/src/main/settings.ts
Felix Rieseberg 45f5a136b2 Add SMB1 server and host folder share
Windows 95 can now mount a host folder as a network drive at \\HOST\HOST.
Read-only, ~1500 lines, zero deps. Defaults to ~/Downloads, configurable in
Settings.

Protocol: NEGOTIATE (LANMAN2.1), SESSION_SETUP, TREE_CONNECT, TRANSACTION/RAP
(NetShareEnum, NetServerGetInfo, NetWkstaGetInfo), TRANSACTION2/FIND_FIRST2,
SEARCH (8.3 with ~N suffix mapping), OPEN_ANDX, NT_CREATE_ANDX, READ_ANDX,
CLOSE, QUERY_INFORMATION, CHECK_DIRECTORY. NetBIOS Name Service on UDP 137
answers Node Status and Name Query so \\HOST resolves.

v86 hook: monkeypatches adapter.on_tcp_connection (old API), shadows
adapter.receive during a port-80 probe to steal a TCPConnection without
side effects, re-aims it at port 139. Data via .on_data (Closure
dead-code-eliminated .on/.emit). Also registers tcp-connection bus event
for newer v86 builds.

Security: read-only, path traversal blocked lexically and through symlinks
(realpath the deepest existing ancestor, re-append tail, confirm under root).
Share path validated in main-process IPC.

BIOS updated to SeaBIOS 1.16.2 (compatible with old v86). v86 itself stays
on the Feb 2025 prod build — newer builds hang at the splash screen on fresh
boot (bisect tooling included in tools/).

Also: tools/update-v86.js builds wasm+libv86+BIOS from a local v86 checkout
and refuses to install JS/wasm pairs more than 14 days apart (copy.sh ships
mismatched pairs). tools/parcel-build.js dynamic-import patch made tolerant
of post-d4c5fa86 builds.
2026-04-11 01:03:34 -07:00

75 lines
1.6 KiB
TypeScript

import * as fs from "fs";
import * as path from "path";
import { app } from "electron";
export interface Settings {
isFileServerEnabled: boolean;
isFileServerShowingHiddenFiles: boolean;
isFileServerShowingSystemHiddenFiles: boolean;
smbSharePath: string;
}
const DEFAULT_SETTINGS: Settings = {
isFileServerEnabled: true,
isFileServerShowingHiddenFiles: false,
isFileServerShowingSystemHiddenFiles: false,
smbSharePath: app.getPath("downloads"),
};
class SettingsManager {
private filePath: string;
private data: Settings;
constructor() {
this.filePath = path.join(app.getPath("userData"), "settings.json");
this.data = this.load();
}
private load(): Settings {
try {
if (fs.existsSync(this.filePath)) {
const fileContent = fs.readFileSync(this.filePath, "utf8");
const parsed = JSON.parse(fileContent);
return {
...DEFAULT_SETTINGS,
...parsed,
};
}
} catch (error) {
console.error("Error loading settings:", error);
}
return DEFAULT_SETTINGS;
}
private save(): void {
try {
fs.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2));
} catch (error) {
console.error("Error saving settings:", error);
}
}
get(key: keyof Settings): any {
return this.data[key];
}
set<K extends keyof Settings>(key: K, value: Settings[K]): void {
this.data[key] = value;
this.save();
}
delete(key: keyof Settings): void {
delete this.data[key];
this.save();
}
clear(): void {
this.data = DEFAULT_SETTINGS;
this.save();
}
}
export const settings = new SettingsManager();