hbsig 0.0.1
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/cjs/bin_to_str.js +44 -0
- package/cjs/collect-body-keys.js +470 -0
- package/cjs/encode-array-item.js +110 -0
- package/cjs/encode-utils.js +236 -0
- package/cjs/encode.js +1318 -0
- package/cjs/erl_json.js +317 -0
- package/cjs/erl_str.js +1037 -0
- package/cjs/flat.js +222 -0
- package/cjs/http-message-signatures/httpbis.js +489 -0
- package/cjs/http-message-signatures/index.js +25 -0
- package/cjs/http-message-signatures/structured-header.js +129 -0
- package/cjs/httpsig.js +716 -0
- package/cjs/httpsig2.js +1160 -0
- package/cjs/id.js +470 -0
- package/cjs/index.js +63 -0
- package/cjs/send.js +194 -0
- package/cjs/signer-utils.js +617 -0
- package/cjs/signer.js +606 -0
- package/cjs/structured.js +296 -0
- package/cjs/test.js +27 -0
- package/cjs/utils.js +42 -0
- package/esm/bin_to_str.js +46 -0
- package/esm/collect-body-keys.js +436 -0
- package/esm/encode-array-item.js +112 -0
- package/esm/encode-utils.js +185 -0
- package/esm/encode.js +1219 -0
- package/esm/erl_json.js +289 -0
- package/esm/erl_str.js +1139 -0
- package/esm/flat.js +196 -0
- package/esm/http-message-signatures/httpbis.js +438 -0
- package/esm/http-message-signatures/index.js +4 -0
- package/esm/http-message-signatures/structured-header.js +105 -0
- package/esm/httpsig.js +658 -0
- package/esm/httpsig2.js +1097 -0
- package/esm/id.js +459 -0
- package/esm/index.js +4 -0
- package/esm/package.json +3 -0
- package/esm/send.js +124 -0
- package/esm/signer-utils.js +494 -0
- package/esm/signer.js +452 -0
- package/esm/structured.js +269 -0
- package/esm/test.js +6 -0
- package/esm/utils.js +28 -0
- package/package.json +28 -0
package/cjs/httpsig2.js
ADDED
|
@@ -0,0 +1,1160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.verifyContentDigest = exports.toBuffer = exports.hasValidSignature = exports.getSignatureNames = exports.from = exports.extractKeys = void 0;
|
|
7
|
+
var _ramda = require("ramda");
|
|
8
|
+
var _signerUtils = require("./signer-utils.js");
|
|
9
|
+
var _base64url = _interopRequireDefault(require("base64url"));
|
|
10
|
+
var _utils = require("./utils.js");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
12
|
+
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
13
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
14
|
+
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
15
|
+
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
16
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
17
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
18
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
19
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
20
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
21
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
22
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
23
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
24
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
25
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
26
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
27
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
28
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
29
|
+
/**
|
|
30
|
+
* Get multipart boundary from content-type header
|
|
31
|
+
*/
|
|
32
|
+
var getBoundary = function getBoundary(http) {
|
|
33
|
+
var ctype = http.headers["content-type"];
|
|
34
|
+
if (ctype && /^multipart\/form-data;/.test((0, _ramda.trim)(ctype))) {
|
|
35
|
+
var _iterator = _createForOfIteratorHelper((0, _ramda.trim)(ctype).split(";").slice(1)),
|
|
36
|
+
_step;
|
|
37
|
+
try {
|
|
38
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
39
|
+
var v = _step.value;
|
|
40
|
+
var sp2 = v.split("=");
|
|
41
|
+
if ((0, _ramda.trim)(sp2[0]) === "boundary") return (0, _ramda.trim)(sp2[1]).replace(/"/g, "");
|
|
42
|
+
}
|
|
43
|
+
} catch (err) {
|
|
44
|
+
_iterator.e(err);
|
|
45
|
+
} finally {
|
|
46
|
+
_iterator.f();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Extract specified components from HTTP message
|
|
54
|
+
* @param {Object} http - HTTP message object with headers and optional body
|
|
55
|
+
* @param {Array} components - Array of component names to extract
|
|
56
|
+
* @returns {Object} Extracted components with their values
|
|
57
|
+
*/
|
|
58
|
+
var extract = function extract(http, components) {
|
|
59
|
+
var extracted = {};
|
|
60
|
+
var needsBody = components.some(function (c) {
|
|
61
|
+
return c.replace(/"/g, "").toLowerCase() === "content-digest";
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// First extract ao-types if it's signed
|
|
65
|
+
var hasAoTypes = components.some(function (c) {
|
|
66
|
+
return c.replace(/"/g, "").toLowerCase() === "ao-types";
|
|
67
|
+
});
|
|
68
|
+
if (hasAoTypes) {
|
|
69
|
+
var aoTypes = http.headers["ao-types"] || http.headers["Ao-Types"];
|
|
70
|
+
if (aoTypes) {
|
|
71
|
+
extracted["ao-types"] = aoTypes;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Extract ao-ids if it's signed
|
|
76
|
+
var hasAoIds = components.some(function (c) {
|
|
77
|
+
return c.replace(/"/g, "").toLowerCase() === "ao-ids";
|
|
78
|
+
});
|
|
79
|
+
if (hasAoIds) {
|
|
80
|
+
var aoIds = http.headers["ao-ids"] || http.headers["Ao-Ids"];
|
|
81
|
+
if (aoIds) {
|
|
82
|
+
extracted["ao-ids"] = aoIds;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
var _iterator2 = _createForOfIteratorHelper(components),
|
|
86
|
+
_step2;
|
|
87
|
+
try {
|
|
88
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
89
|
+
var component = _step2.value;
|
|
90
|
+
var cleanComponent = component.replace(/"/g, "");
|
|
91
|
+
if (cleanComponent.startsWith("@")) {
|
|
92
|
+
// Handle derived components
|
|
93
|
+
switch (cleanComponent) {
|
|
94
|
+
case "@method":
|
|
95
|
+
extracted[cleanComponent] = http.method || "GET";
|
|
96
|
+
break;
|
|
97
|
+
case "@target-uri":
|
|
98
|
+
extracted[cleanComponent] = http.url || "";
|
|
99
|
+
break;
|
|
100
|
+
case "@authority":
|
|
101
|
+
extracted[cleanComponent] = http.headers.host || "";
|
|
102
|
+
break;
|
|
103
|
+
case "@scheme":
|
|
104
|
+
if (http.url) {
|
|
105
|
+
var url = new URL(http.url);
|
|
106
|
+
extracted[cleanComponent] = url.protocol.replace(":", "");
|
|
107
|
+
}
|
|
108
|
+
break;
|
|
109
|
+
case "@request-target":
|
|
110
|
+
if (http.url) {
|
|
111
|
+
var _url = new URL(http.url);
|
|
112
|
+
extracted[cleanComponent] = _url.pathname + _url.search;
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
case "@path":
|
|
116
|
+
if (http.url) {
|
|
117
|
+
var _url2 = new URL(http.url);
|
|
118
|
+
extracted[cleanComponent] = _url2.pathname;
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
case "@query":
|
|
122
|
+
if (http.url) {
|
|
123
|
+
var _url3 = new URL(http.url);
|
|
124
|
+
extracted[cleanComponent] = _url3.search;
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
case "@status":
|
|
128
|
+
extracted[cleanComponent] = String(http.status || http["@status"] || "");
|
|
129
|
+
break;
|
|
130
|
+
case "@query-param":
|
|
131
|
+
// This would need additional parsing logic for specific query parameters
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
// Handle regular headers - try both exact case and lowercase
|
|
136
|
+
var headerValue = http.headers[cleanComponent] || http.headers[cleanComponent.toLowerCase()];
|
|
137
|
+
if (headerValue !== null && headerValue !== undefined) {
|
|
138
|
+
extracted[cleanComponent] = headerValue;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// If content-digest is signed, we need to include the body
|
|
144
|
+
} catch (err) {
|
|
145
|
+
_iterator2.e(err);
|
|
146
|
+
} finally {
|
|
147
|
+
_iterator2.f();
|
|
148
|
+
}
|
|
149
|
+
if (needsBody && http.body !== undefined) {
|
|
150
|
+
extracted["body"] = http.body;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Add flag if body is needed but missing
|
|
154
|
+
if (needsBody && http.body === undefined) {
|
|
155
|
+
extracted["__bodyRequired__"] = true;
|
|
156
|
+
}
|
|
157
|
+
return extracted;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Convert body to Buffer from various sources
|
|
162
|
+
* @param {string|Buffer|ArrayBuffer} body - The body to convert
|
|
163
|
+
* @returns {Buffer} The body as a Buffer
|
|
164
|
+
*/
|
|
165
|
+
var toBuffer = exports.toBuffer = function toBuffer(body) {
|
|
166
|
+
if (!body) {
|
|
167
|
+
return Buffer.alloc(0);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// If it's already a Buffer, return it
|
|
171
|
+
if (Buffer.isBuffer(body)) {
|
|
172
|
+
return body;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// If it's a string, convert to Buffer
|
|
176
|
+
if (typeof body === "string") {
|
|
177
|
+
return Buffer.from(body, "utf-8");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// If it's an ArrayBuffer or TypedArray
|
|
181
|
+
if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {
|
|
182
|
+
return Buffer.from(body);
|
|
183
|
+
}
|
|
184
|
+
throw new Error("Unsupported body type");
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Parse ao-ids dictionary
|
|
189
|
+
* @param {string} aoIds - The ao-ids header value
|
|
190
|
+
* @returns {Object} Parsed ID mappings
|
|
191
|
+
*/
|
|
192
|
+
var parseAoIds = function parseAoIds(aoIds) {
|
|
193
|
+
var result = {};
|
|
194
|
+
|
|
195
|
+
// Match pattern: ID="value"
|
|
196
|
+
var regex = /([A-Za-z0-9_-]{43})="([^"]*)"/g;
|
|
197
|
+
var match;
|
|
198
|
+
while ((match = regex.exec(aoIds)) !== null) {
|
|
199
|
+
var _match = match,
|
|
200
|
+
_match2 = _slicedToArray(_match, 3),
|
|
201
|
+
id = _match2[1],
|
|
202
|
+
value = _match2[2];
|
|
203
|
+
result[id] = value;
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Convert message to JSON with proper type conversions
|
|
210
|
+
* Following the logic from dev_codec_structured, dev_codec_httpsig_conv, and dev_codec_flat
|
|
211
|
+
* @param {Object} msg - The message to convert
|
|
212
|
+
* @returns {Object} JSON representation
|
|
213
|
+
*/
|
|
214
|
+
var _toJSON = function toJSON(msg) {
|
|
215
|
+
if (!msg || _typeof(msg) !== "object") {
|
|
216
|
+
return msg;
|
|
217
|
+
}
|
|
218
|
+
var result = _objectSpread({}, msg);
|
|
219
|
+
|
|
220
|
+
// Handle ao-ids parsing
|
|
221
|
+
if (result["ao-ids"]) {
|
|
222
|
+
var parsedIds = parseAoIds(result["ao-ids"]);
|
|
223
|
+
// Remove the ao-ids header and merge the parsed IDs
|
|
224
|
+
delete result["ao-ids"];
|
|
225
|
+
result = _objectSpread(_objectSpread({}, result), parsedIds);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// First, handle the multipart body if present
|
|
229
|
+
var contentType = result["content-type"];
|
|
230
|
+
var body = result.body;
|
|
231
|
+
if (body && contentType && contentType.includes("multipart/form-data")) {
|
|
232
|
+
var boundary = getBoundary({
|
|
233
|
+
headers: {
|
|
234
|
+
"content-type": contentType
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
if (boundary) {
|
|
238
|
+
// Parse multipart body
|
|
239
|
+
var parts = parseMultipartBody(body, boundary);
|
|
240
|
+
|
|
241
|
+
// Remove the raw body since we've parsed it
|
|
242
|
+
delete result.body;
|
|
243
|
+
|
|
244
|
+
// Merge parsed parts into result
|
|
245
|
+
for (var _i = 0, _Object$entries = Object.entries(parts); _i < _Object$entries.length; _i++) {
|
|
246
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
247
|
+
partName = _Object$entries$_i[0],
|
|
248
|
+
partData = _Object$entries$_i[1];
|
|
249
|
+
// Parse ao-types from part data if present
|
|
250
|
+
var partTypes = {};
|
|
251
|
+
if (partData["ao-types"]) {
|
|
252
|
+
// Updated regex to handle spaces and trim the key
|
|
253
|
+
var matches = _toConsumableArray(partData["ao-types"].matchAll(/([^=,]+)="([^"]+)"/g));
|
|
254
|
+
var _iterator3 = _createForOfIteratorHelper(matches),
|
|
255
|
+
_step3;
|
|
256
|
+
try {
|
|
257
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
258
|
+
var _step3$value = _slicedToArray(_step3.value, 3),
|
|
259
|
+
_ = _step3$value[0],
|
|
260
|
+
key = _step3$value[1],
|
|
261
|
+
type = _step3$value[2];
|
|
262
|
+
partTypes[key.trim()] = type;
|
|
263
|
+
}
|
|
264
|
+
} catch (err) {
|
|
265
|
+
_iterator3.e(err);
|
|
266
|
+
} finally {
|
|
267
|
+
_iterator3.f();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Apply type conversions to part data
|
|
272
|
+
var convertedPartData = {};
|
|
273
|
+
for (var _i2 = 0, _Object$entries2 = Object.entries(partData); _i2 < _Object$entries2.length; _i2++) {
|
|
274
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
275
|
+
_key = _Object$entries2$_i[0],
|
|
276
|
+
value = _Object$entries2$_i[1];
|
|
277
|
+
if (_key === "ao-types" || _key === "content-disposition") continue;
|
|
278
|
+
var _type = partTypes[_key];
|
|
279
|
+
if (_type && typeof value === "string") {
|
|
280
|
+
convertedPartData[_key] = convertByType(value, _type);
|
|
281
|
+
} else {
|
|
282
|
+
convertedPartData[_key] = value;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Store the result
|
|
287
|
+
if (Object.keys(convertedPartData).length > 0) {
|
|
288
|
+
// Check if the part name suggests it's an array element (ends with /number)
|
|
289
|
+
var isArrayElement = /\/\d+$/.test(partName);
|
|
290
|
+
|
|
291
|
+
// For top-level parts (no slash in name) with objects, keep the structure
|
|
292
|
+
var isTopLevel = !partName.includes("/");
|
|
293
|
+
|
|
294
|
+
// Check if this is a nested path that will be unflattened
|
|
295
|
+
var isNestedPath = partName.includes("/") && !isArrayElement;
|
|
296
|
+
if (isArrayElement || isNestedPath) {
|
|
297
|
+
// Array elements and nested paths keep their structure
|
|
298
|
+
result[partName] = convertedPartData;
|
|
299
|
+
} else if (isTopLevel || Object.keys(convertedPartData).length > 1) {
|
|
300
|
+
// Top-level objects or multi-field objects keep their structure
|
|
301
|
+
result[partName] = convertedPartData;
|
|
302
|
+
} else {
|
|
303
|
+
// Only lift single values for simple cases
|
|
304
|
+
result[partName] = convertedPartData[Object.keys(convertedPartData)[0]];
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Store type information for nested fields
|
|
309
|
+
if (Object.keys(partTypes).length > 0) {
|
|
310
|
+
for (var _i3 = 0, _Object$entries3 = Object.entries(partTypes); _i3 < _Object$entries3.length; _i3++) {
|
|
311
|
+
var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i3], 2),
|
|
312
|
+
fieldKey = _Object$entries3$_i[0],
|
|
313
|
+
fieldType = _Object$entries3$_i[1];
|
|
314
|
+
if (fieldKey !== "ao-types" && fieldKey !== "content-disposition") {
|
|
315
|
+
// Add to global typeMap with the full path
|
|
316
|
+
var fullPath = partName + "/" + fieldKey;
|
|
317
|
+
// Store in the ao-types for later use
|
|
318
|
+
if (!result["__typeMap"]) result["__typeMap"] = {};
|
|
319
|
+
result["__typeMap"][fullPath] = fieldType;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Parse global ao-types to get type information
|
|
328
|
+
var typeMap = {};
|
|
329
|
+
if (result["ao-types"]) {
|
|
330
|
+
// Updated regex to handle spaces and trim the key
|
|
331
|
+
var _matches = _toConsumableArray(result["ao-types"].matchAll(/([^=,]+)="([^"]+)"/g));
|
|
332
|
+
var _iterator4 = _createForOfIteratorHelper(_matches),
|
|
333
|
+
_step4;
|
|
334
|
+
try {
|
|
335
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
336
|
+
var _step4$value = _slicedToArray(_step4.value, 3),
|
|
337
|
+
_2 = _step4$value[0],
|
|
338
|
+
_key2 = _step4$value[1],
|
|
339
|
+
_type2 = _step4$value[2];
|
|
340
|
+
typeMap[_key2.trim()] = _type2;
|
|
341
|
+
}
|
|
342
|
+
} catch (err) {
|
|
343
|
+
_iterator4.e(err);
|
|
344
|
+
} finally {
|
|
345
|
+
_iterator4.f();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Merge in types from multipart parsing
|
|
350
|
+
if (result["__typeMap"]) {
|
|
351
|
+
Object.assign(typeMap, result["__typeMap"]);
|
|
352
|
+
delete result["__typeMap"];
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Also collect types from multipart parts for nested fields
|
|
356
|
+
for (var _i4 = 0, _Object$entries4 = Object.entries(result); _i4 < _Object$entries4.length; _i4++) {
|
|
357
|
+
var _Object$entries4$_i = _slicedToArray(_Object$entries4[_i4], 2),
|
|
358
|
+
_key3 = _Object$entries4$_i[0],
|
|
359
|
+
_value = _Object$entries4$_i[1];
|
|
360
|
+
if (_key3.includes("/") && _typeof(_value) === "object" && _value !== null && _value.__partTypes) {
|
|
361
|
+
// This is a multipart part with type information
|
|
362
|
+
for (var _i5 = 0, _Object$entries5 = Object.entries(_value.__partTypes); _i5 < _Object$entries5.length; _i5++) {
|
|
363
|
+
var _Object$entries5$_i = _slicedToArray(_Object$entries5[_i5], 2),
|
|
364
|
+
_fieldKey = _Object$entries5$_i[0],
|
|
365
|
+
_fieldType = _Object$entries5$_i[1];
|
|
366
|
+
// Create the full path for the type
|
|
367
|
+
var _fullPath = "".concat(_key3, "/").concat(_fieldKey);
|
|
368
|
+
typeMap[_fullPath] = _fieldType;
|
|
369
|
+
}
|
|
370
|
+
// Remove the __partTypes after processing
|
|
371
|
+
delete _value.__partTypes;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Add empty values for fields that are in ao-types but not in result
|
|
376
|
+
for (var _i6 = 0, _Object$entries6 = Object.entries(typeMap); _i6 < _Object$entries6.length; _i6++) {
|
|
377
|
+
var _Object$entries6$_i = _slicedToArray(_Object$entries6[_i6], 2),
|
|
378
|
+
_key4 = _Object$entries6$_i[0],
|
|
379
|
+
_type3 = _Object$entries6$_i[1];
|
|
380
|
+
if (!(_key4 in result) && _type3.startsWith("empty-")) {
|
|
381
|
+
result[_key4] = convertByType("", _type3);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Apply type conversions and build final result
|
|
386
|
+
var finalResult = {};
|
|
387
|
+
for (var _i7 = 0, _Object$entries7 = Object.entries(result); _i7 < _Object$entries7.length; _i7++) {
|
|
388
|
+
var _Object$entries7$_i = _slicedToArray(_Object$entries7[_i7], 2),
|
|
389
|
+
_key5 = _Object$entries7$_i[0],
|
|
390
|
+
_value2 = _Object$entries7$_i[1];
|
|
391
|
+
// Skip internal keys and headers we don't want in the final result
|
|
392
|
+
if (_key5.startsWith("__")) continue;
|
|
393
|
+
|
|
394
|
+
// Skip @ fields EXCEPT @path which we want to include
|
|
395
|
+
if (_key5.startsWith("@") && _key5 !== "@path") continue;
|
|
396
|
+
if (_key5 === "ao-types") continue;
|
|
397
|
+
if (_key5 === "content-type") continue;
|
|
398
|
+
if (_key5 === "content-digest") continue;
|
|
399
|
+
if (_key5 === "signature") continue;
|
|
400
|
+
if (_key5 === "signature-input") continue;
|
|
401
|
+
if (_key5 === "body-keys") continue;
|
|
402
|
+
|
|
403
|
+
// Get the type for this key
|
|
404
|
+
var _type4 = typeMap[_key5];
|
|
405
|
+
|
|
406
|
+
// Special handling for objects that should be lists
|
|
407
|
+
if (_type4 === "list" && _typeof(_value2) === "object" && _value2 !== null && !Array.isArray(_value2)) {
|
|
408
|
+
// This is an object that should be converted to a list
|
|
409
|
+
var converted = maybeConvertToArray(_value2);
|
|
410
|
+
finalResult[_key5] = converted;
|
|
411
|
+
} else if (_type4 && typeof _value2 === "string") {
|
|
412
|
+
// Convert based on type
|
|
413
|
+
finalResult[_key5] = convertByType(_value2, _type4);
|
|
414
|
+
} else if (_type4 && _value2 === undefined) {
|
|
415
|
+
// Handle empty types
|
|
416
|
+
finalResult[_key5] = convertByType("", _type4);
|
|
417
|
+
} else if (_typeof(_value2) === "object" && _value2 !== null && !Array.isArray(_value2)) {
|
|
418
|
+
// For objects without a specific type, keep them as objects
|
|
419
|
+
// Only recurse for processing nested values
|
|
420
|
+
var processedObj = {};
|
|
421
|
+
for (var _i8 = 0, _Object$entries8 = Object.entries(_value2); _i8 < _Object$entries8.length; _i8++) {
|
|
422
|
+
var _Object$entries8$_i = _slicedToArray(_Object$entries8[_i8], 2),
|
|
423
|
+
k = _Object$entries8$_i[0],
|
|
424
|
+
v = _Object$entries8$_i[1];
|
|
425
|
+
if (Array.isArray(v)) {
|
|
426
|
+
// Keep arrays as arrays
|
|
427
|
+
processedObj[k] = v;
|
|
428
|
+
} else if (_typeof(v) === "object" && v !== null) {
|
|
429
|
+
processedObj[k] = _toJSON(v);
|
|
430
|
+
} else {
|
|
431
|
+
processedObj[k] = v;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
finalResult[_key5] = processedObj;
|
|
435
|
+
} else {
|
|
436
|
+
// Keep as-is (including arrays)
|
|
437
|
+
finalResult[_key5] = _value2;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Handle flattened paths - pass typeMap for context
|
|
442
|
+
return unflattenPaths(finalResult, typeMap);
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Convert objects with numeric keys to arrays
|
|
447
|
+
*/
|
|
448
|
+
var maybeConvertToArray = function maybeConvertToArray(obj) {
|
|
449
|
+
if (Array.isArray(obj)) return obj;
|
|
450
|
+
var keys = Object.keys(obj);
|
|
451
|
+
var numericKeys = keys.filter(function (k) {
|
|
452
|
+
return /^\d+$/.test(k);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// If all keys are numeric and sequential starting from 1
|
|
456
|
+
if (numericKeys.length > 0 && numericKeys.length === keys.length) {
|
|
457
|
+
var sortedNumericKeys = numericKeys.map(Number).sort(function (a, b) {
|
|
458
|
+
return a - b;
|
|
459
|
+
});
|
|
460
|
+
var maxIndex = Math.max.apply(Math, _toConsumableArray(sortedNumericKeys));
|
|
461
|
+
var arr = [];
|
|
462
|
+
|
|
463
|
+
// Fill array based on numeric keys (1-based to 0-based)
|
|
464
|
+
for (var i = 1; i <= maxIndex; i++) {
|
|
465
|
+
if (obj[String(i)] !== undefined) {
|
|
466
|
+
arr[i - 1] = obj[String(i)];
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return arr;
|
|
470
|
+
}
|
|
471
|
+
return obj;
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Convert value based on its type
|
|
476
|
+
*/
|
|
477
|
+
var convertByType = function convertByType(value, type) {
|
|
478
|
+
switch (type) {
|
|
479
|
+
case "integer":
|
|
480
|
+
// Handle structured field integer format
|
|
481
|
+
if (typeof value === "string" && value.match(/^"?\(ao-type-integer\)\s+(\d+)"?$/)) {
|
|
482
|
+
var match = value.match(/(\d+)/);
|
|
483
|
+
return parseInt(match[1], 10);
|
|
484
|
+
}
|
|
485
|
+
return parseInt(value, 10);
|
|
486
|
+
case "float":
|
|
487
|
+
case "decimal":
|
|
488
|
+
return parseFloat(value);
|
|
489
|
+
case "boolean":
|
|
490
|
+
return value === "true" || value === "?1";
|
|
491
|
+
case "atom":
|
|
492
|
+
// Remove quotes from atom values
|
|
493
|
+
var atomValue = value;
|
|
494
|
+
|
|
495
|
+
// Remove any surrounding quotes (single or double)
|
|
496
|
+
if (atomValue.startsWith('"') && atomValue.endsWith('"') || atomValue.startsWith("'") && atomValue.endsWith("'")) {
|
|
497
|
+
atomValue = atomValue.slice(1, -1);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Also handle escaped quotes
|
|
501
|
+
atomValue = atomValue.replace(/\\"/g, '"').replace(/\\'/g, "'");
|
|
502
|
+
|
|
503
|
+
// Handle special atom values
|
|
504
|
+
if (atomValue === "true") return true;
|
|
505
|
+
if (atomValue === "false") return false;
|
|
506
|
+
if (atomValue === "null") return null;
|
|
507
|
+
|
|
508
|
+
// For other atoms, return as Symbol
|
|
509
|
+
return Symbol["for"](atomValue);
|
|
510
|
+
case "list":
|
|
511
|
+
// Handle case where list is a comma-separated string
|
|
512
|
+
if (typeof value === "string" && !value.startsWith("(")) {
|
|
513
|
+
var items = [];
|
|
514
|
+
var current = "";
|
|
515
|
+
var inQuotes = false;
|
|
516
|
+
var depth = 0;
|
|
517
|
+
for (var i = 0; i < value.length; i++) {
|
|
518
|
+
var _char = value[i];
|
|
519
|
+
var prevChar = value[i - 1];
|
|
520
|
+
if (_char === '"' && prevChar !== "\\") {
|
|
521
|
+
inQuotes = !inQuotes;
|
|
522
|
+
}
|
|
523
|
+
if (!inQuotes) {
|
|
524
|
+
if (_char === "(") {
|
|
525
|
+
depth++;
|
|
526
|
+
} else if (_char === ")") {
|
|
527
|
+
depth--;
|
|
528
|
+
} else if (_char === "," && depth === 0) {
|
|
529
|
+
if (current.trim()) {
|
|
530
|
+
// Parse the item to handle type annotations
|
|
531
|
+
items.push(parseStructuredItem(current.trim()));
|
|
532
|
+
}
|
|
533
|
+
current = "";
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
current += _char;
|
|
538
|
+
}
|
|
539
|
+
if (current.trim()) {
|
|
540
|
+
items.push(parseStructuredItem(current.trim()));
|
|
541
|
+
}
|
|
542
|
+
return items;
|
|
543
|
+
}
|
|
544
|
+
return parseStructuredList(value);
|
|
545
|
+
case "map":
|
|
546
|
+
case "dictionary":
|
|
547
|
+
return parseStructuredDict(value);
|
|
548
|
+
case "empty-binary":
|
|
549
|
+
return "";
|
|
550
|
+
case "empty-list":
|
|
551
|
+
return [];
|
|
552
|
+
case "empty-message":
|
|
553
|
+
return {};
|
|
554
|
+
default:
|
|
555
|
+
return value;
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Parse structured field list
|
|
561
|
+
*/
|
|
562
|
+
var parseStructuredList = function parseStructuredList(value) {
|
|
563
|
+
if (!value || value === "()") return [];
|
|
564
|
+
|
|
565
|
+
// Remove outer quotes if present
|
|
566
|
+
var content = value.trim();
|
|
567
|
+
if (content.startsWith('"') && content.endsWith('"')) {
|
|
568
|
+
content = content.slice(1, -1);
|
|
569
|
+
}
|
|
570
|
+
var items = [];
|
|
571
|
+
var current = "";
|
|
572
|
+
var inQuotes = false;
|
|
573
|
+
var depth = 0;
|
|
574
|
+
for (var i = 0; i < content.length; i++) {
|
|
575
|
+
var _char2 = content[i];
|
|
576
|
+
var prevChar = content[i - 1];
|
|
577
|
+
if (_char2 === '"' && prevChar !== "\\") {
|
|
578
|
+
inQuotes = !inQuotes;
|
|
579
|
+
current += _char2;
|
|
580
|
+
} else if (!inQuotes) {
|
|
581
|
+
if (_char2 === "(") {
|
|
582
|
+
depth++;
|
|
583
|
+
current += _char2;
|
|
584
|
+
} else if (_char2 === ")") {
|
|
585
|
+
depth--;
|
|
586
|
+
current += _char2;
|
|
587
|
+
} else if (_char2 === "," && depth === 0) {
|
|
588
|
+
if (current.trim()) {
|
|
589
|
+
items.push(parseStructuredItem(current.trim()));
|
|
590
|
+
}
|
|
591
|
+
current = "";
|
|
592
|
+
} else {
|
|
593
|
+
current += _char2;
|
|
594
|
+
}
|
|
595
|
+
} else {
|
|
596
|
+
current += _char2;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
if (current.trim()) {
|
|
600
|
+
items.push(parseStructuredItem(current.trim()));
|
|
601
|
+
}
|
|
602
|
+
return items;
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Parse structured field item
|
|
607
|
+
*/
|
|
608
|
+
var parseStructuredItem = function parseStructuredItem(item) {
|
|
609
|
+
// Quoted string - handle first to properly process inner content
|
|
610
|
+
if (item.startsWith('"') && item.endsWith('"')) {
|
|
611
|
+
var inner = item.slice(1, -1).replace(/\\"/g, '"');
|
|
612
|
+
|
|
613
|
+
// Check if the inner content is ao-type encoded
|
|
614
|
+
var innerAoTypeMatch = inner.match(/^\(ao-type-(\w+)\)\s+(.+)$/);
|
|
615
|
+
if (innerAoTypeMatch) {
|
|
616
|
+
var _innerAoTypeMatch = _slicedToArray(innerAoTypeMatch, 3),
|
|
617
|
+
type = _innerAoTypeMatch[1],
|
|
618
|
+
value = _innerAoTypeMatch[2];
|
|
619
|
+
// The value here has already had escaped quotes converted to real quotes
|
|
620
|
+
// If it's wrapped in quotes, remove them
|
|
621
|
+
var cleanValue = value;
|
|
622
|
+
if (cleanValue.startsWith('"') && cleanValue.endsWith('"') || cleanValue.startsWith("'") && cleanValue.endsWith("'")) {
|
|
623
|
+
cleanValue = cleanValue.slice(1, -1);
|
|
624
|
+
}
|
|
625
|
+
return convertByType(cleanValue, type);
|
|
626
|
+
}
|
|
627
|
+
return inner;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// Handle ao-type encoded items without outer quotes
|
|
631
|
+
var aoTypeMatch = item.match(/^\(ao-type-(\w+)\)\s+(.+)$/);
|
|
632
|
+
if (aoTypeMatch) {
|
|
633
|
+
var _aoTypeMatch = _slicedToArray(aoTypeMatch, 3),
|
|
634
|
+
_type5 = _aoTypeMatch[1],
|
|
635
|
+
_value3 = _aoTypeMatch[2];
|
|
636
|
+
var _cleanValue = _value3;
|
|
637
|
+
// Handle escaped quotes
|
|
638
|
+
_cleanValue = _cleanValue.replace(/\\"/g, '"');
|
|
639
|
+
// If wrapped in quotes, remove them
|
|
640
|
+
if (_cleanValue.startsWith('"') && _cleanValue.endsWith('"') || _cleanValue.startsWith("'") && _cleanValue.endsWith("'")) {
|
|
641
|
+
_cleanValue = _cleanValue.slice(1, -1);
|
|
642
|
+
}
|
|
643
|
+
return convertByType(_cleanValue, _type5);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Boolean
|
|
647
|
+
if (item === "?1") return true;
|
|
648
|
+
if (item === "?0") return false;
|
|
649
|
+
|
|
650
|
+
// Number
|
|
651
|
+
if (/^-?\d+$/.test(item)) {
|
|
652
|
+
return parseInt(item, 10);
|
|
653
|
+
}
|
|
654
|
+
if (/^-?\d+\.\d+$/.test(item)) {
|
|
655
|
+
return parseFloat(item);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Nested list
|
|
659
|
+
if (item.startsWith("(") && item.endsWith(")")) {
|
|
660
|
+
return parseStructuredList(item);
|
|
661
|
+
}
|
|
662
|
+
return item;
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Parse structured field dictionary
|
|
667
|
+
*/
|
|
668
|
+
var parseStructuredDict = function parseStructuredDict(value) {
|
|
669
|
+
var decoded = (0, _signerUtils.decodeSigInput)(value);
|
|
670
|
+
var result = {};
|
|
671
|
+
for (var _i9 = 0, _Object$entries9 = Object.entries(decoded); _i9 < _Object$entries9.length; _i9++) {
|
|
672
|
+
var _Object$entries9$_i = _slicedToArray(_Object$entries9[_i9], 2),
|
|
673
|
+
key = _Object$entries9$_i[0],
|
|
674
|
+
info = _Object$entries9$_i[1];
|
|
675
|
+
if (info && info.components && info.components.length > 0) {
|
|
676
|
+
result[key] = parseStructuredItem(info.components[0]);
|
|
677
|
+
} else {
|
|
678
|
+
result[key] = true;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return result;
|
|
682
|
+
};
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Parse body-keys list
|
|
686
|
+
*/
|
|
687
|
+
var parseBodyKeysList = function parseBodyKeysList(value) {
|
|
688
|
+
var matches = _toConsumableArray(value.matchAll(/"([^"]+)"/g));
|
|
689
|
+
return matches.map(function (m) {
|
|
690
|
+
return m[1];
|
|
691
|
+
});
|
|
692
|
+
};
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Parse multipart body
|
|
696
|
+
*/
|
|
697
|
+
var parseMultipartBody = function parseMultipartBody(body, boundary) {
|
|
698
|
+
var result = {};
|
|
699
|
+
|
|
700
|
+
// Split by boundary lines
|
|
701
|
+
var parts = body.split("--".concat(boundary));
|
|
702
|
+
for (var i = 0; i < parts.length; i++) {
|
|
703
|
+
var part = parts[i];
|
|
704
|
+
|
|
705
|
+
// Skip empty parts and the terminating part
|
|
706
|
+
if (!part || part === "--" || part === "--\r\n" || part.trim() === "") continue;
|
|
707
|
+
|
|
708
|
+
// Remove leading \r\n if present
|
|
709
|
+
var content = part;
|
|
710
|
+
if (content.startsWith("\r\n")) {
|
|
711
|
+
content = content.substring(2);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// Remove trailing \r\n or -- if present
|
|
715
|
+
if (content.endsWith("\r\n")) {
|
|
716
|
+
content = content.substring(0, content.length - 2);
|
|
717
|
+
}
|
|
718
|
+
if (!content) continue;
|
|
719
|
+
|
|
720
|
+
// Parse all lines
|
|
721
|
+
var lines = content.split("\r\n");
|
|
722
|
+
var partData = {};
|
|
723
|
+
var partName = null;
|
|
724
|
+
var _iterator5 = _createForOfIteratorHelper(lines),
|
|
725
|
+
_step5;
|
|
726
|
+
try {
|
|
727
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
728
|
+
var line = _step5.value;
|
|
729
|
+
if (!line) continue;
|
|
730
|
+
var colonIndex = line.indexOf(": ");
|
|
731
|
+
if (colonIndex > -1) {
|
|
732
|
+
var name = line.substring(0, colonIndex);
|
|
733
|
+
var value = line.substring(colonIndex + 2);
|
|
734
|
+
|
|
735
|
+
// Check if this is content-disposition to extract part name
|
|
736
|
+
if (name.toLowerCase() === "content-disposition") {
|
|
737
|
+
var nameMatch = value.match(/name="([^"]+)"/);
|
|
738
|
+
if (nameMatch) {
|
|
739
|
+
partName = nameMatch[1];
|
|
740
|
+
}
|
|
741
|
+
} else {
|
|
742
|
+
// Store all other headers/fields
|
|
743
|
+
partData[name] = value;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Store the part data under its name
|
|
749
|
+
} catch (err) {
|
|
750
|
+
_iterator5.e(err);
|
|
751
|
+
} finally {
|
|
752
|
+
_iterator5.f();
|
|
753
|
+
}
|
|
754
|
+
if (partName && Object.keys(partData).length > 0) {
|
|
755
|
+
result[partName] = partData;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return result;
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Unflatten paths with '/'
|
|
763
|
+
*/
|
|
764
|
+
var unflattenPaths = function unflattenPaths(obj) {
|
|
765
|
+
var typeMap = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
766
|
+
var result = {};
|
|
767
|
+
|
|
768
|
+
// Check if there are any paths to unflatten
|
|
769
|
+
var hasPathsToUnflatten = Object.keys(obj).some(function (key) {
|
|
770
|
+
return key.includes("/");
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
// If no paths to unflatten, return the object as-is
|
|
774
|
+
if (!hasPathsToUnflatten) {
|
|
775
|
+
return obj;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// First pass: collect all keys and sort them to process parents before children
|
|
779
|
+
var sortedKeys = Object.keys(obj).sort();
|
|
780
|
+
var _iterator6 = _createForOfIteratorHelper(sortedKeys),
|
|
781
|
+
_step6;
|
|
782
|
+
try {
|
|
783
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
784
|
+
var key = _step6.value;
|
|
785
|
+
var value = obj[key];
|
|
786
|
+
if (key.includes("/")) {
|
|
787
|
+
var parts = key.split("/");
|
|
788
|
+
var current = result;
|
|
789
|
+
var i = 0;
|
|
790
|
+
while (i < parts.length - 1) {
|
|
791
|
+
var part = parts[i];
|
|
792
|
+
|
|
793
|
+
// Check if we have consecutive empty parts (multiple slashes)
|
|
794
|
+
if (part === "" && i + 1 < parts.length && parts[i + 1] === "") {
|
|
795
|
+
// Skip empty parts until we find a non-empty one or reach the end
|
|
796
|
+
var j = i;
|
|
797
|
+
while (j < parts.length && parts[j] === "") {
|
|
798
|
+
j++;
|
|
799
|
+
}
|
|
800
|
+
// Use "/" as the key for multiple slashes
|
|
801
|
+
part = "/";
|
|
802
|
+
i = j - 1; // Will be incremented at the end of loop
|
|
803
|
+
} else if (part === "") {
|
|
804
|
+
// Single empty part at the beginning or middle, skip it
|
|
805
|
+
i++;
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
if (!current[part]) {
|
|
809
|
+
current[part] = {};
|
|
810
|
+
}
|
|
811
|
+
current = current[part];
|
|
812
|
+
i++;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// Handle the final part
|
|
816
|
+
var finalPart = parts[parts.length - 1];
|
|
817
|
+
current[finalPart] = value;
|
|
818
|
+
} else {
|
|
819
|
+
result[key] = value;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Second pass: convert objects with numeric keys to arrays only if they have type="list"
|
|
824
|
+
} catch (err) {
|
|
825
|
+
_iterator6.e(err);
|
|
826
|
+
} finally {
|
|
827
|
+
_iterator6.f();
|
|
828
|
+
}
|
|
829
|
+
var _convertToArraysRecursive = function convertToArraysRecursive(obj) {
|
|
830
|
+
var parentKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
|
|
831
|
+
if (Array.isArray(obj)) {
|
|
832
|
+
return obj.map(function (item, index) {
|
|
833
|
+
return _convertToArraysRecursive(item, "".concat(parentKey, "/").concat(index + 1));
|
|
834
|
+
});
|
|
835
|
+
} else if (obj && _typeof(obj) === "object") {
|
|
836
|
+
// Check if this object has type="list" in typeMap
|
|
837
|
+
var hasListType = typeMap[parentKey] === "list";
|
|
838
|
+
|
|
839
|
+
// Only convert to array if it has numeric keys AND type="list"
|
|
840
|
+
if (hasListType) {
|
|
841
|
+
var converted = maybeConvertToArray(obj);
|
|
842
|
+
if (Array.isArray(converted)) {
|
|
843
|
+
return converted.map(function (item, index) {
|
|
844
|
+
return _convertToArraysRecursive(item, "".concat(parentKey, "/").concat(index + 1));
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
// Otherwise, keep as object and recurse
|
|
850
|
+
var _result = {};
|
|
851
|
+
for (var _i0 = 0, _Object$entries0 = Object.entries(obj); _i0 < _Object$entries0.length; _i0++) {
|
|
852
|
+
var _Object$entries0$_i = _slicedToArray(_Object$entries0[_i0], 2),
|
|
853
|
+
key = _Object$entries0$_i[0],
|
|
854
|
+
value = _Object$entries0$_i[1];
|
|
855
|
+
var childKey = parentKey ? "".concat(parentKey, "/").concat(key) : key;
|
|
856
|
+
_result[key] = _convertToArraysRecursive(value, childKey);
|
|
857
|
+
}
|
|
858
|
+
return _result;
|
|
859
|
+
}
|
|
860
|
+
return obj;
|
|
861
|
+
};
|
|
862
|
+
return _convertToArraysRecursive(result);
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Helper to check if a key pattern suggests an array structure
|
|
867
|
+
*/
|
|
868
|
+
var isArrayKey = function isArrayKey(obj, currentKey, partIndex) {
|
|
869
|
+
var parts = currentKey.split("/");
|
|
870
|
+
var prefix = parts.slice(0, partIndex + 1).join("/");
|
|
871
|
+
|
|
872
|
+
// Check if there are other keys with the same prefix but numeric suffixes
|
|
873
|
+
for (var _i1 = 0, _Object$keys = Object.keys(obj); _i1 < _Object$keys.length; _i1++) {
|
|
874
|
+
var key = _Object$keys[_i1];
|
|
875
|
+
if (key.startsWith(prefix + "/") && key !== currentKey) {
|
|
876
|
+
var otherParts = key.split("/");
|
|
877
|
+
if (otherParts.length > partIndex + 1 && /^\d+$/.test(otherParts[partIndex + 1])) {
|
|
878
|
+
return true;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
return false;
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Check if a string contains binary data (non-printable characters)
|
|
887
|
+
* @param {string} str - The string to check
|
|
888
|
+
* @returns {boolean} True if binary data detected
|
|
889
|
+
*/
|
|
890
|
+
var isBinaryString = function isBinaryString(str) {
|
|
891
|
+
if (!str || typeof str !== "string") return false;
|
|
892
|
+
|
|
893
|
+
// Check for non-printable characters (excluding common whitespace)
|
|
894
|
+
for (var i = 0; i < str.length; i++) {
|
|
895
|
+
var code = str.charCodeAt(i);
|
|
896
|
+
// Allow tab (9), newline (10), carriage return (13), and printable ASCII (32-126)
|
|
897
|
+
if (code < 9 || code > 13 && code < 32 || code > 126) {
|
|
898
|
+
return true;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
return false;
|
|
902
|
+
};
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* Convert binary string to Buffer
|
|
906
|
+
* @param {string} str - Binary string to convert
|
|
907
|
+
* @returns {Buffer} Buffer representation of the string
|
|
908
|
+
*/
|
|
909
|
+
var stringToBuffer = function stringToBuffer(str) {
|
|
910
|
+
var buffer = Buffer.alloc(str.length);
|
|
911
|
+
for (var i = 0; i < str.length; i++) {
|
|
912
|
+
buffer[i] = str.charCodeAt(i);
|
|
913
|
+
}
|
|
914
|
+
return buffer;
|
|
915
|
+
};
|
|
916
|
+
var from = exports.from = function from(http) {
|
|
917
|
+
var input = http.headers["signature-input"] || http.headers["Signature-Input"];
|
|
918
|
+
if (!input) {
|
|
919
|
+
return null;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// Decode signature inputs
|
|
923
|
+
var inputs = (0, _signerUtils.decodeSigInput)(input);
|
|
924
|
+
// Process the first signature (following the original logic)
|
|
925
|
+
for (var k in inputs) {
|
|
926
|
+
var _sigData$params$tag, _sigData$params;
|
|
927
|
+
var sigData = inputs[k];
|
|
928
|
+
// Extract only the signed components
|
|
929
|
+
var extractedComponents = extract(http, sigData.components);
|
|
930
|
+
var ret = {
|
|
931
|
+
hashpath: (_sigData$params$tag = sigData === null || sigData === void 0 || (_sigData$params = sigData.params) === null || _sigData$params === void 0 ? void 0 : _sigData$params.tag) !== null && _sigData$params$tag !== void 0 ? _sigData$params$tag : null
|
|
932
|
+
};
|
|
933
|
+
try {
|
|
934
|
+
ret.signer = (0, _utils.toAddr)(sigData.params.keyid);
|
|
935
|
+
} catch (e) {}
|
|
936
|
+
|
|
937
|
+
// Check if @path was in the signed components
|
|
938
|
+
var hasPathComponent = sigData.components.some(function (c) {
|
|
939
|
+
return c.replace(/"/g, "") === "@path";
|
|
940
|
+
});
|
|
941
|
+
|
|
942
|
+
// If @path is signed, add the path header to extracted components
|
|
943
|
+
if (hasPathComponent) {
|
|
944
|
+
extractedComponents["path"] = http.headers.path;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// Check if ao-result header is present
|
|
948
|
+
var aoResult = http.headers["ao-result"] || http.headers["Ao-Result"];
|
|
949
|
+
|
|
950
|
+
// Handle ao-result pointing to body
|
|
951
|
+
if (aoResult === "body") {
|
|
952
|
+
// Handle empty body case
|
|
953
|
+
if (!extractedComponents.body) {
|
|
954
|
+
return _objectSpread({
|
|
955
|
+
out: ""
|
|
956
|
+
}, ret); // Return empty string for empty body
|
|
957
|
+
}
|
|
958
|
+
// Check if body is binary data
|
|
959
|
+
if (isBinaryString(extractedComponents.body)) {
|
|
960
|
+
return _objectSpread({
|
|
961
|
+
out: stringToBuffer(extractedComponents.body)
|
|
962
|
+
}, ret);
|
|
963
|
+
}
|
|
964
|
+
// Return body as-is if it's not binary
|
|
965
|
+
return _objectSpread({
|
|
966
|
+
out: extractedComponents.body
|
|
967
|
+
}, ret);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// Convert the extracted components to JSON format
|
|
971
|
+
var result = _toJSON(extractedComponents);
|
|
972
|
+
|
|
973
|
+
// Handle ao-result if present and pointing to other fields
|
|
974
|
+
if (aoResult && aoResult !== "body") {
|
|
975
|
+
// Return the value of the key specified by ao-result
|
|
976
|
+
// If the key doesn't exist, return undefined (or could return null/empty string)
|
|
977
|
+
return _objectSpread({
|
|
978
|
+
out: result[aoResult] !== undefined ? result[aoResult] : ""
|
|
979
|
+
}, ret);
|
|
980
|
+
}
|
|
981
|
+
return _objectSpread({
|
|
982
|
+
out: result
|
|
983
|
+
}, ret);
|
|
984
|
+
}
|
|
985
|
+
return {
|
|
986
|
+
out: null,
|
|
987
|
+
hashpath: null
|
|
988
|
+
};
|
|
989
|
+
};
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Extract all keys and signature information from HTTP signature message
|
|
993
|
+
* @param {Object} http - HTTP message object with headers and body
|
|
994
|
+
* @returns {Object} Object containing all extracted signature data
|
|
995
|
+
*/
|
|
996
|
+
var extractKeys = exports.extractKeys = function extractKeys(http) {
|
|
997
|
+
var result = {
|
|
998
|
+
signatures: {},
|
|
999
|
+
keys: {},
|
|
1000
|
+
boundary: null,
|
|
1001
|
+
requiresBody: false,
|
|
1002
|
+
body: http.body ? toBuffer(http.body) : null,
|
|
1003
|
+
bodyText: typeof http.body === "string" ? http.body : null
|
|
1004
|
+
};
|
|
1005
|
+
|
|
1006
|
+
// Get multipart boundary if present
|
|
1007
|
+
result.boundary = getBoundary(http);
|
|
1008
|
+
|
|
1009
|
+
// Get signature header
|
|
1010
|
+
var signatureHeader = http.headers.signature || http.headers.Signature;
|
|
1011
|
+
if (!signatureHeader) {
|
|
1012
|
+
return result;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
// Get signature-input header
|
|
1016
|
+
var signatureInput = http.headers["signature-input"] || http.headers["Signature-Input"];
|
|
1017
|
+
if (!signatureInput) {
|
|
1018
|
+
return result;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// Decode all signature inputs
|
|
1022
|
+
var inputs = (0, _signerUtils.decodeSigInput)(signatureInput);
|
|
1023
|
+
|
|
1024
|
+
// Parse signature header to extract actual signatures
|
|
1025
|
+
// Format: sig1=:base64signature:, sig2=:base64signature:
|
|
1026
|
+
var signatures = {};
|
|
1027
|
+
var sigPattern = /([a-zA-Z0-9-]+)=:([^:]+):/g;
|
|
1028
|
+
var match;
|
|
1029
|
+
while ((match = sigPattern.exec(signatureHeader)) !== null) {
|
|
1030
|
+
signatures[match[1]] = match[2];
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// Process each signature
|
|
1034
|
+
for (var _i10 = 0, _Object$entries1 = Object.entries(inputs); _i10 < _Object$entries1.length; _i10++) {
|
|
1035
|
+
var _Object$entries1$_i = _slicedToArray(_Object$entries1[_i10], 2),
|
|
1036
|
+
sigName = _Object$entries1$_i[0],
|
|
1037
|
+
sigData = _Object$entries1$_i[1];
|
|
1038
|
+
var extractedValues = extract(http, sigData.components);
|
|
1039
|
+
|
|
1040
|
+
// Check if body is required
|
|
1041
|
+
if (extractedValues.__bodyRequired__) {
|
|
1042
|
+
result.requiresBody = true;
|
|
1043
|
+
}
|
|
1044
|
+
var signatureInfo = {
|
|
1045
|
+
name: sigName,
|
|
1046
|
+
signature: signatures[sigName] || null,
|
|
1047
|
+
components: sigData.components,
|
|
1048
|
+
params: sigData.params,
|
|
1049
|
+
extractedValues: extractedValues,
|
|
1050
|
+
hasContentDigest: sigData.components.some(function (c) {
|
|
1051
|
+
return c.replace(/"/g, "").toLowerCase() === "content-digest";
|
|
1052
|
+
})
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
// If has content-digest, verify it
|
|
1056
|
+
if (signatureInfo.hasContentDigest && result.body) {
|
|
1057
|
+
var contentDigest = http.headers["content-digest"] || http.headers["Content-Digest"];
|
|
1058
|
+
if (contentDigest) {
|
|
1059
|
+
signatureInfo.contentDigestVerification = verifyContentDigest(contentDigest, result.body);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// Extract key information from params
|
|
1064
|
+
if (sigData.params.keyid) {
|
|
1065
|
+
try {
|
|
1066
|
+
var keyBuffer = _base64url["default"].toBuffer(sigData.params.keyid);
|
|
1067
|
+
result.keys[sigName] = {
|
|
1068
|
+
keyid: sigData.params.keyid,
|
|
1069
|
+
keyBuffer: keyBuffer,
|
|
1070
|
+
algorithm: sigData.params.alg || "unknown"
|
|
1071
|
+
};
|
|
1072
|
+
} catch (e) {
|
|
1073
|
+
// If keyid is not base64url encoded, store as-is
|
|
1074
|
+
result.keys[sigName] = {
|
|
1075
|
+
keyid: sigData.params.keyid,
|
|
1076
|
+
algorithm: sigData.params.alg || "unknown"
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
result.signatures[sigName] = signatureInfo;
|
|
1081
|
+
}
|
|
1082
|
+
return result;
|
|
1083
|
+
};
|
|
1084
|
+
|
|
1085
|
+
/**
|
|
1086
|
+
* Verify if a message has valid HTTP signature structure
|
|
1087
|
+
* @param {Object} http - HTTP message object
|
|
1088
|
+
* @returns {boolean} True if message has valid signature structure
|
|
1089
|
+
*/
|
|
1090
|
+
var hasValidSignature = exports.hasValidSignature = function hasValidSignature(http) {
|
|
1091
|
+
var hasSignature = (http.headers.signature || http.headers.Signature) !== undefined;
|
|
1092
|
+
var hasSignatureInput = (http.headers["signature-input"] || http.headers["Signature-Input"]) !== undefined;
|
|
1093
|
+
return hasSignature && hasSignatureInput;
|
|
1094
|
+
};
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* Verify content-digest header against body
|
|
1098
|
+
* @param {string} contentDigest - Content-Digest header value
|
|
1099
|
+
* @param {string|Buffer} body - Request/response body
|
|
1100
|
+
* @returns {Object} Verification result with digest info
|
|
1101
|
+
*/
|
|
1102
|
+
var verifyContentDigest = exports.verifyContentDigest = function verifyContentDigest(contentDigest, body) {
|
|
1103
|
+
// Parse content-digest header format: algorithm=:base64digest:
|
|
1104
|
+
var match = contentDigest.match(/([^=]+)=:([^:]+):/);
|
|
1105
|
+
if (!match) {
|
|
1106
|
+
return {
|
|
1107
|
+
valid: false,
|
|
1108
|
+
error: "Invalid content-digest format"
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
var _match3 = _slicedToArray(match, 3),
|
|
1112
|
+
algorithm = _match3[1],
|
|
1113
|
+
expectedDigest = _match3[2];
|
|
1114
|
+
try {
|
|
1115
|
+
// Convert body to Buffer if needed
|
|
1116
|
+
var bodyBuffer = typeof body === "string" ? Buffer.from(body, "utf-8") : body;
|
|
1117
|
+
|
|
1118
|
+
// Calculate digest based on algorithm
|
|
1119
|
+
var actualDigest;
|
|
1120
|
+
var crypto = require("crypto");
|
|
1121
|
+
if (algorithm === "sha-256") {
|
|
1122
|
+
var hash = crypto.createHash("sha256");
|
|
1123
|
+
hash.update(bodyBuffer);
|
|
1124
|
+
actualDigest = hash.digest("base64");
|
|
1125
|
+
} else if (algorithm === "sha-512") {
|
|
1126
|
+
var _hash = crypto.createHash("sha512");
|
|
1127
|
+
_hash.update(bodyBuffer);
|
|
1128
|
+
actualDigest = _hash.digest("base64");
|
|
1129
|
+
} else {
|
|
1130
|
+
return {
|
|
1131
|
+
valid: false,
|
|
1132
|
+
error: "Unsupported algorithm: ".concat(algorithm)
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
return {
|
|
1136
|
+
valid: actualDigest === expectedDigest,
|
|
1137
|
+
algorithm: algorithm,
|
|
1138
|
+
expectedDigest: expectedDigest,
|
|
1139
|
+
actualDigest: actualDigest,
|
|
1140
|
+
matches: actualDigest === expectedDigest
|
|
1141
|
+
};
|
|
1142
|
+
} catch (error) {
|
|
1143
|
+
return {
|
|
1144
|
+
valid: false,
|
|
1145
|
+
error: error.message
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* Get all signature names from a message
|
|
1152
|
+
* @param {Object} http - HTTP message object
|
|
1153
|
+
* @returns {Array} Array of signature names
|
|
1154
|
+
*/
|
|
1155
|
+
var getSignatureNames = exports.getSignatureNames = function getSignatureNames(http) {
|
|
1156
|
+
var signatureInput = http.headers["signature-input"] || http.headers["Signature-Input"];
|
|
1157
|
+
if (!signatureInput) return [];
|
|
1158
|
+
var inputs = (0, _signerUtils.decodeSigInput)(signatureInput);
|
|
1159
|
+
return Object.keys(inputs);
|
|
1160
|
+
};
|