nixamp 0.7.18 → 0.7.19
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.
- package/dist/server.js +11 -4
- package/dist/share.d.ts +13 -2
- package/dist/share.js +14 -3
- package/package.json +1 -1
- package/src/server.ts +11 -4
- package/src/share.ts +15 -4
- package/web/dist/sw.js +1 -1
package/dist/server.js
CHANGED
|
@@ -775,10 +775,17 @@ export function createHandler(engine, options) {
|
|
|
775
775
|
// cookie, so every later fetch, EventSource and <audio src> carries it
|
|
776
776
|
// without the page knowing anything about keys. Either key works here, and
|
|
777
777
|
// which one was used decides what the browser can then do.
|
|
778
|
-
const
|
|
779
|
-
if (
|
|
780
|
-
const offered =
|
|
781
|
-
|
|
778
|
+
const inPath = key !== null ? keyInPath(path) : null;
|
|
779
|
+
if (inPath !== null) {
|
|
780
|
+
const offered = inPath.key;
|
|
781
|
+
// The path has to be telling the truth about the key it carries. A `/v/`
|
|
782
|
+
// link holding the control key would read as view-only to whoever you
|
|
783
|
+
// sent it to and hand them the controls, which is the whole reason for
|
|
784
|
+
// naming the two shapes in the first place.
|
|
785
|
+
//
|
|
786
|
+
// A mismatch answers exactly as a wrong key does, so nothing is learned
|
|
787
|
+
// from the difference between the two.
|
|
788
|
+
if (scopeOf(offered, key, listenKey) !== inPath.wants) {
|
|
782
789
|
json(response, 404, { error: "not found" });
|
|
783
790
|
return;
|
|
784
791
|
}
|
package/dist/share.d.ts
CHANGED
|
@@ -94,8 +94,19 @@ export declare function reachableAddresses(host: string, port: number, publicUrl
|
|
|
94
94
|
* A link should say what it is before anybody clicks it.
|
|
95
95
|
*/
|
|
96
96
|
export declare const KEY_PATHS: readonly ["/a/", "/v/"];
|
|
97
|
-
/**
|
|
98
|
-
|
|
97
|
+
/**
|
|
98
|
+
* The key in a share link, and what the link claimed to be.
|
|
99
|
+
*
|
|
100
|
+
* Both halves, because a label nobody checks is a label that can lie. `/a/`
|
|
101
|
+
* means this administers and `/v/` means this only views; handed the other
|
|
102
|
+
* key, a path would otherwise have said one thing and done the other -- and
|
|
103
|
+
* the dangerous direction is real: a `/v/` link built around the control key
|
|
104
|
+
* reads as view-only to the person you send it to and hands them the controls.
|
|
105
|
+
*/
|
|
106
|
+
export declare function keyInPath(path: string): {
|
|
107
|
+
key: string;
|
|
108
|
+
wants: Scope;
|
|
109
|
+
} | null;
|
|
99
110
|
/** The full link, key and all. `admin` picks the shape that says which it is. */
|
|
100
111
|
export declare function shareLink(base: string, key: string | null, admin?: boolean): string;
|
|
101
112
|
/**
|
package/dist/share.js
CHANGED
|
@@ -251,7 +251,15 @@ export function reachableAddresses(host, port, publicUrl = "", scheme = "http")
|
|
|
251
251
|
* A link should say what it is before anybody clicks it.
|
|
252
252
|
*/
|
|
253
253
|
export const KEY_PATHS = ["/a/", "/v/"];
|
|
254
|
-
/**
|
|
254
|
+
/**
|
|
255
|
+
* The key in a share link, and what the link claimed to be.
|
|
256
|
+
*
|
|
257
|
+
* Both halves, because a label nobody checks is a label that can lie. `/a/`
|
|
258
|
+
* means this administers and `/v/` means this only views; handed the other
|
|
259
|
+
* key, a path would otherwise have said one thing and done the other -- and
|
|
260
|
+
* the dangerous direction is real: a `/v/` link built around the control key
|
|
261
|
+
* reads as view-only to the person you send it to and hands them the controls.
|
|
262
|
+
*/
|
|
255
263
|
export function keyInPath(path) {
|
|
256
264
|
for (const prefix of KEY_PATHS) {
|
|
257
265
|
if (!path.startsWith(prefix))
|
|
@@ -259,12 +267,15 @@ export function keyInPath(path) {
|
|
|
259
267
|
const rest = path.slice(prefix.length).replace(/\/+$/, "");
|
|
260
268
|
if (rest === "" || rest.includes("/"))
|
|
261
269
|
return null;
|
|
270
|
+
let key = rest;
|
|
262
271
|
try {
|
|
263
|
-
|
|
272
|
+
key = decodeURIComponent(rest);
|
|
264
273
|
}
|
|
265
274
|
catch {
|
|
266
|
-
|
|
275
|
+
// A key that is not valid percent-encoding is taken as written; it will
|
|
276
|
+
// fail to match anything, which is the right answer either way.
|
|
267
277
|
}
|
|
278
|
+
return { key, wants: prefix === "/a/" ? "control" : "listen" };
|
|
268
279
|
}
|
|
269
280
|
return null;
|
|
270
281
|
}
|
package/package.json
CHANGED
package/src/server.ts
CHANGED
|
@@ -1074,10 +1074,17 @@ export function createHandler(engine: Engine, options: HandlerOptions) {
|
|
|
1074
1074
|
// cookie, so every later fetch, EventSource and <audio src> carries it
|
|
1075
1075
|
// without the page knowing anything about keys. Either key works here, and
|
|
1076
1076
|
// which one was used decides what the browser can then do.
|
|
1077
|
-
const
|
|
1078
|
-
if (
|
|
1079
|
-
const offered =
|
|
1080
|
-
|
|
1077
|
+
const inPath = key !== null ? keyInPath(path) : null;
|
|
1078
|
+
if (inPath !== null) {
|
|
1079
|
+
const offered = inPath.key;
|
|
1080
|
+
// The path has to be telling the truth about the key it carries. A `/v/`
|
|
1081
|
+
// link holding the control key would read as view-only to whoever you
|
|
1082
|
+
// sent it to and hand them the controls, which is the whole reason for
|
|
1083
|
+
// naming the two shapes in the first place.
|
|
1084
|
+
//
|
|
1085
|
+
// A mismatch answers exactly as a wrong key does, so nothing is learned
|
|
1086
|
+
// from the difference between the two.
|
|
1087
|
+
if (scopeOf(offered, key, listenKey) !== inPath.wants) {
|
|
1081
1088
|
json(response, 404, { error: "not found" });
|
|
1082
1089
|
return;
|
|
1083
1090
|
}
|
package/src/share.ts
CHANGED
|
@@ -282,17 +282,28 @@ export function reachableAddresses(
|
|
|
282
282
|
*/
|
|
283
283
|
export const KEY_PATHS = ["/a/", "/v/"] as const;
|
|
284
284
|
|
|
285
|
-
/**
|
|
286
|
-
|
|
285
|
+
/**
|
|
286
|
+
* The key in a share link, and what the link claimed to be.
|
|
287
|
+
*
|
|
288
|
+
* Both halves, because a label nobody checks is a label that can lie. `/a/`
|
|
289
|
+
* means this administers and `/v/` means this only views; handed the other
|
|
290
|
+
* key, a path would otherwise have said one thing and done the other -- and
|
|
291
|
+
* the dangerous direction is real: a `/v/` link built around the control key
|
|
292
|
+
* reads as view-only to the person you send it to and hands them the controls.
|
|
293
|
+
*/
|
|
294
|
+
export function keyInPath(path: string): { key: string; wants: Scope } | null {
|
|
287
295
|
for (const prefix of KEY_PATHS) {
|
|
288
296
|
if (!path.startsWith(prefix)) continue;
|
|
289
297
|
const rest = path.slice(prefix.length).replace(/\/+$/, "");
|
|
290
298
|
if (rest === "" || rest.includes("/")) return null;
|
|
299
|
+
let key = rest;
|
|
291
300
|
try {
|
|
292
|
-
|
|
301
|
+
key = decodeURIComponent(rest);
|
|
293
302
|
} catch {
|
|
294
|
-
|
|
303
|
+
// A key that is not valid percent-encoding is taken as written; it will
|
|
304
|
+
// fail to match anything, which is the right answer either way.
|
|
295
305
|
}
|
|
306
|
+
return { key, wants: prefix === "/a/" ? "control" : "listen" };
|
|
296
307
|
}
|
|
297
308
|
return null;
|
|
298
309
|
}
|
package/web/dist/sw.js
CHANGED