neozipkit 0.1.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.
Files changed (135) hide show
  1. package/README.md +400 -0
  2. package/contracts/Lock.sol +34 -0
  3. package/contracts/bytecode.txt +1 -0
  4. package/contracts/compile-contract.js +168 -0
  5. package/contracts/deploy/deploy-both-contracts.js +286 -0
  6. package/contracts/deploy/deploy-enhanced-contract.js +197 -0
  7. package/contracts/deploy/deploy-private-contract.js +190 -0
  8. package/contracts/deploy/deploy-public-clean.js +1063 -0
  9. package/contracts/deploy/deploy-public-contract.js +1107 -0
  10. package/contracts/deployment.config.example.js +25 -0
  11. package/contracts/remix-compile.js +222 -0
  12. package/contracts/setup-deployment.js +51 -0
  13. package/contracts/src/NZIP-NFT-Private.sol +350 -0
  14. package/contracts/src/NZIP-NFT.sol +265 -0
  15. package/contracts/src/ZipFileNFT-DEPRECATED-6field.sol +260 -0
  16. package/contracts/src/ZipFileNFT-DEPRECATED-Enhanced.sol +289 -0
  17. package/dist/browser/CertificateGeneratorBrowser.d.ts +75 -0
  18. package/dist/browser/CertificateGeneratorBrowser.js +433 -0
  19. package/dist/browser/TokenVerifierBrowser.d.ts +76 -0
  20. package/dist/browser/TokenVerifierBrowser.js +299 -0
  21. package/dist/browser/ZipKitBrowser.d.ts +18 -0
  22. package/dist/browser/ZipKitBrowser.js +250 -0
  23. package/dist/browser/ZipKitStampBrowser.d.ts +2 -0
  24. package/dist/browser/ZipKitStampBrowser.js +12 -0
  25. package/dist/browser-index.d.ts +21 -0
  26. package/dist/browser-index.js +58 -0
  27. package/dist/browser.d.ts +21 -0
  28. package/dist/browser.js +58 -0
  29. package/dist/index.d.ts +29 -0
  30. package/dist/index.js +76 -0
  31. package/dist/server/blockchain/CertificateToken.d.ts +48 -0
  32. package/dist/server/blockchain/CertificateToken.js +386 -0
  33. package/dist/server/blockchain/NFTMinter.d.ts +41 -0
  34. package/dist/server/blockchain/NFTMinter.js +323 -0
  35. package/dist/server/blockchain/TokenQuerier.d.ts +31 -0
  36. package/dist/server/blockchain/TokenQuerier.js +259 -0
  37. package/dist/server/blockchain/TokenVerifier.d.ts +20 -0
  38. package/dist/server/blockchain/TokenVerifier.js +395 -0
  39. package/dist/server/blockchain/WalletAnalyzer.d.ts +81 -0
  40. package/dist/server/blockchain/WalletAnalyzer.js +356 -0
  41. package/dist/server/blockchain/WalletFormatter.d.ts +39 -0
  42. package/dist/server/blockchain/WalletFormatter.js +196 -0
  43. package/dist/server/blockchain/WalletManager.d.ts +46 -0
  44. package/dist/server/blockchain/WalletManager.js +294 -0
  45. package/dist/server/blockchain/ZipMetadata.d.ts +27 -0
  46. package/dist/server/blockchain/ZipMetadata.js +131 -0
  47. package/dist/server/blockchain/ZipTokenProcessor.d.ts +44 -0
  48. package/dist/server/blockchain/ZipTokenProcessor.js +204 -0
  49. package/dist/server/blockchain/constants.d.ts +102 -0
  50. package/dist/server/blockchain/constants.js +968 -0
  51. package/dist/server/blockchain/index.d.ts +9 -0
  52. package/dist/server/blockchain/index.js +44 -0
  53. package/dist/server/blockchain/test-certificate.d.ts +8 -0
  54. package/dist/server/blockchain/test-certificate.js +100 -0
  55. package/dist/server/blockchain/types.d.ts +69 -0
  56. package/dist/server/blockchain/types.js +51 -0
  57. package/dist/server/platform/server/ZipKitServer.d.ts +105 -0
  58. package/dist/server/platform/server/ZipKitServer.js +437 -0
  59. package/dist/server/platform/servercomponents/ZipKitOTS.d.ts +91 -0
  60. package/dist/server/platform/servercomponents/ZipKitOTS.js +271 -0
  61. package/dist/shared/ZipEntry.d.ts +131 -0
  62. package/dist/shared/ZipEntry.js +686 -0
  63. package/dist/shared/ZipKit.d.ts +249 -0
  64. package/dist/shared/ZipKit.js +789 -0
  65. package/dist/shared/components/CertificateOTS.d.ts +15 -0
  66. package/dist/shared/components/CertificateOTS.js +116 -0
  67. package/dist/shared/components/FileSys.d.ts +2 -0
  68. package/dist/shared/components/FileSys.js +113 -0
  69. package/dist/shared/components/HashAccumulator.d.ts +55 -0
  70. package/dist/shared/components/HashAccumulator.js +100 -0
  71. package/dist/shared/components/Support.d.ts +63 -0
  72. package/dist/shared/components/Support.js +70 -0
  73. package/dist/shared/components/Util.d.ts +21 -0
  74. package/dist/shared/components/Util.js +115 -0
  75. package/dist/shared/components/ZipCrypto.d.ts +3 -0
  76. package/dist/shared/components/ZipCrypto.js +78 -0
  77. package/dist/shared/components/merkleTree.d.ts +66 -0
  78. package/dist/shared/components/merkleTree.js +136 -0
  79. package/dist/shared/constants/Errors.d.ts +53 -0
  80. package/dist/shared/constants/Errors.js +69 -0
  81. package/dist/shared/constants/Headers.d.ts +167 -0
  82. package/dist/shared/constants/Headers.js +191 -0
  83. package/dist/shared/types/index.d.ts +21 -0
  84. package/dist/shared/types/index.js +3 -0
  85. package/dist/shared/types.d.ts +33 -0
  86. package/dist/shared/types.js +8 -0
  87. package/dist/shared/version.d.ts +4 -0
  88. package/dist/shared/version.js +7 -0
  89. package/dist/types/index.d.ts +21 -0
  90. package/dist/types/index.js +3 -0
  91. package/examples/unzip-token.ts +488 -0
  92. package/examples/zip-token.ts +604 -0
  93. package/package.json +117 -0
  94. package/src/browser/CertificateGeneratorBrowser.ts +498 -0
  95. package/src/browser/TokenVerifierBrowser.ts +344 -0
  96. package/src/browser/ZipKitBrowser.ts +242 -0
  97. package/src/browser/ZipKitStampBrowser.ts +9 -0
  98. package/src/browser-index.ts +36 -0
  99. package/src/index.ts +48 -0
  100. package/src/server/blockchain/CertificateToken.ts +444 -0
  101. package/src/server/blockchain/NFTMinter.ts +357 -0
  102. package/src/server/blockchain/TokenQuerier.ts +287 -0
  103. package/src/server/blockchain/TokenVerifier.ts +453 -0
  104. package/src/server/blockchain/WalletAnalyzer.ts +397 -0
  105. package/src/server/blockchain/WalletFormatter.ts +206 -0
  106. package/src/server/blockchain/WalletManager.ts +294 -0
  107. package/src/server/blockchain/ZipMetadata.ts +117 -0
  108. package/src/server/blockchain/ZipTokenProcessor.ts +234 -0
  109. package/src/server/blockchain/constants.ts +969 -0
  110. package/src/server/blockchain/index.ts +42 -0
  111. package/src/server/blockchain/test-certificate.ts +137 -0
  112. package/src/server/blockchain/types.ts +134 -0
  113. package/src/server/platform/server/ZipKitServer.ts +459 -0
  114. package/src/server/platform/servercomponents/ZipKitOTS.ts +313 -0
  115. package/src/server/platform/servercomponents/opentimestamps.d.ts +23 -0
  116. package/src/shared/ZipEntry.ts +767 -0
  117. package/src/shared/ZipKit.ts +899 -0
  118. package/src/shared/components/CertificateOTS.ts +132 -0
  119. package/src/shared/components/FileSys.ts +87 -0
  120. package/src/shared/components/HashAccumulator.ts +113 -0
  121. package/src/shared/components/Support.ts +77 -0
  122. package/src/shared/components/Util.ts +113 -0
  123. package/src/shared/components/ZipCrypto.ts +91 -0
  124. package/src/shared/components/merkleTree.ts +162 -0
  125. package/src/shared/constants/Errors.ts +82 -0
  126. package/src/shared/constants/Headers.ts +203 -0
  127. package/src/shared/types/index.ts +25 -0
  128. package/src/shared/types/modules.d.ts +22 -0
  129. package/src/shared/types/opentimestamps.d.ts +23 -0
  130. package/src/shared/types.d.ts +8 -0
  131. package/src/shared/types.ts +43 -0
  132. package/src/shared/version.ts +4 -0
  133. package/src/types/index.ts +25 -0
  134. package/src/types/modules.d.ts +22 -0
  135. package/src/types/opentimestamps.d.ts +23 -0
@@ -0,0 +1,459 @@
1
+ /**
2
+ * ZipKitServer
3
+ * Copyright (c) 2025 NeoWare, Inc. All rights reserved.
4
+ *
5
+ * Server-side implementation of ZipKit that passes through all functions
6
+ * directly to the parent ZipKit class. This class provides a consistent interface
7
+ * for server environments and ensures all ZipKit functionality is available.
8
+ */
9
+
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import { v4 as uuidv4 } from 'uuid';
13
+ import { exit } from 'process';
14
+
15
+ import ZipKit,{ CompressOptions, ZipEntry, TIMESTAMP_METADATA, TIMESTAMP_SUBMITTED, CMP_METHOD } from '../../../shared/ZipKit';
16
+ import { createTimestamp, deserializeOts, TimestampResult } from '../servercomponents/ZipKitOTS';
17
+ import * as Headers from '../../../shared/constants/Headers';
18
+ import { crc32 } from '../../../shared/components/Util';
19
+ import OTS from '../../../shared/components/CertificateOTS';
20
+ import Errors from '../../../shared/constants/Errors';
21
+
22
+ // Re-export everything from ZipKit
23
+ export * from '../../../shared/ZipKit';
24
+ export { Headers };
25
+
26
+ /**
27
+ * This implementation is optimized for server environments and handles all
28
+ * ZIP operations including compression, extraction, encryption, and file management.
29
+ */
30
+ export default class ZipKitServer extends ZipKit {
31
+ /**
32
+ * Creates a new ZipKitServer instance
33
+ *
34
+ * Initializes the parent ZipKit class and logs environment support information
35
+ * for diagnostic purposes.
36
+ */
37
+ constructor() {
38
+ super(); // Call the parent constructor
39
+
40
+ // console.log('ZipKit.support.isNode: ', ZipKit.support.isNode);
41
+ // console.log('ZipKit.support.buffer: ', ZipKit.support.buffer);
42
+ // console.log('ZipKit.support.blob: ', ZipKit.support.blob);
43
+ // console.log('ZipKit.support.streams: ', ZipKit.support.streams);
44
+ // console.log('ZipKit.support.fileReader: ', ZipKit.support.fileReader);
45
+ }
46
+
47
+ /**
48
+ * Loads a ZIP file from the filesystem for updating/creating operations
49
+ *
50
+ * Attempts to read an existing ZIP file, but creates a new empty archive if
51
+ * the file doesn't exist. This method is used when adding or updating entries
52
+ * in an archive, handling both new and existing ZIP files gracefully.
53
+ *
54
+ * @param zipFile - Path to the ZIP file to load or create
55
+ */
56
+ loadZipFile(zipFile: string): void {
57
+ let inBuffer: Buffer | null = null;
58
+ let fdIn: number | null = null;
59
+
60
+ try {
61
+ if (fs.existsSync(zipFile)) {
62
+ fdIn = fs.openSync(zipFile, 'r');
63
+ const stats = fs.fstatSync(fdIn);
64
+ inBuffer = Buffer.alloc(stats.size);
65
+ fs.readSync(fdIn, inBuffer, 0, stats.size, 0);
66
+ } else {
67
+ // File doesn't exist, use an empty buffer
68
+ inBuffer = Buffer.alloc(0);
69
+ }
70
+ } catch (error) {
71
+ console.log('Warning: Could not open existing file. Creating new archive.');
72
+ inBuffer = Buffer.alloc(0);
73
+ } finally {
74
+ if (fdIn !== null) {
75
+ fs.closeSync(fdIn);
76
+ }
77
+ }
78
+
79
+ // Initialize empty buffer if null
80
+ const buffer = inBuffer || Buffer.alloc(0);
81
+ super.loadZip(buffer);
82
+ }
83
+
84
+ /**
85
+ * Loads a ZIP file from the filesystem for extraction and listing operations
86
+ *
87
+ * Reads an existing ZIP file and throws an error if the file doesn't exist.
88
+ * Use this method when working with existing archives that need to be extracted.
89
+ *
90
+ * @param zipFile - Path to the ZIP file to load
91
+ * @throws Error if the file doesn't exist or can't be read
92
+ */
93
+ loadUnzipFile(zipFile: string): void {
94
+ try {
95
+ // Check if the file exists before trying to read it
96
+ if (!fs.existsSync(zipFile)) {
97
+ console.error(`Error: Zip file "${zipFile}" does not exist`);
98
+ exit(1);
99
+ }
100
+
101
+ const inBuffer = fs.readFileSync(zipFile);
102
+ super.loadZip(inBuffer);
103
+ } catch (error) {
104
+ console.error(`Error: Failed to read zip file "${zipFile}"`);
105
+ exit(1);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Adds a single file to the ZIP archive
111
+ * @param filename - Path to the file to be added
112
+ * @param comment - Optional comment for the file entry
113
+ *
114
+ * Handles:
115
+ * - Creating/updating ZipEntry objects
116
+ * - Setting file attributes and timestamps
117
+ * - Respecting freshen (-f) and update (-u) flags
118
+ * - Setting compression method
119
+ */
120
+ addFile(filename: string, freshen: boolean = false, update: boolean = false): void {
121
+ let entry = super.getZipEntry(filename);
122
+ if (!entry) {
123
+ // Check for Freshen option
124
+ if (freshen) return;
125
+ entry = super.createZipEntry(filename);
126
+ } else if (!update) {
127
+ // Mark this entry as not being updated
128
+ entry.isUpdated = false;
129
+ return;
130
+ }
131
+ entry.platform = process.platform;
132
+
133
+ // Correctly retrieve file stats
134
+ let attr = fs.statSync(filename); // Synchronously get the stats of the file
135
+
136
+ entry.uncompressedSize = attr.size;
137
+
138
+ // Set the DOS file time/date based on the Date stamp of the file.
139
+ const utcDate = new Date(attr.mtime.getTime());
140
+ entry.timeDateDOS = entry.setDateTime(utcDate);
141
+ entry.universalTime = Math.floor(attr.mtime.getTime() / 1000); // Store Unix timestamp
142
+
143
+ // Set Unix UID/GID if on Unix-like system
144
+ if (process.platform !== 'win32') {
145
+ entry.uid = attr.uid;
146
+ entry.gid = attr.gid;
147
+ }
148
+
149
+ // Use attr.mode for file permissions
150
+ entry.isDirectory = attr.isDirectory();
151
+ let _fattr = (attr.mode & 0xfff) | (entry.isDirectory ? 0x4000 : 0x8000);
152
+ entry.extFileAttr = ((_fattr << 16) | (entry.isDirectory ? 0x10 : 0)) >>> 0;
153
+
154
+ // Set Compression method
155
+ // if (options.store) {
156
+ // entry.cmpMethod = CMP_METHOD.STORED;
157
+ // } else if (options.Z) {
158
+ // entry.cmpMethod = Headers.CMP_METHOD.DEFLATED;
159
+ // } else {
160
+ // entry.cmpMethod = CMP_METHOD.ZSTD;
161
+ // }
162
+ }
163
+
164
+ /**
165
+ * Processes files to be added to the ZIP archive
166
+ * Creates ZipEntry objects for each file and initiates the compression process
167
+ */
168
+ addFiles(files: string[], freshen: boolean = false, update: boolean = false) {
169
+ let filesAdded = 0;
170
+ for (var i=0; files[i] != undefined; i++) {
171
+ const filename = String(files[i]);
172
+ // console.log('filename: ', filename);
173
+
174
+ // Skip arguments that look like options (start with hyphen but aren't files)
175
+ if (filename.startsWith('-') && !fs.existsSync(filename)) {
176
+ console.warn(`Warning: Skipping '${filename}' which appears to be an option, not a file.`);
177
+ continue;
178
+ }
179
+
180
+ this.addFile(filename, freshen, update);
181
+ filesAdded++;
182
+ }
183
+
184
+ return filesAdded;
185
+ }
186
+
187
+ /**
188
+ * Creates a ZIP file with optional OpenTimestamps (OTS) metadata
189
+ *
190
+ * This method creates a ZIP file with optional OpenTimestamps (OTS) metadata,
191
+ * which includes a timestamp of the ZIP file's contents on the Bitcoin blockchain.
192
+ *
193
+ * @param zipFile - The path to the ZIP file to create
194
+ * @param compressOptions - The compression options for the ZIP file
195
+ * @returns void - The method triggers a download of the ZIP file
196
+ */
197
+ async createZip(zipFile: string, compressOptions: CompressOptions) {
198
+
199
+ // Ensure the directory structure for the output file exists
200
+ const outputDir = path.dirname(zipFile);
201
+ if (!fs.existsSync(outputDir)) {
202
+ fs.mkdirSync(outputDir, { recursive: true });
203
+ }
204
+
205
+ // Generate a unique temporary file name in the output directory
206
+ const _tempZipFile = path.join(outputDir, `neozip-${uuidv4()}.zip`);
207
+
208
+ // Open or create the .zip file for writing
209
+ const fd = fs.openSync(_tempZipFile, 'w');
210
+
211
+ let offset = await super.createZipFileData(compressOptions, {
212
+ onReadEntryData: (entry: ZipEntry) => {
213
+ // console.log(`Reading file: ${entry.filename}`);
214
+ try {
215
+ return fs.readFileSync(entry.filename);
216
+ } catch (error) {
217
+ throw new Error(`Failed to read file: ${entry.filename}`);
218
+ }
219
+ // return fs.readFileSync(entry.filename);
220
+ },
221
+ onOutputBuffer: (buffer: Buffer) => {
222
+ fs.writeSync(fd, buffer);
223
+ },
224
+ onEntryDone: (entry: ZipEntry, status: string) => {
225
+ console.log(`${status} ${entry.filename} to ${zipFile}`);
226
+ }
227
+ });
228
+
229
+ // Write the metadata entry to the .zip fi
230
+ await super.finishZipFileData(
231
+ offset,
232
+ function onOutputBuffer(buffer: Buffer) {
233
+ fs.writeSync(fd, buffer);
234
+ },
235
+ undefined
236
+ );
237
+
238
+ // Close the .zip file
239
+ fs.closeSync(fd);
240
+
241
+ // Delete the existing .zip file if it exists
242
+ if (fs.existsSync(zipFile)) {
243
+ fs.unlinkSync(zipFile);
244
+ }
245
+
246
+ // Replace the existing .zip file with the temporary file
247
+ fs.renameSync(_tempZipFile, zipFile);
248
+ }
249
+
250
+ /**
251
+ * Creates a ZIP file with OpenTimestamps (OTS) metadata
252
+ *
253
+ * This method creates a ZIP file with OpenTimestamps (OTS) metadata, which
254
+ * includes a timestamp of the ZIP file's contents on the Bitcoin blockchain.
255
+ *
256
+ * @param zipFile - The path to the ZIP file to create
257
+ * @param compressOptions - The compression options for the ZIP file
258
+ * @returns void - The method triggers a download of the ZIP file
259
+ */
260
+ async createZipOTS(zipFile: string, compressOptions: CompressOptions) {
261
+
262
+ // Ensure the directory structure for the output file exists
263
+ const outputDir = path.dirname(zipFile);
264
+ if (!fs.existsSync(outputDir)) {
265
+ fs.mkdirSync(outputDir, { recursive: true });
266
+ }
267
+
268
+ // Generate a unique temporary file name in the output directory
269
+ const _tempZipFile = path.join(outputDir, `neozip-${uuidv4()}.zip`);
270
+
271
+ // Open or create the .zip file for writing
272
+ const fd = fs.openSync(_tempZipFile, 'w');
273
+
274
+ let offset = await super.createZipFileData(compressOptions, {
275
+ onReadEntryData: (entry: ZipEntry) => {
276
+ // console.log(`Reading file: ${entry.filename}`);
277
+ try {
278
+ return fs.readFileSync(entry.filename);
279
+ } catch (error) {
280
+ throw new Error(`Failed to read file: ${entry.filename}`);
281
+ }
282
+ // return fs.readFileSync(entry.filename);
283
+ },
284
+ onOutputBuffer: (buffer: Buffer) => {
285
+ fs.writeSync(fd, buffer);
286
+ },
287
+ onEntryDone: (entry: ZipEntry, status: string) => {
288
+ console.log(`${status} ${entry.filename} to ${zipFile}`);
289
+ }
290
+ });
291
+
292
+ // Timestamp the zip file to the Bitcoin blockchain
293
+ let _metadataEntry = null;
294
+
295
+ console.log('Timestamping to Bitcoin blockchain...');
296
+ const _merkleRoot = super.getMerkleRoot();
297
+ console.log('Merkle Root: ' + _merkleRoot);
298
+ const _ots = await createTimestamp(_merkleRoot);
299
+ _metadataEntry = super.createTimestampMetadataEntry(_ots);
300
+
301
+ // Write the metadata entry to the .zip fi
302
+ await super.finishZipFileData(
303
+ offset,
304
+ function onOutputBuffer(buffer: Buffer) {
305
+ fs.writeSync(fd, buffer);
306
+ },
307
+ _metadataEntry || undefined
308
+ );
309
+
310
+ // Close the .zip file
311
+ fs.closeSync(fd);
312
+
313
+ // Delete the existing .zip file if it exists
314
+ if (fs.existsSync(zipFile)) {
315
+ fs.unlinkSync(zipFile);
316
+ }
317
+
318
+ // Replace the existing .zip file with the temporary file
319
+ fs.renameSync(_tempZipFile, zipFile);
320
+ }
321
+
322
+ /**
323
+ * Removes specified files from the ZIP archive
324
+ * Deletes matching ZipEntry objects and rebuilds the archive if any files were removed
325
+ */
326
+ deleteFiles(delFiles: string[]): number {
327
+
328
+ super.getDirectory();
329
+ let filesDel = 0;
330
+ delFiles.forEach(fname => {
331
+ const deleted = super.deleteFile(fname);
332
+ if (deleted) {
333
+ console.log(' deleting: ' + fname + "\n");
334
+ ++filesDel;
335
+ } else {
336
+ console.log(' warning: name not found: ' + fname + "\n");
337
+ }
338
+ })
339
+
340
+ return filesDel;
341
+ }
342
+
343
+ /**
344
+ * Upgrades a timestamp in an existing ZIP file
345
+ *
346
+ * This method takes an existing ZIP file and upgrades its timestamp by:
347
+ * 1. Loading the original ZIP file
348
+ * 2. Removing any existing timestamp metadata entries
349
+ * 3. Adding a new timestamp metadata entry with the upgraded OTS proof
350
+ * 4. Creating a new ZIP file with the updated timestamp
351
+ *
352
+ * @param zipFile - The original ZIP file to upgrade
353
+ * @param upgradedOts - The upgraded OpenTimestamps proof as an ArrayBuffer
354
+ * @returns void - The method triggers a download of the upgraded ZIP file
355
+ */
356
+ async upgradeOTS(fileName: string, upgradedOts: Buffer) {
357
+
358
+ // Generate a unique temporary file name in the output directory
359
+ let tempName = fileName.replace('.zip', '.upgrade.zip');
360
+
361
+ // Open or create the .zip file for writing
362
+ const fd = fs.openSync(tempName, 'w');
363
+ try {
364
+ const zipEntries = this.getDirectory();
365
+
366
+ let offset = 0;
367
+ // Copy the entries from the original file to the output file
368
+ for (const entry of zipEntries) {
369
+ if (entry.filename === TIMESTAMP_METADATA || entry.filename === TIMESTAMP_SUBMITTED) {
370
+ this.deleteFile(entry.filename);
371
+ } else {
372
+ // Copy the entry data to the output file
373
+ console.log('Copying entry: ', entry.filename);
374
+ const inData = this.copyEntry(entry);
375
+ entry.localHdrOffset = offset
376
+ offset += inData.length;
377
+ fs.writeSync(fd, inData);
378
+ }
379
+ }
380
+
381
+ // Add the new timestamp metadata file
382
+ let tsEntry = this.createZipEntry(TIMESTAMP_METADATA);
383
+ tsEntry.timeDateDOS = tsEntry.setDateTime(new Date());
384
+ tsEntry.compressedSize = upgradedOts.byteLength;
385
+ tsEntry.uncompressedSize = upgradedOts.byteLength;
386
+ tsEntry.cmpMethod = CMP_METHOD.STORED;
387
+ tsEntry.crc = crc32(upgradedOts);
388
+ tsEntry.fileBuffer = upgradedOts;
389
+ console.log('tsEntry: ', tsEntry);
390
+
391
+ const localHdr = tsEntry.createLocalHdr();
392
+ // Save local header offset for entry and calculate next offset
393
+ tsEntry.localHdrOffset = offset;
394
+ offset += localHdr.length + tsEntry.compressedSize;
395
+ fs.writeSync(fd, localHdr);
396
+ fs.writeSync(fd, upgradedOts);
397
+
398
+ // Output ZipEntries as Central End Directory
399
+ const centralDirOffset = offset;
400
+ for (const entry of zipEntries) {
401
+ const centralDirEntry = entry.centralDirEntry();
402
+ offset += centralDirEntry.length;
403
+ fs.writeSync(fd, centralDirEntry);
404
+ }
405
+ const centralDirSize = offset - centralDirOffset;
406
+
407
+ let ceBuf = this.centralEndHdr(centralDirSize, centralDirOffset);
408
+ fs.writeSync(fd, ceBuf);
409
+
410
+ // Close the .zip file
411
+ fs.closeSync(fd);
412
+
413
+ // Delete the existing .zip file if it exists
414
+ if (fs.existsSync(fileName)) {
415
+ fs.unlinkSync(fileName);
416
+ }
417
+
418
+ // Replace the existing .zip file with the temporary file
419
+ fs.renameSync(tempName, fileName);
420
+ }
421
+ catch (err) {
422
+ console.error('Error-upgradeOTS: ', err);
423
+ }
424
+ }
425
+
426
+ async createCertificateOTS(fileName: string, zipEntries: ZipEntry[], timestampResult: TimestampResult): Promise<string> {
427
+ if (!timestampResult || !timestampResult.merkleRoot || !fileName)
428
+ return Errors.CERTIFICATE_OTS_BAD;
429
+
430
+ let rsp = await deserializeOts(timestampResult);
431
+ if (!rsp) return Errors.CERTIFICATE_OTS_FAILED;
432
+ const result = JSON.parse(rsp);
433
+
434
+ const cert = OTS(
435
+ result.attestStr,
436
+ fileName,
437
+ timestampResult.merkleRoot,
438
+ result.needsUpdateMsg,
439
+ result.attestationValues,
440
+ zipEntries,
441
+ false,
442
+ );
443
+ if (!cert) return Errors.CERTIFICATE_OTS_FAILED;
444
+
445
+ // Generate certificate file name
446
+ const certFileName = fileName + '.certificate.html';
447
+
448
+ try {
449
+ // Write the certificate HTML to a file
450
+ fs.writeFileSync(certFileName, cert, { encoding: 'utf8' });
451
+ return `Certificate created as ${certFileName}`;
452
+ } catch (error) {
453
+ console.error(`Failed to write certificate file: ${error}`);
454
+ return Errors.CERTIFICATE_OTS_FAILED;
455
+ }
456
+ }
457
+ }
458
+
459
+