@swf2es/desktop 0.1.15 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +85 -12
  2. package/dist/launch/launch.js +4 -1
  3. package/dist/launch/launch.js.map +1 -1
  4. package/dist/main/air.d.ts +3 -3
  5. package/dist/main/air.d.ts.map +1 -1
  6. package/dist/main/air.js +17 -8
  7. package/dist/main/air.js.map +1 -1
  8. package/dist/main/case-paths.d.ts +12 -0
  9. package/dist/main/case-paths.d.ts.map +1 -0
  10. package/dist/main/case-paths.js +84 -0
  11. package/dist/main/case-paths.js.map +1 -0
  12. package/dist/main/connections.d.ts +20 -1
  13. package/dist/main/connections.d.ts.map +1 -1
  14. package/dist/main/connections.js +71 -8
  15. package/dist/main/connections.js.map +1 -1
  16. package/dist/main/main.js +133 -9
  17. package/dist/main/main.js.map +1 -1
  18. package/dist/main/netlog.d.ts +21 -0
  19. package/dist/main/netlog.d.ts.map +1 -0
  20. package/dist/main/netlog.js +90 -0
  21. package/dist/main/netlog.js.map +1 -0
  22. package/dist/main/network.d.ts +10 -0
  23. package/dist/main/network.d.ts.map +1 -1
  24. package/dist/main/network.js +111 -35
  25. package/dist/main/network.js.map +1 -1
  26. package/dist/main/proxy.d.ts +48 -0
  27. package/dist/main/proxy.d.ts.map +1 -0
  28. package/dist/main/proxy.js +402 -0
  29. package/dist/main/proxy.js.map +1 -0
  30. package/dist/main/sandbox.d.ts.map +1 -1
  31. package/dist/main/sandbox.js +2 -1
  32. package/dist/main/sandbox.js.map +1 -1
  33. package/dist/main/settings.d.ts +2 -0
  34. package/dist/main/settings.d.ts.map +1 -1
  35. package/dist/main/settings.js +4 -0
  36. package/dist/main/settings.js.map +1 -1
  37. package/dist/main/sockets.d.ts +6 -2
  38. package/dist/main/sockets.d.ts.map +1 -1
  39. package/dist/main/sockets.js +18 -3
  40. package/dist/main/sockets.js.map +1 -1
  41. package/dist/main/websocket-connections.d.ts +73 -0
  42. package/dist/main/websocket-connections.d.ts.map +1 -0
  43. package/dist/main/websocket-connections.js +266 -0
  44. package/dist/main/websocket-connections.js.map +1 -0
  45. package/dist/main/websockets.d.ts +12 -0
  46. package/dist/main/websockets.d.ts.map +1 -0
  47. package/dist/main/websockets.js +94 -0
  48. package/dist/main/websockets.js.map +1 -0
  49. package/dist/preload/preload.cjs +20 -0
  50. package/dist/preload/preload.cjs.map +1 -1
  51. package/dist/renderer/air.d.ts.map +1 -1
  52. package/dist/renderer/air.js +1 -0
  53. package/dist/renderer/air.js.map +1 -1
  54. package/dist/renderer/full-screen.d.ts +4 -0
  55. package/dist/renderer/full-screen.d.ts.map +1 -0
  56. package/dist/renderer/full-screen.js +32 -0
  57. package/dist/renderer/full-screen.js.map +1 -0
  58. package/dist/renderer/index.d.ts.map +1 -1
  59. package/dist/renderer/index.js +4 -0
  60. package/dist/renderer/index.js.map +1 -1
  61. package/dist/renderer/websockets.d.ts +4 -0
  62. package/dist/renderer/websockets.d.ts.map +1 -0
  63. package/dist/renderer/websockets.js +36 -0
  64. package/dist/renderer/websockets.js.map +1 -0
  65. package/dist/shared/api.d.ts +53 -0
  66. package/dist/shared/api.d.ts.map +1 -1
  67. package/package.json +7 -7
  68. package/src/launch/launch.ts +5 -2
  69. package/src/main/air.ts +18 -8
  70. package/src/main/case-paths.ts +97 -0
  71. package/src/main/connections.ts +90 -8
  72. package/src/main/main.ts +174 -10
  73. package/src/main/netlog.ts +108 -0
  74. package/src/main/network.ts +140 -37
  75. package/src/main/proxy.ts +497 -0
  76. package/src/main/sandbox.ts +2 -1
  77. package/src/main/settings.ts +5 -0
  78. package/src/main/sockets.ts +22 -3
  79. package/src/main/websocket-connections.ts +344 -0
  80. package/src/main/websockets.ts +117 -0
  81. package/src/preload/preload.cts +23 -0
  82. package/src/renderer/air.ts +1 -0
  83. package/src/renderer/full-screen.ts +44 -0
  84. package/src/renderer/index.ts +4 -0
  85. package/src/renderer/websockets.ts +43 -0
  86. package/src/shared/api.ts +40 -0
package/README.md CHANGED
@@ -9,6 +9,11 @@ npx @swf2es/desktop [options] [file.swf | https://host/movie.swf]
9
9
  npx @swf2es/desktop [options] app.xml [root-dir] [-- arguments...]
10
10
  ```
11
11
 
12
+ npx takes the first `--` on its command line as the end of its own
13
+ options, so with arguments for the application write one before the
14
+ package too: `npx -- @swf2es/desktop app.xml -- --server=local`. The
15
+ installed command, `swf2es-desktop`, needs only the second.
16
+
12
17
  Node 22.18 or later runs it. The first run downloads Electron's binary
13
18
  (about 100 MB), once; installed, the command is `swf2es-desktop`. A
14
19
  relative path is taken from the directory the command was run in.
@@ -32,7 +37,11 @@ fetch-electron` does so ahead, for the tests.
32
37
  open; File › Open Recent lists the last ten, files and URLs. The
33
38
  window takes the SWF's name. View › Reload Movie (Ctrl+R) starts it
34
39
  again, View › Toggle Full Screen (F11) fills the screen, and File ›
35
- Close Movie (Ctrl+W) stops it. Opening another SWF destroys the
40
+ Close Movie (Ctrl+W) stops it. A SWF's own full screen
41
+ (`Stage.displayState`) is the window's too: it needs no click, as in AIR
42
+ and Flash's projector, draws its `fullScreenSourceRect` alone where it
43
+ set one, and ends with Esc or F11, which the SWF hears of as a
44
+ `FullScreenEvent`. Opening another SWF destroys the
36
45
  player before the next starts.
37
46
  - **Stage3D.** View › Stage3D (Experimental) opts in to Context3D playback.
38
47
  It starts off, remembers the choice in `settings.json`, and restarts the
@@ -50,18 +59,59 @@ fetch-electron` does so ahead, for the tests.
50
59
  MPL-2.0) and playerglobal that ship with the player, with nothing to set
51
60
  up. File › Choose playerglobal.abc… plays on another playerglobal, such
52
61
  as Flash Player's, in place of the app's own; the app keeps its path in
53
- `settings.json` in Electron's user data directory.
62
+ `settings.json` in Electron's user data directory, across updates of the
63
+ app, and says so on stderr at each start. File › Use the App's
64
+ playerglobal goes back to the app's own.
54
65
  - **Trace.** `--trace` prints what the page logs, a SWF's `trace()` among
55
66
  it, to the terminal: trace lines to stdout, warnings and errors to stderr.
67
+ - **Network log.** `--log-network` prints each of the SWF's requests to
68
+ stderr as it is answered (`swf2es: net GET https://… 200 12.3 kB 48 ms`),
69
+ an aborted one too, and each socket and each WebSocket of an AIR
70
+ application as it is asked for, opened, refused, failed and closed
71
+ (`swf2es: websocket #1 connecting to ws://…`, `open`, `close 1000`). A
72
+ refused request is said with or without it. The
73
+ window's DevTools show none of these in their Network tab: the page has
74
+ no network, and the main process sends them.
75
+ `--log-sockets` prints those lines and each message a socket or a
76
+ WebSocket sends (`>`) and receives (`<`): its size and its first 512
77
+ bytes, as text where it is text and in hex otherwise, a WebSocket's
78
+ text message as its text. That is whatever the SWF sends, a login
79
+ and its password among it: mind where the terminal's output goes.
56
80
  - **Certificates.** `--ignore-certificate-errors` leaves every HTTPS
57
- server's certificate unverified for this run, and
81
+ server's certificate, and every `wss:` server's that an AIR
82
+ application's WebSocket connects to, unverified for this run, and
58
83
  `--ignore-certificate-errors=dev.test,localhost` those hosts' alone, on
59
84
  any port: for a server of your own whose certificate it signed itself.
60
85
  Whoever is between you and such a host can then read and change what the
61
- SWF loads from it. It is never kept in the settings, and the app says on
86
+ SWF loads from it or says to it. It is never kept in the settings, and the app says on
62
87
  stderr, each time it starts with it, which hosts go unverified. The page
63
- itself has no network (the main process makes a SWF's requests), so
64
- nothing but those requests is affected.
88
+ itself has no network (the main process makes a SWF's requests and
89
+ connections), so nothing but those is affected.
90
+ - **Proxy.** `--proxy=socks5://host:1080` sends everything the SWF does
91
+ on the network through a SOCKS5 proxy (RFC 1928; `socks5h://` is the
92
+ same), and `--proxy=http://host:3128` through an HTTP proxy, by a
93
+ `CONNECT` tunnel for each connection, plain http too: its http and https
94
+ requests, the policy files they need, its sockets with their socket
95
+ policies, and an AIR application's WebSockets. A username and password
96
+ go in the URL (`socks5://user:pass@host:1080`, %-escaped where they need
97
+ it): RFC 1929's for SOCKS5, `Proxy-Authorization: Basic` for HTTP. They
98
+ come from the command line alone, and are never kept nor said: the app
99
+ says on stderr, as it starts, which proxy it uses, by its host and port.
100
+ TLS is the app's own, over the tunnel, so certificates are verified, or
101
+ not for the hosts `--ignore-certificate-errors` names, as without a
102
+ proxy. Whether a host is on this machine or the local network (below)
103
+ is still judged by this machine's DNS, and the proxy is then asked for
104
+ the address judged, not the name, so it reaches nothing the judgement
105
+ did not; a socket or WebSocket nothing judged (a local SWF's, an AIR
106
+ application's) goes by its name, for the proxy to resolve. A proxy that
107
+ is not there, refuses the credentials or refuses a connection is, to
108
+ the SWF, a server that is not there (IOErrorEvent, a socket's #2031), and
109
+ a line on stderr says why: `swf2es: not loading http://…: the proxy
110
+ socks5://127.0.0.1:1080 refused: connection refused (SOCKS reply 5)`.
111
+ `--log-network`'s lines name the target, and end in `via proxy`. A
112
+ second start of the app with another `--proxy` opens nothing in the
113
+ first. An HTTP proxy that allows `CONNECT` only to port 443, as Squid
114
+ does by default, refuses plain http and sockets on other ports.
65
115
  - **Sandbox.** A SWF plays in the sandbox Flash Player gave a local SWF,
66
116
  by its FileAttributes' UseNetwork bit. Without it,
67
117
  local-with-filesystem: it reads the files in its own directory and below
@@ -90,16 +140,28 @@ fetch-electron` does so ahead, for the tests.
90
140
  - **Sockets** (`flash.net.Socket`) connect over TCP through the main
91
141
  process. The first connection to each server asks: Allow Once, Always
92
142
  Allow for This SWF (remembered in `settings.json`) or Deny.
143
+ - **WebSockets** (`air.net.WebSocket`, AIR's and not Flash Player's)
144
+ connect through the main process too, with the WebSocket client of
145
+ Electron's Node, for an AIR application alone: to any `ws:` or `wss:`
146
+ URL, unasked, text and binary messages, subprotocols and close codes.
147
+ As in a browser, it sends the close codes 1000 and 3000 to 4999 (any
148
+ other closes with none), answers a server's pings itself and sends
149
+ none of the application's own.
93
150
  - **AIR applications** run by their descriptor (`app.xml`), as adl runs
94
151
  them: its first window's content SWF, from the descriptor's directory
95
152
  or the root directory given after it, at the descriptor's size and with
96
153
  its title, the arguments after `--` handed to its InvokeEvent. It plays
97
- with AIR's API (NativeApplication, the window, `flash.filesystem.File`)
154
+ with AIR's API (NativeApplication, the window, the system's displays as
155
+ `flash.display.Screen`, `flash.filesystem.File`)
98
156
  in AIR's application sandbox: it is played from `app:/`, reads any
99
157
  local file through File, FileStream and its `app:`, `app-storage:` and
100
158
  `file:` URLs, writes any file but through its `app:` URLs, as AIR does,
101
- and reaches the network and sockets without Flash's policy files or a
102
- prompt, as an installed application does. Its storage directory is
159
+ makes temporary files and directories (`File.createTempFile()`,
160
+ `createTempDirectory()`) in the system's temporary directory, its
161
+ `File.cacheDirectory`, which it leaves for the application to delete,
162
+ and reaches the network, sockets and WebSockets (`air.net.WebSocket`)
163
+ without Flash's policy files or a prompt, as an installed application
164
+ does. Its storage directory is
103
165
  under the app's user data, by its id, and its `EncryptedLocalStore`
104
166
  beside it, encrypted by the system's keychain (Electron's
105
167
  `safeStorage`) where there is one. Only the application playing has
@@ -108,6 +170,16 @@ fetch-electron` does so ahead, for the tests.
108
170
  opened with the app runs the application too, from its own directory
109
171
  with no arguments; the app asks first, once, until the descriptor
110
172
  leaves the recent list.
173
+ - **Case in names.** Windows and macOS find a file whatever case its name
174
+ is given in, so content made there names files as it likes. On Linux, a
175
+ path a SWF or an AIR application names that is not there exactly is
176
+ found the same way: each missing name is the one in its directory equal
177
+ to it ignoring case (both as NFC, lowercased, which is close to how NTFS
178
+ and APFS fold case). `Maps/Town.swf` reads `maps/town.swf`; a file
179
+ written into `Saves/` goes into `saves/` where that is there, under the
180
+ name it was given. Where a directory holds two names that differ only in
181
+ case, neither is taken, and stderr says so once. A sandbox reaches no
182
+ more than before: what it lets a SWF read is judged on the file found.
111
183
  - **File dialogs** requested by AS2 or AS3 FileReference use native open
112
184
  and save dialogs after a click or key. Uploads and downloads use the
113
185
  same network permissions as other data requests.
@@ -118,11 +190,12 @@ fetch-electron` does so ahead, for the tests.
118
190
  ## Layout
119
191
 
120
192
  ```
121
- src/main/ the main process: window, menu, settings, swf2es://, sockets and the network
193
+ src/main/ the main process: window, menu, settings, swf2es://, sockets, WebSockets
194
+ and the network
122
195
  src/preload/ window.swf2esDesktop, the page's only way to the main process, and the
123
196
  URL dialog's window.swf2esPrompt
124
- src/renderer/ the page: the element, the welcome and library panels, the socket and
125
- fetch hosts; and the URL dialog's page
197
+ src/renderer/ the page: the element, the welcome and library panels, the socket,
198
+ WebSocket and fetch hosts; and the URL dialog's page
126
199
  src/shared/ api.ts, the types of window.swf2esDesktop
127
200
  static/ index.html (with the page's import map), open-url.html and style.css
128
201
  src/launch/ the swf2es-desktop command, and `start`: finds Electron, fetching its
@@ -3,7 +3,7 @@
3
3
  // swf2es-desktop command of the package npm installs, and a checkout's
4
4
  // `start`.
5
5
  //
6
- // npx @swf2es/desktop [--trace] [file.swf | https://host/movie.swf]
6
+ // npx @swf2es/desktop [--trace] [--log-network] [file.swf | https://host/movie.swf]
7
7
  // npx @swf2es/desktop [--trace] app.xml [root-dir] [-- arguments...]
8
8
  // pnpm --filter @swf2es/desktop start ... the same, in a checkout
9
9
  //
@@ -61,6 +61,9 @@ if (!build || appRoot.includes(`${join("node_modules", "@swf2es")}`)) {
61
61
  build = JSON.parse(readFileSync(join(appRoot, "package.json"), "utf8")).version;
62
62
  }
63
63
  const env = { ...process.env, SWF2ES_DESKTOP_BUILD: build };
64
+ // Set by tools that are Electron apps themselves, an editor's terminals and tasks among them,
65
+ // for the node they run: here it would make Electron run the app's main module as plain node.
66
+ delete env.ELECTRON_RUN_AS_NODE;
64
67
  const child = spawn(electronBinary(), [appRoot, ...args], { stdio: "inherit", env });
65
68
  child.on("exit", (code, signal) => process.exit(signal ? 1 : (code ?? 0)));
66
69
  for (const signal of ["SIGINT", "SIGTERM"]) {
@@ -1 +1 @@
1
- {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/launch/launch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/launch/launch.ts"],"names":[],"mappings":"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"}
@@ -25,7 +25,7 @@ export declare function airLaunch(command: AirCommand, currentDirectory: string,
25
25
  height: number | null;
26
26
  };
27
27
  /** What is at `path`, as File reads it; null where nothing is. */
28
- export declare function statOf(path: string): AirFileStat | null;
28
+ export declare function statOf(asked: string): AirFileStat | null;
29
29
  /** The names in the directory at `path`; null where it is none. */
30
30
  export declare function listOf(path: string): string[] | null;
31
31
  /** The bytes of the file at `path`, as FileStream's open reads them at once; null where none can be read. */
@@ -61,11 +61,11 @@ export declare class EncryptedItems {
61
61
  * `length` long, made with its directories where it is not: FileStream's
62
62
  * writes. False where it cannot be written.
63
63
  */
64
- export declare function writeOf(path: string, bytes: Uint8Array, offset: number, length: number): boolean;
64
+ export declare function writeOf(asked: string, bytes: Uint8Array, offset: number, length: number): boolean;
65
65
  /** Makes the directory at `path` and those it is in; false where it cannot. */
66
66
  export declare function createDirectoryOf(path: string): boolean;
67
67
  /** Removes the file or directory at `path`, with all in it; false where it cannot. */
68
68
  export declare function removeOf(path: string): boolean;
69
69
  /** Moves what is at `from` to `to`, its directories made; false where it cannot. */
70
- export declare function moveOf(from: string, to: string): boolean;
70
+ export declare function moveOf(askedFrom: string, askedTo: string): boolean;
71
71
  //# sourceMappingURL=air.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"air.d.ts","sourceRoot":"","sources":["../../src/main/air.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE/D,wGAAwG;AACxG,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAezE;AAED,yGAAyG;AACzG,wBAAgB,SAAS,CACvB,OAAO,EAAE,UAAU,EACnB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,oGAAoG;IACpG,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CA2BA;AAED,kEAAkE;AAClE,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAgBvD;AAED,mEAAmE;AACnE,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAMpD;AAED,6GAA6G;AAC7G,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAMtD;AAED,sGAAsG;AACtG,MAAM,WAAW,MAAM;IACrB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC;IAClC,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAEhD,YAAY,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAI9C;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAEnC;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAGzC;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIzB;IAED,KAAK,IAAI,IAAI,CAGZ;IAED,sGAAsG;IACtG,OAAO,CAAC,IAAI;IAwBZ,OAAO,CAAC,IAAI;CAcb;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAahG;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,sFAAsF;AACtF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,oFAAoF;AACpF,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAexD"}
1
+ {"version":3,"file":"air.d.ts","sourceRoot":"","sources":["../../src/main/air.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG/D,wGAAwG;AACxG,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAezE;AAED,yGAAyG;AACzG,wBAAgB,SAAS,CACvB,OAAO,EAAE,UAAU,EACnB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,oGAAoG;IACpG,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CA2BA;AAED,kEAAkE;AAClE,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAiBxD;AAED,mEAAmE;AACnE,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAMpD;AAED,6GAA6G;AAC7G,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAMtD;AAED,sGAAsG;AACtG,MAAM,WAAW,MAAM;IACrB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC;IAClC,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAEhD,YAAY,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAI9C;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAEnC;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAGzC;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIzB;IAED,KAAK,IAAI,IAAI,CAGZ;IAED,sGAAsG;IACtG,OAAO,CAAC,IAAI;IAwBZ,OAAO,CAAC,IAAI;CAcb;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAcjG;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,sFAAsF;AACtF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,oFAAoF;AACpF,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBlE"}
package/dist/main/air.js CHANGED
@@ -7,6 +7,7 @@ import { closeSync, cpSync, ftruncateSync, lstatSync, mkdirSync, openSync, readd
7
7
  import { homedir } from "node:os";
8
8
  import { basename, dirname, join, resolve, sep } from "node:path";
9
9
  import { readAirDescriptor } from "@swf2es/format";
10
+ import { resolveCase } from "./case-paths.js";
10
11
  /**
11
12
  * The AIR application `argv` names, from `cwd`: a descriptor (`.xml`), the
12
13
  * directory its content is under if one follows, and what follows `--`.
@@ -35,7 +36,7 @@ export function airLaunch(command, currentDirectory, userData, directories) {
35
36
  const applicationStorage = join(userData, "air", descriptor.id.replace(/[^\w.-]/g, "_"), "Local Store");
36
37
  mkdirSync(applicationStorage, { recursive: true });
37
38
  return {
38
- content: resolve(application, ...descriptor.content.split("/")),
39
+ content: resolveCase(resolve(application, ...descriptor.content.split("/"))),
39
40
  relative: descriptor.content,
40
41
  launch: {
41
42
  descriptor: xml,
@@ -51,7 +52,8 @@ export function airLaunch(command, currentDirectory, userData, directories) {
51
52
  };
52
53
  }
53
54
  /** What is at `path`, as File reads it; null where nothing is. */
54
- export function statOf(path) {
55
+ export function statOf(asked) {
56
+ const path = resolveCase(asked);
55
57
  try {
56
58
  const s = statSync(path);
57
59
  const link = lstatSync(path).isSymbolicLink();
@@ -72,7 +74,7 @@ export function statOf(path) {
72
74
  /** The names in the directory at `path`; null where it is none. */
73
75
  export function listOf(path) {
74
76
  try {
75
- return readdirSync(path);
77
+ return readdirSync(resolveCase(path));
76
78
  }
77
79
  catch {
78
80
  return null;
@@ -81,7 +83,7 @@ export function listOf(path) {
81
83
  /** The bytes of the file at `path`, as FileStream's open reads them at once; null where none can be read. */
82
84
  export function readOf(path) {
83
85
  try {
84
- return new Uint8Array(readFileSync(path));
86
+ return new Uint8Array(readFileSync(resolveCase(path)));
85
87
  }
86
88
  catch {
87
89
  return null;
@@ -164,7 +166,8 @@ export class EncryptedItems {
164
166
  * `length` long, made with its directories where it is not: FileStream's
165
167
  * writes. False where it cannot be written.
166
168
  */
167
- export function writeOf(path, bytes, offset, length) {
169
+ export function writeOf(asked, bytes, offset, length) {
170
+ const path = resolveCase(asked);
168
171
  return attempt(() => {
169
172
  mkdirSync(dirname(path), { recursive: true });
170
173
  // "a+" would only append; "r+" needs the file there, which "a" makes without emptying it.
@@ -181,14 +184,20 @@ export function writeOf(path, bytes, offset, length) {
181
184
  }
182
185
  /** Makes the directory at `path` and those it is in; false where it cannot. */
183
186
  export function createDirectoryOf(path) {
184
- return attempt(() => mkdirSync(path, { recursive: true }));
187
+ return attempt(() => mkdirSync(resolveCase(path), { recursive: true }));
185
188
  }
186
189
  /** Removes the file or directory at `path`, with all in it; false where it cannot. */
187
190
  export function removeOf(path) {
188
- return attempt(() => rmSync(path, { recursive: true }));
191
+ return attempt(() => rmSync(resolveCase(path), { recursive: true }));
189
192
  }
190
193
  /** Moves what is at `from` to `to`, its directories made; false where it cannot. */
191
- export function moveOf(from, to) {
194
+ export function moveOf(askedFrom, askedTo) {
195
+ const from = resolveCase(askedFrom);
196
+ let to = resolveCase(askedTo);
197
+ // A rename of its case alone, which Windows makes: the name as given, in its directory as found.
198
+ if (to === from) {
199
+ to = join(resolveCase(dirname(askedTo)), basename(askedTo));
200
+ }
192
201
  return attempt(() => {
193
202
  mkdirSync(dirname(to), { recursive: true });
194
203
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"air.js","sourceRoot":"","sources":["../../src/main/air.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,2EAA2E;AAC3E,yEAAyE;AACzE,SAAS;AACT,0EAA0E;AAC1E,OAAO,EACL,SAAS,EACT,MAAM,EACN,aAAa,EACb,SAAS,EACT,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,UAAU,EACV,MAAM,EACN,QAAQ,EACR,aAAa,EACb,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAUnD;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,GAAW;IACpD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACpF,MAAM,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;IAC5F,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QACtC,SAAS,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,SAAS,CACvB,OAAmB,EACnB,gBAAwB,EACxB,QAAgB,EAChB,WAAkE;IAUlE,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAChE,4EAA4E;IAC5E,MAAM,kBAAkB,GAAG,IAAI,CAC7B,QAAQ,EACR,KAAK,EACL,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,EACtC,aAAa,CACd,CAAC;IACF,SAAS,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/D,QAAQ,EAAE,UAAU,CAAC,OAAO;QAC5B,MAAM,EAAE;YACN,UAAU,EAAE,GAAG;YACf,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,gBAAgB;YAChB,SAAS,EAAE,GAAG;YACd,WAAW,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,WAAW,EAAE;SAClF;QACD,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QACvD,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,MAAM,EAAE,UAAU,CAAC,MAAM;KAC1B,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;QAC9C,OAAO;YACL,SAAS,EAAE,CAAC,CAAC,WAAW,EAAE;YAC1B,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;YAClC,QAAQ,EAAE,CAAC,CAAC,OAAO;YACnB,OAAO,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,OAAO;YACnC,uFAAuF;YACvF,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YACtC,YAAY,EAAE,IAAI;SACnB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,6GAA6G;AAC7G,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,IAAI,CAAC;QACH,OAAO,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAQD;;;;;;;GAOG;AACH,MAAM,OAAO,cAAc;IACR,IAAI,CAAS;IACb,MAAM,CAAgB;IACtB,KAAK,CAA0B;IAEhD,YAAY,IAAY,EAAE,MAAqB;QAC7C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IACtC,CAAC;IAED,GAAG,CAAC,IAAY,EAAE,KAAiB;QACjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,MAAM,CAAC,IAAY;QACjB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,sGAAsG;IAC9F,IAAI;QACV,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC5C,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACpC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/D,CAAC;iBAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC5B,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA2B,CAAC;YACzD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,IAAI;QACV,MAAM,KAAK,GAA2B,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM;YACtB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9D,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACjE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,aAAa,CAAC,GAAG,IAAI,CAAC,IAAI,MAAM,EAAE,IAAI,CAAC,CAAC;QACxC,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,KAAiB,EAAE,MAAc,EAAE,MAAc;IACrF,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,0FAA0F;QAC1F,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/B,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC;YACH,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC9C,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC5B,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,EAAU;IAC7C,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,kDAAkD;YAClD,IAAK,CAA2B,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAClD,MAAM,CAAC,CAAC;YACV,CAAC;YAED,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,OAAO,CAAC,MAAkB;IACjC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"air.js","sourceRoot":"","sources":["../../src/main/air.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `path`, absolute, as Windows would find it: unchanged where it is there
3
+ * exactly; otherwise from the deepest ancestor that is there, each missing
4
+ * segment taken as the entry of its directory equal to it ignoring case,
5
+ * until one has none, which is kept as given with all after it (a file to
6
+ * be made keeps its name). Where two entries or more are equal ignoring
7
+ * case, which one is meant is not guessed: `path` comes back unchanged.
8
+ * Each call lists the directories it needs afresh, as they change; one
9
+ * whose path is there costs one lstat.
10
+ */
11
+ export declare function resolveCase(path: string, caseSensitive?: boolean): string;
12
+ //# sourceMappingURL=case-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"case-paths.d.ts","sourceRoot":"","sources":["../../src/main/case-paths.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,UAAiB,GAAG,MAAM,CAyDhF"}
@@ -0,0 +1,84 @@
1
+ // Local paths as a case-insensitive file system finds them. AIR runs on
2
+ // Windows and macOS, whose file systems ignore case, so an AIR application
3
+ // or a SWF made there may name a file in any case: maps/Town.swf for
4
+ // maps/town.swf. On Linux such a path finds nothing, so where the exact
5
+ // path is missing each missing segment is taken as the one entry of its
6
+ // directory equal to it ignoring case. Names are compared as NFC,
7
+ // lowercased by toLowerCase(): close enough to how NTFS and APFS fold
8
+ // case, and APFS keeps a name's normalization, as NFC compares it.
9
+ // Apart from Electron, so that node tests it (tests/desktop/case-paths.test.ts).
10
+ import { lstatSync, readdirSync } from "node:fs";
11
+ import { isAbsolute, parse, sep } from "node:path";
12
+ /** Whether this system's file system tells names apart by case: Linux's do; Windows' and macOS's do not. */
13
+ const CASE_SENSITIVE = process.platform === "linux";
14
+ /** The directories already said, on stderr, to hold names that differ only in case. */
15
+ const told = new Set();
16
+ const fold = (name) => name.normalize("NFC").toLowerCase();
17
+ function exists(path) {
18
+ try {
19
+ lstatSync(path);
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ /**
27
+ * `path`, absolute, as Windows would find it: unchanged where it is there
28
+ * exactly; otherwise from the deepest ancestor that is there, each missing
29
+ * segment taken as the entry of its directory equal to it ignoring case,
30
+ * until one has none, which is kept as given with all after it (a file to
31
+ * be made keeps its name). Where two entries or more are equal ignoring
32
+ * case, which one is meant is not guessed: `path` comes back unchanged.
33
+ * Each call lists the directories it needs afresh, as they change; one
34
+ * whose path is there costs one lstat.
35
+ */
36
+ export function resolveCase(path, caseSensitive = CASE_SENSITIVE) {
37
+ if (!caseSensitive || !isAbsolute(path) || exists(path)) {
38
+ return path;
39
+ }
40
+ const root = parse(path).root;
41
+ const segments = path.slice(root.length).split(sep);
42
+ // Joined as given, not normalized: ".." is the file system's to follow, through links as today.
43
+ const at = (count, from) => root + from.slice(0, count).join(sep);
44
+ let found = segments.length - 1;
45
+ while (found > 0 && !exists(at(found, segments))) {
46
+ found--;
47
+ }
48
+ const resolved = segments.slice();
49
+ for (let i = found; i < segments.length; i++) {
50
+ const segment = segments[i];
51
+ if (segment === "" || segment === "." || segment === "..") {
52
+ continue;
53
+ }
54
+ const directory = at(i, resolved);
55
+ let names;
56
+ try {
57
+ names = readdirSync(directory);
58
+ }
59
+ catch {
60
+ break;
61
+ }
62
+ // In a directory resolved by case, a segment after it may be there exactly.
63
+ if (names.includes(segment)) {
64
+ continue;
65
+ }
66
+ const wanted = fold(segment);
67
+ const matches = names.filter((name) => fold(name) === wanted);
68
+ if (matches.length === 0) {
69
+ break;
70
+ }
71
+ if (matches.length > 1) {
72
+ const key = `${directory}${sep}${wanted}`;
73
+ if (!told.has(key)) {
74
+ told.add(key);
75
+ console.error(`swf2es: ${directory} holds ${matches.join(", ")}, which differ only in case; ` +
76
+ `${segment} is taken as named, not as any of them.`);
77
+ }
78
+ return path;
79
+ }
80
+ resolved[i] = matches[0];
81
+ }
82
+ return root + resolved.join(sep);
83
+ }
84
+ //# sourceMappingURL=case-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"case-paths.js","sourceRoot":"","sources":["../../src/main/case-paths.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { SocketEvent } from "../shared/api.js";
2
+ import { type ProxyConfig } from "./proxy.ts";
2
3
  /**
3
4
  * The bytes a connection may hold unsent. A peer that stops reading would
4
5
  * otherwise have the main process buffer all a SWF writes: 100 writes of
@@ -8,11 +9,21 @@ import type { SocketEvent } from "../shared/api.js";
8
9
  export declare const MAX_BUFFERED: number;
9
10
  /** Whether the page asked for a host name of DNS's length and a TCP port. */
10
11
  export declare function validEndpoint(host: unknown, port: unknown): host is string;
12
+ export interface ConnectionOptions {
13
+ /** What every connection goes through; none by default. */
14
+ proxy?: ProxyConfig | null;
15
+ /** Told why a connection through the proxy did not come about, for stderr. */
16
+ warn?: (message: string) => void;
17
+ }
11
18
  export declare class Connections {
12
19
  private readonly sockets;
20
+ /** Connections still being made through the proxy, each stopped by its controller. */
21
+ private readonly opening;
13
22
  private readonly tell;
23
+ private readonly proxy;
24
+ private readonly warn;
14
25
  /** `tell` carries each connection's events to its page. */
15
- constructor(tell: (id: number, event: SocketEvent) => void);
26
+ constructor(tell: (id: number, event: SocketEvent) => void, options?: ConnectionOptions);
16
27
  get size(): number;
17
28
  /** Counts closeAll's: a connection decided on before one belongs to a page that is gone. */
18
29
  generation: number;
@@ -21,6 +32,14 @@ export declare class Connections {
21
32
  * was pinned (a remote SWF's socket policy came from there); a refusal is an error, then a close.
22
33
  */
23
34
  connect(id: number, host: unknown, port: unknown, address?: string): void;
35
+ /**
36
+ * Connect `id` through `proxy`, by the address where one was pinned, else
37
+ * by name for the proxy to resolve. Its peer is the target: the proxy's
38
+ * address is no business of the SWF's. A proxy that fails is a refusal,
39
+ * said with why.
40
+ */
41
+ private connectThrough;
42
+ private attach;
24
43
  /**
25
44
  * Write `bytes`, unless the peer has left more than MAX_BUFFERED unread: then the connection
26
45
  * fails.
@@ -1 +1 @@
1
- {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/main/connections.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAKpD;;;;;GAKG;AACH,eAAO,MAAM,YAAY,QAAkB,CAAC;AAI5C,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAU1E;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2C;IAEhE,2DAA2D;IAC3D,YAAY,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,IAAI,EAEzD;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,4FAA4F;IAC5F,UAAU,SAAK;IAEf;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CA2BxE;IAED;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAaxC;IAED,gFAAgF;IAChF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAGvB;IAED,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEtB;IAED;;;OAGG;IACH,QAAQ,IAAI,IAAI,CASf;CACF"}
1
+ {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/main/connections.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAkB,KAAK,WAAW,EAAmB,MAAM,YAAY,CAAC;AAK/E;;;;;GAKG;AACH,eAAO,MAAM,YAAY,QAAkB,CAAC;AAI5C,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAU1E;AAED,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,8EAA8E;IAC9E,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,sFAAsF;IACtF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;IAC9D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2C;IAChE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IAEjD,2DAA2D;IAC3D,YAAY,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,IAAI,EAAE,OAAO,GAAE,iBAAsB,EAI1F;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,4FAA4F;IAC5F,UAAU,SAAK;IAEf;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CA4BxE;IAED;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAgCtB,OAAO,CAAC,MAAM;IAcd;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAaxC;IAED,gFAAgF;IAChF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAGvB;IAED,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAWtB;IAED;;;OAGG;IACH,QAAQ,IAAI,IAAI,CAcf;CACF"}
@@ -1,7 +1,9 @@
1
- // One page's flash.net.Socket connections, made with node:net: what the
2
- // socket bridge (sockets.ts) holds for each page, apart from Electron so
3
- // that node runs it in the tests (tests/desktop/connections.test.ts).
1
+ // One page's flash.net.Socket connections, made with node:net, or through
2
+ // the proxy (--proxy, proxy.ts): what the socket bridge (sockets.ts) holds
3
+ // for each page, apart from Electron so that node runs it in the tests
4
+ // (tests/desktop/connections.test.ts).
4
5
  import { connect } from "node:net";
6
+ import { connectThrough } from "./proxy.js";
5
7
  /** As many as a page may hold open at once; past it a connection is refused. */
6
8
  const MAX_OPEN = 64;
7
9
  /**
@@ -24,13 +26,19 @@ export function validEndpoint(host, port) {
24
26
  }
25
27
  export class Connections {
26
28
  sockets = new Map();
29
+ /** Connections still being made through the proxy, each stopped by its controller. */
30
+ opening = new Map();
27
31
  tell;
32
+ proxy;
33
+ warn;
28
34
  /** `tell` carries each connection's events to its page. */
29
- constructor(tell) {
35
+ constructor(tell, options = {}) {
30
36
  this.tell = tell;
37
+ this.proxy = options.proxy ?? null;
38
+ this.warn = options.warn ?? (() => { });
31
39
  }
32
40
  get size() {
33
- return this.sockets.size;
41
+ return this.sockets.size + this.opening.size;
34
42
  }
35
43
  /** Counts closeAll's: a connection decided on before one belongs to a page that is gone. */
36
44
  generation = 0;
@@ -39,12 +47,19 @@ export class Connections {
39
47
  * was pinned (a remote SWF's socket policy came from there); a refusal is an error, then a close.
40
48
  */
41
49
  connect(id, host, port, address) {
42
- if (!validEndpoint(host, port) || this.sockets.has(id) || this.sockets.size >= MAX_OPEN) {
50
+ if (!validEndpoint(host, port) ||
51
+ this.sockets.has(id) ||
52
+ this.opening.has(id) ||
53
+ this.size >= MAX_OPEN) {
43
54
  this.refuse(id);
44
55
  return;
45
56
  }
46
- const socket = connect({ host: address ?? host, port: port });
47
- this.sockets.set(id, socket);
57
+ const target = address ?? host;
58
+ if (this.proxy) {
59
+ this.connectThrough(this.proxy, id, target, port);
60
+ return;
61
+ }
62
+ const socket = connect({ host: target, port: port });
48
63
  socket.on("connect", () => this.tell(id, {
49
64
  type: "open",
50
65
  localAddress: socket.localAddress ?? "",
@@ -52,6 +67,42 @@ export class Connections {
52
67
  remoteAddress: socket.remoteAddress ?? "",
53
68
  remotePort: socket.remotePort ?? 0,
54
69
  }));
70
+ this.attach(id, socket);
71
+ }
72
+ /**
73
+ * Connect `id` through `proxy`, by the address where one was pinned, else
74
+ * by name for the proxy to resolve. Its peer is the target: the proxy's
75
+ * address is no business of the SWF's. A proxy that fails is a refusal,
76
+ * said with why.
77
+ */
78
+ connectThrough(proxy, id, target, port) {
79
+ const opening = new AbortController();
80
+ this.opening.set(id, opening);
81
+ connectThrough(proxy, target, port, { signal: opening.signal }).then((socket) => {
82
+ if (this.opening.get(id) !== opening) {
83
+ socket.destroy();
84
+ return;
85
+ }
86
+ this.opening.delete(id);
87
+ this.attach(id, socket);
88
+ this.tell(id, {
89
+ type: "open",
90
+ localAddress: socket.localAddress ?? "",
91
+ localPort: socket.localPort ?? 0,
92
+ remoteAddress: target,
93
+ remotePort: port,
94
+ });
95
+ }, (error) => {
96
+ if (this.opening.get(id) !== opening) {
97
+ return;
98
+ }
99
+ this.opening.delete(id);
100
+ this.warn(`no socket to ${target}:${port}: ${error.message}`);
101
+ this.refuse(id);
102
+ });
103
+ }
104
+ attach(id, socket) {
105
+ this.sockets.set(id, socket);
55
106
  socket.on("data", (bytes) => this.tell(id, { type: "data", bytes: new Uint8Array(bytes) }));
56
107
  socket.on("error", () => this.tell(id, { type: "error", message: SOCKET_ERROR }));
57
108
  socket.on("close", () => {
@@ -84,6 +135,14 @@ export class Connections {
84
135
  this.tell(id, { type: "close" });
85
136
  }
86
137
  close(id) {
138
+ const opening = this.opening.get(id);
139
+ if (opening) {
140
+ // Closed before the proxy made it: closed, as a socket destroyed before it connects.
141
+ this.opening.delete(id);
142
+ opening.abort();
143
+ this.tell(id, { type: "close" });
144
+ return;
145
+ }
87
146
  this.sockets.get(id)?.destroy();
88
147
  }
89
148
  /**
@@ -96,7 +155,11 @@ export class Connections {
96
155
  socket.on("error", () => { });
97
156
  socket.destroy();
98
157
  }
158
+ for (const opening of this.opening.values()) {
159
+ opening.abort();
160
+ }
99
161
  this.sockets.clear();
162
+ this.opening.clear();
100
163
  this.generation++;
101
164
  }
102
165
  }