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.
- package/README.md +400 -0
- package/contracts/Lock.sol +34 -0
- package/contracts/bytecode.txt +1 -0
- package/contracts/compile-contract.js +168 -0
- package/contracts/deploy/deploy-both-contracts.js +286 -0
- package/contracts/deploy/deploy-enhanced-contract.js +197 -0
- package/contracts/deploy/deploy-private-contract.js +190 -0
- package/contracts/deploy/deploy-public-clean.js +1063 -0
- package/contracts/deploy/deploy-public-contract.js +1107 -0
- package/contracts/deployment.config.example.js +25 -0
- package/contracts/remix-compile.js +222 -0
- package/contracts/setup-deployment.js +51 -0
- package/contracts/src/NZIP-NFT-Private.sol +350 -0
- package/contracts/src/NZIP-NFT.sol +265 -0
- package/contracts/src/ZipFileNFT-DEPRECATED-6field.sol +260 -0
- package/contracts/src/ZipFileNFT-DEPRECATED-Enhanced.sol +289 -0
- package/dist/browser/CertificateGeneratorBrowser.d.ts +75 -0
- package/dist/browser/CertificateGeneratorBrowser.js +433 -0
- package/dist/browser/TokenVerifierBrowser.d.ts +76 -0
- package/dist/browser/TokenVerifierBrowser.js +299 -0
- package/dist/browser/ZipKitBrowser.d.ts +18 -0
- package/dist/browser/ZipKitBrowser.js +250 -0
- package/dist/browser/ZipKitStampBrowser.d.ts +2 -0
- package/dist/browser/ZipKitStampBrowser.js +12 -0
- package/dist/browser-index.d.ts +21 -0
- package/dist/browser-index.js +58 -0
- package/dist/browser.d.ts +21 -0
- package/dist/browser.js +58 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +76 -0
- package/dist/server/blockchain/CertificateToken.d.ts +48 -0
- package/dist/server/blockchain/CertificateToken.js +386 -0
- package/dist/server/blockchain/NFTMinter.d.ts +41 -0
- package/dist/server/blockchain/NFTMinter.js +323 -0
- package/dist/server/blockchain/TokenQuerier.d.ts +31 -0
- package/dist/server/blockchain/TokenQuerier.js +259 -0
- package/dist/server/blockchain/TokenVerifier.d.ts +20 -0
- package/dist/server/blockchain/TokenVerifier.js +395 -0
- package/dist/server/blockchain/WalletAnalyzer.d.ts +81 -0
- package/dist/server/blockchain/WalletAnalyzer.js +356 -0
- package/dist/server/blockchain/WalletFormatter.d.ts +39 -0
- package/dist/server/blockchain/WalletFormatter.js +196 -0
- package/dist/server/blockchain/WalletManager.d.ts +46 -0
- package/dist/server/blockchain/WalletManager.js +294 -0
- package/dist/server/blockchain/ZipMetadata.d.ts +27 -0
- package/dist/server/blockchain/ZipMetadata.js +131 -0
- package/dist/server/blockchain/ZipTokenProcessor.d.ts +44 -0
- package/dist/server/blockchain/ZipTokenProcessor.js +204 -0
- package/dist/server/blockchain/constants.d.ts +102 -0
- package/dist/server/blockchain/constants.js +968 -0
- package/dist/server/blockchain/index.d.ts +9 -0
- package/dist/server/blockchain/index.js +44 -0
- package/dist/server/blockchain/test-certificate.d.ts +8 -0
- package/dist/server/blockchain/test-certificate.js +100 -0
- package/dist/server/blockchain/types.d.ts +69 -0
- package/dist/server/blockchain/types.js +51 -0
- package/dist/server/platform/server/ZipKitServer.d.ts +105 -0
- package/dist/server/platform/server/ZipKitServer.js +437 -0
- package/dist/server/platform/servercomponents/ZipKitOTS.d.ts +91 -0
- package/dist/server/platform/servercomponents/ZipKitOTS.js +271 -0
- package/dist/shared/ZipEntry.d.ts +131 -0
- package/dist/shared/ZipEntry.js +686 -0
- package/dist/shared/ZipKit.d.ts +249 -0
- package/dist/shared/ZipKit.js +789 -0
- package/dist/shared/components/CertificateOTS.d.ts +15 -0
- package/dist/shared/components/CertificateOTS.js +116 -0
- package/dist/shared/components/FileSys.d.ts +2 -0
- package/dist/shared/components/FileSys.js +113 -0
- package/dist/shared/components/HashAccumulator.d.ts +55 -0
- package/dist/shared/components/HashAccumulator.js +100 -0
- package/dist/shared/components/Support.d.ts +63 -0
- package/dist/shared/components/Support.js +70 -0
- package/dist/shared/components/Util.d.ts +21 -0
- package/dist/shared/components/Util.js +115 -0
- package/dist/shared/components/ZipCrypto.d.ts +3 -0
- package/dist/shared/components/ZipCrypto.js +78 -0
- package/dist/shared/components/merkleTree.d.ts +66 -0
- package/dist/shared/components/merkleTree.js +136 -0
- package/dist/shared/constants/Errors.d.ts +53 -0
- package/dist/shared/constants/Errors.js +69 -0
- package/dist/shared/constants/Headers.d.ts +167 -0
- package/dist/shared/constants/Headers.js +191 -0
- package/dist/shared/types/index.d.ts +21 -0
- package/dist/shared/types/index.js +3 -0
- package/dist/shared/types.d.ts +33 -0
- package/dist/shared/types.js +8 -0
- package/dist/shared/version.d.ts +4 -0
- package/dist/shared/version.js +7 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.js +3 -0
- package/examples/unzip-token.ts +488 -0
- package/examples/zip-token.ts +604 -0
- package/package.json +117 -0
- package/src/browser/CertificateGeneratorBrowser.ts +498 -0
- package/src/browser/TokenVerifierBrowser.ts +344 -0
- package/src/browser/ZipKitBrowser.ts +242 -0
- package/src/browser/ZipKitStampBrowser.ts +9 -0
- package/src/browser-index.ts +36 -0
- package/src/index.ts +48 -0
- package/src/server/blockchain/CertificateToken.ts +444 -0
- package/src/server/blockchain/NFTMinter.ts +357 -0
- package/src/server/blockchain/TokenQuerier.ts +287 -0
- package/src/server/blockchain/TokenVerifier.ts +453 -0
- package/src/server/blockchain/WalletAnalyzer.ts +397 -0
- package/src/server/blockchain/WalletFormatter.ts +206 -0
- package/src/server/blockchain/WalletManager.ts +294 -0
- package/src/server/blockchain/ZipMetadata.ts +117 -0
- package/src/server/blockchain/ZipTokenProcessor.ts +234 -0
- package/src/server/blockchain/constants.ts +969 -0
- package/src/server/blockchain/index.ts +42 -0
- package/src/server/blockchain/test-certificate.ts +137 -0
- package/src/server/blockchain/types.ts +134 -0
- package/src/server/platform/server/ZipKitServer.ts +459 -0
- package/src/server/platform/servercomponents/ZipKitOTS.ts +313 -0
- package/src/server/platform/servercomponents/opentimestamps.d.ts +23 -0
- package/src/shared/ZipEntry.ts +767 -0
- package/src/shared/ZipKit.ts +899 -0
- package/src/shared/components/CertificateOTS.ts +132 -0
- package/src/shared/components/FileSys.ts +87 -0
- package/src/shared/components/HashAccumulator.ts +113 -0
- package/src/shared/components/Support.ts +77 -0
- package/src/shared/components/Util.ts +113 -0
- package/src/shared/components/ZipCrypto.ts +91 -0
- package/src/shared/components/merkleTree.ts +162 -0
- package/src/shared/constants/Errors.ts +82 -0
- package/src/shared/constants/Headers.ts +203 -0
- package/src/shared/types/index.ts +25 -0
- package/src/shared/types/modules.d.ts +22 -0
- package/src/shared/types/opentimestamps.d.ts +23 -0
- package/src/shared/types.d.ts +8 -0
- package/src/shared/types.ts +43 -0
- package/src/shared/version.ts +4 -0
- package/src/types/index.ts +25 -0
- package/src/types/modules.d.ts +22 -0
- package/src/types/opentimestamps.d.ts +23 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ======================================
|
|
4
|
+
// unzip-token.ts
|
|
5
|
+
// A command-line utility for extracting and managing ZIP archives with advanced features
|
|
6
|
+
// including decryption, blockchain token verification, and SHA-256 validation.
|
|
7
|
+
// Copyright (c) 2025 NeoWare, Inc. All rights reserved.
|
|
8
|
+
// ======================================
|
|
9
|
+
|
|
10
|
+
import { exit } from 'process';
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import readline from 'readline';
|
|
14
|
+
import moment from 'moment-timezone';
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
NEOZIPKIT_INFO,
|
|
18
|
+
ZipKitServer,
|
|
19
|
+
ZipEntry,
|
|
20
|
+
TIMESTAMP_METADATA,
|
|
21
|
+
TIMESTAMP_SUBMITTED,
|
|
22
|
+
verifyTimestamp
|
|
23
|
+
} from 'neozipkit';
|
|
24
|
+
|
|
25
|
+
import yargs from 'yargs';
|
|
26
|
+
import { hideBin } from 'yargs/helpers';
|
|
27
|
+
import { sprintf } from 'sprintf-js';
|
|
28
|
+
|
|
29
|
+
// Import blockchain components for token verification
|
|
30
|
+
import { NZipTokenInfo } from './blockchain/types';
|
|
31
|
+
import { TOKENIZED_METADATA } from '../src/constants/Headers';
|
|
32
|
+
|
|
33
|
+
// Import token verification functionality
|
|
34
|
+
import {
|
|
35
|
+
checkForTokenization,
|
|
36
|
+
TokenVerificationOptions
|
|
37
|
+
} from './blockchain/TokenVerifier';
|
|
38
|
+
|
|
39
|
+
// Add NeoUnzip version constants
|
|
40
|
+
const NEOUNZIP_VERSION = '0.1.2';
|
|
41
|
+
const NEOUNZIP_RELEASE_DATE = '03-31-2025';
|
|
42
|
+
|
|
43
|
+
// Display copyright and version header on startup
|
|
44
|
+
console.log(`NeoUnzip v${NEOUNZIP_VERSION} (${NEOUNZIP_RELEASE_DATE}) Copyright (c) 2025 NeoWare, Inc. All rights reserved`);
|
|
45
|
+
console.log(`Using NeoZipKit v${NEOZIPKIT_INFO.version} (${NEOZIPKIT_INFO.releaseDate})`);
|
|
46
|
+
|
|
47
|
+
const options = yargs(hideBin(process.argv))
|
|
48
|
+
.usage("Usage: $0 <zipfile> <extract path>")
|
|
49
|
+
.demandCommand(1, "Error - The .zip filename is required.")
|
|
50
|
+
.option('t', { alias: 'test', describe: 'Test archive files', type: 'boolean' })
|
|
51
|
+
.option('u', { alias: 'update', describe: 'Update files, create if neccessary', type: 'boolean' })
|
|
52
|
+
.option('f', { alias: 'freshen', describe: 'Freshen by extracting only if older file on disk.', type: 'boolean' })
|
|
53
|
+
.option('d', { alias: 'directory', describe: 'Specify a different directory', type: 'string' })
|
|
54
|
+
.option('x', { alias: 'exclude', describe: 'Exclude specified files', type: 'array' })
|
|
55
|
+
.option('j', { alias: 'junk', describe: 'Junk paths (don\'t make directories)', type: 'boolean' })
|
|
56
|
+
.option('q', { alias: 'quiet', describe: 'Quiet mode', type: 'boolean' })
|
|
57
|
+
.option('o', { alias: 'overwrite', describe: 'Overwrite files without prompting', type: 'boolean' })
|
|
58
|
+
.option('n', { alias: 'never', describe: 'Never overwrite existing files', type: 'boolean' })
|
|
59
|
+
.option('L', { alias: 'license', describe: 'Display software license', type: 'boolean' })
|
|
60
|
+
.option('H', { alias: 'Hash SHA-256', describe: 'Calculate and validate SHA-256 Hash on entries', type: 'boolean' })
|
|
61
|
+
.option('skip-hash', { describe: 'Skip SHA-256 hash validation', type: 'boolean' })
|
|
62
|
+
.option('skip-token', { describe: 'Skip NFT token verification', type: 'boolean' })
|
|
63
|
+
.option('S', { alias: 'Skip Timestamp', describe: 'Do not validate timestamped Zip', type: 'boolean' })
|
|
64
|
+
.option('C', { alias: 'Timestamp Certificate HTML', describe: 'Create a timestamp certicate as HTML file', type: 'boolean' })
|
|
65
|
+
.option('P', { alias: 'Timestamp Certificate PDF', describe: 'Create a timestamp certicate as PDF file', type: 'boolean' })
|
|
66
|
+
.option('c', { alias: 'certificate', describe: 'Generate token certificate', type: 'boolean' })
|
|
67
|
+
.help('help', 'Show help').alias('help', 'h')
|
|
68
|
+
.wrap(null)
|
|
69
|
+
.epilog('Copyright (c) 2025 NeoWare, Inc. - Type "neounzip "-L" for software license.\n')
|
|
70
|
+
.parseSync()
|
|
71
|
+
|
|
72
|
+
const zipFile = options._[0] as string;
|
|
73
|
+
const zipKit = new ZipKitServer();
|
|
74
|
+
|
|
75
|
+
// Global variables for token verification
|
|
76
|
+
let isTokenizedZip = false;
|
|
77
|
+
let tokenMetadata: NZipTokenInfo | null = null;
|
|
78
|
+
let calculatedMerkleRoot: string | null = null;
|
|
79
|
+
|
|
80
|
+
async function main() {
|
|
81
|
+
try {
|
|
82
|
+
// Check if the file exists before trying to read it
|
|
83
|
+
if (!fs.existsSync(zipFile)) {
|
|
84
|
+
console.error(`Error: Zip file "${zipFile}" does not exist`);
|
|
85
|
+
exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const inBuffer = fs.readFileSync(zipFile);
|
|
89
|
+
zipKit.loadZip(inBuffer);
|
|
90
|
+
|
|
91
|
+
// Check if this is a tokenized ZIP file
|
|
92
|
+
const verificationOptions: TokenVerificationOptions = {
|
|
93
|
+
skipHash: options['skip-hash'],
|
|
94
|
+
skipToken: options['skip-token'],
|
|
95
|
+
generateCertificate: options.c,
|
|
96
|
+
zipFileName: zipFile
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const result = await checkForTokenization(zipKit, verificationOptions);
|
|
100
|
+
|
|
101
|
+
// Update global variables with results
|
|
102
|
+
isTokenizedZip = result.isTokenized;
|
|
103
|
+
tokenMetadata = result.tokenMetadata;
|
|
104
|
+
calculatedMerkleRoot = result.calculatedMerkleRoot;
|
|
105
|
+
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error(`Error: Failed to read zip file "${zipFile}"`);
|
|
108
|
+
console.error(error);
|
|
109
|
+
exit(1);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// command options
|
|
113
|
+
if (options.t) {
|
|
114
|
+
// Test the CRC of the zip file
|
|
115
|
+
await extractFiles(true);
|
|
116
|
+
} else if (options.z) {
|
|
117
|
+
// Archive comment onlyzip
|
|
118
|
+
} else if (options.L) {
|
|
119
|
+
displayLicense();
|
|
120
|
+
} else {
|
|
121
|
+
// No options, extract all files
|
|
122
|
+
await extractFiles(false)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Start the main function
|
|
127
|
+
main().catch(error => {
|
|
128
|
+
console.error('Unhandled error:', error);
|
|
129
|
+
exit(1);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Display the software license
|
|
133
|
+
function displayLicense() {
|
|
134
|
+
prt('Copyright (c) 2025 by NeoWare, Inc. All rights reserved\n');
|
|
135
|
+
exit(0);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Extracts or tests files from the ZIP archive
|
|
140
|
+
* @param test - If true, only tests archive integrity without extracting
|
|
141
|
+
*/
|
|
142
|
+
async function extractFiles(test: boolean = false) {
|
|
143
|
+
try {
|
|
144
|
+
let zipEntries = zipKit.getDirectory() as ZipEntry[];
|
|
145
|
+
|
|
146
|
+
// Check if we have any entries
|
|
147
|
+
if (!zipEntries || zipEntries.length === 0) {
|
|
148
|
+
console.log('\nArchive is empty or invalid: ', zipFile);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let zipComment = zipKit.getZipComment();
|
|
153
|
+
|
|
154
|
+
console.log('\nArchive: ', zipFile);
|
|
155
|
+
if (zipComment)
|
|
156
|
+
console.log(zipComment);
|
|
157
|
+
|
|
158
|
+
let _extFiles = 0;
|
|
159
|
+
let _total = 0;
|
|
160
|
+
let _cmpTotal = 0;
|
|
161
|
+
let _password = null;
|
|
162
|
+
let _localData = null;
|
|
163
|
+
let _metaStamp = null;
|
|
164
|
+
for (const entry of zipEntries) {
|
|
165
|
+
// Check if Zip Entry is encrypted
|
|
166
|
+
if (entry.isEncrypted) {
|
|
167
|
+
if (entry.isStrongEncrypt) {
|
|
168
|
+
prt(sprintf(" skipping: %-25s Strong Encryption not supported\n", entry.filename));
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
for (var i=0; i < 3; i++) {
|
|
172
|
+
if (_password == null) {
|
|
173
|
+
_password = await inputPassword(entry, i > 0);
|
|
174
|
+
}
|
|
175
|
+
_localData = zipKit.decryptEntry(entry, _password);
|
|
176
|
+
if (_localData) break;
|
|
177
|
+
_password = null;
|
|
178
|
+
}
|
|
179
|
+
if (!_localData) {
|
|
180
|
+
prt(sprintf(" skipping: %-25s incorrect password\n", entry.filename));
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
test ? prt(sprintf(" Testing: %-25s ", entry.filename)) :
|
|
186
|
+
prt(sprintf(" Extracting: %-25s ", entry.filename));
|
|
187
|
+
try {
|
|
188
|
+
let _outBuf = await zipKit.extract(entry);
|
|
189
|
+
|
|
190
|
+
if (entry.filename === TIMESTAMP_METADATA) {
|
|
191
|
+
_metaStamp = _outBuf;
|
|
192
|
+
console.log(' Timestamp Metadata');
|
|
193
|
+
continue;
|
|
194
|
+
} else if (entry.filename === TIMESTAMP_SUBMITTED) {
|
|
195
|
+
_metaStamp = _outBuf;
|
|
196
|
+
console.log(' Timestamp Submitted');
|
|
197
|
+
continue;
|
|
198
|
+
} else if (entry.filename === TOKENIZED_METADATA) {
|
|
199
|
+
console.log(' NFT Token Metadata (not extracted)');
|
|
200
|
+
continue;
|
|
201
|
+
} else if (!test) {
|
|
202
|
+
const _path = options.d ? options.d + path.sep + entry.filename : entry.filename;
|
|
203
|
+
const _overwrite = await testOverwrite(_path);
|
|
204
|
+
if (_overwrite) {
|
|
205
|
+
if (_outBuf) {
|
|
206
|
+
writeFile(_path, _outBuf, entry, entry.extFileAttr);
|
|
207
|
+
} else {
|
|
208
|
+
prt("Error: No data to write\n");
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
} else if (options.n) {
|
|
212
|
+
prt("file exists, Skipped\n");
|
|
213
|
+
continue;
|
|
214
|
+
} else {
|
|
215
|
+
prt(" Skipped\n");
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Automatically validate SHA-256 if available and not skipped
|
|
221
|
+
if (entry.sha256 && !options['skip-hash']) {
|
|
222
|
+
console.log(' OK SHA-256 ✅');
|
|
223
|
+
} else if (entry.sha256 && options['skip-hash']) {
|
|
224
|
+
console.log(' OK (SHA-256 skipped)');
|
|
225
|
+
} else {
|
|
226
|
+
console.log(' OK');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
_extFiles++;
|
|
230
|
+
_total += entry.uncompressedSize;
|
|
231
|
+
_cmpTotal += entry.compressedSize;
|
|
232
|
+
} catch (e) {
|
|
233
|
+
prt(" Failed\n");
|
|
234
|
+
console.log(e);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
console.log('No Errors where detected in %d files %s.', _extFiles, test ? 'tested' : 'extracted');
|
|
238
|
+
|
|
239
|
+
// Display token verification results if this is a tokenized ZIP
|
|
240
|
+
if (isTokenizedZip && tokenMetadata) {
|
|
241
|
+
console.log('\n🔗 Token Verification Summary:');
|
|
242
|
+
console.log('═'.repeat(50));
|
|
243
|
+
|
|
244
|
+
// Full NFT token info only
|
|
245
|
+
console.log(`Token ID: ${tokenMetadata.tokenId}`);
|
|
246
|
+
console.log(`Network: ${tokenMetadata.network}`);
|
|
247
|
+
console.log(`Contract: ${tokenMetadata.contractAddress}`);
|
|
248
|
+
|
|
249
|
+
if (options['skip-token']) {
|
|
250
|
+
console.log('⏭️ Token verification: SKIPPED');
|
|
251
|
+
} else if (options['skip-hash']) {
|
|
252
|
+
console.log('⏭️ Archive integrity: SKIPPED');
|
|
253
|
+
console.log(' Hash calculation disabled - cannot verify');
|
|
254
|
+
} else if (calculatedMerkleRoot) {
|
|
255
|
+
console.log('🌐 Archive integrity: BLOCKCHAIN VERIFIED');
|
|
256
|
+
console.log(' See verification details above');
|
|
257
|
+
} else {
|
|
258
|
+
console.log('⚠️ Archive integrity: CANNOT VERIFY');
|
|
259
|
+
console.log(' Unable to calculate merkle root for comparison');
|
|
260
|
+
}
|
|
261
|
+
console.log('═'.repeat(50));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
let _merkleRoot = zipKit.checkForTimestamp();
|
|
265
|
+
if (_merkleRoot) {
|
|
266
|
+
if (options.S) {
|
|
267
|
+
console.log('Archive contains timestamp metadata - Skipping Validation');
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
console.log('Archive is timestamped - Pending Validation');
|
|
271
|
+
if (!_merkleRoot) {
|
|
272
|
+
console.log('No timestamp metadata found');
|
|
273
|
+
console.log('Archive timestamp validation failed!');
|
|
274
|
+
} else {
|
|
275
|
+
// Validate the timestamp
|
|
276
|
+
let _ots = await zipKit.getOts();
|
|
277
|
+
const _timestampResult = await verifyTimestamp(_merkleRoot, _ots);
|
|
278
|
+
|
|
279
|
+
// First check if _timestampResult is not null
|
|
280
|
+
if (_timestampResult) {
|
|
281
|
+
// Type guard to check if we have a successful result with the verified property
|
|
282
|
+
if ('verified' in _timestampResult && _timestampResult.verified) {
|
|
283
|
+
// Check if results property exists
|
|
284
|
+
if ('results' in _timestampResult && _timestampResult.results) {
|
|
285
|
+
for (const chain in _timestampResult.results) {
|
|
286
|
+
let _results = _timestampResult.results[chain];
|
|
287
|
+
const _date = moment(_results.timestamp * 1000).tz(moment.tz.guess()).format('MM-DD-YYYY hh:mma z');
|
|
288
|
+
const _blockchain = chain.charAt(0).toUpperCase() + chain.slice(1);
|
|
289
|
+
console.log('Success! ' + _blockchain + ' block ' + _results.height + ' attests existence as of ' + _date);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Check if upgradedOts property exists
|
|
294
|
+
if ('upgradedOts' in _timestampResult && _timestampResult.upgradedOts) {
|
|
295
|
+
const upgrade = await askUpgrade();
|
|
296
|
+
if (upgrade) {
|
|
297
|
+
let upgradeBuf = Buffer.from(_timestampResult.upgradedOts);
|
|
298
|
+
await zipKit.upgradeOTS(zipFile, upgradeBuf);
|
|
299
|
+
console.log('OTS upgraded - Certificate generation is now possible');
|
|
300
|
+
} else {
|
|
301
|
+
console.log('Certificate generation is not possible until timestamp is validated');
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
} else if ('error' in _timestampResult && !_timestampResult.error) {
|
|
305
|
+
console.log('Archive timestamp awaiting submittion to blockchain');
|
|
306
|
+
if (options.C || options.P) {
|
|
307
|
+
console.log('Certificate generation is not possible until timestamp is validated');
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} else {
|
|
311
|
+
console.log('No timestamp information available');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
} catch (error) {
|
|
316
|
+
console.error('Error processing zip file:', error);
|
|
317
|
+
exit(1);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Writes an extracted file to disk
|
|
323
|
+
* @param filename - Path where the file should be written
|
|
324
|
+
* @param outBuf - Buffer containing file data
|
|
325
|
+
* @param entry - ZIP entry associated with the file
|
|
326
|
+
* @param fileAttr - Optional Unix file permissions
|
|
327
|
+
* @returns boolean indicating success
|
|
328
|
+
*/
|
|
329
|
+
function writeFile(filename: string, outBuf: Buffer, entry?: ZipEntry, fileAttr?: number | undefined) {
|
|
330
|
+
// get Unix file permissions
|
|
331
|
+
const _fattr = fileAttr ? (((fileAttr >>> 0) | 0) >> 16) & 0xfff : 0;
|
|
332
|
+
|
|
333
|
+
var fd;
|
|
334
|
+
try {
|
|
335
|
+
fd = fs.openSync(filename, "w", 438); // 0666
|
|
336
|
+
} catch (e) {
|
|
337
|
+
fs.chmodSync(filename, 438);
|
|
338
|
+
fd = fs.openSync(filename, "w", 438);
|
|
339
|
+
}
|
|
340
|
+
if (!fd) return false;
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
fs.writeSync(fd, outBuf, 0, outBuf.length, 0);
|
|
344
|
+
} finally {
|
|
345
|
+
fs.closeSync(fd);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (_fattr)
|
|
349
|
+
fs.chmodSync(filename, _fattr);
|
|
350
|
+
|
|
351
|
+
// Set file modification time if universal time is available
|
|
352
|
+
if (entry && entry.universalTime) {
|
|
353
|
+
const mtime = new Date(entry.universalTime * 1000); // Convert Unix timestamp (seconds) to milliseconds
|
|
354
|
+
try {
|
|
355
|
+
// Set both access time and modification time to the universal time
|
|
356
|
+
fs.utimesSync(filename, mtime, mtime);
|
|
357
|
+
} catch (e) {
|
|
358
|
+
console.error(`Warning: Could not set file time for ${filename}: ${e}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Set owner and group if UID and GID are available (Unix-like systems only)
|
|
363
|
+
if (entry && (entry.uid !== null || entry.gid !== null)) {
|
|
364
|
+
try {
|
|
365
|
+
// Use process functions as fallbacks if they exist (Unix-like systems)
|
|
366
|
+
// Default to 0 (root) if neither entry values nor process functions are available
|
|
367
|
+
const uid = entry.uid !== null ? entry.uid :
|
|
368
|
+
(typeof process.getuid === 'function' ? process.getuid() : 0);
|
|
369
|
+
const gid = entry.gid !== null ? entry.gid :
|
|
370
|
+
(typeof process.getgid === 'function' ? process.getgid() : 0);
|
|
371
|
+
|
|
372
|
+
// Change owner and group of the file
|
|
373
|
+
fs.chownSync(filename, uid, gid);
|
|
374
|
+
} catch (e) {
|
|
375
|
+
// This might fail on Windows or if user doesn't have permission
|
|
376
|
+
console.error(`Warning: Could not set owner/group for ${filename}: ${e}`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Checks if a file should be overwritten during extraction
|
|
385
|
+
* @param filename - Path of the file to check
|
|
386
|
+
* @returns Promise<boolean> indicating if file should be overwritten
|
|
387
|
+
*/
|
|
388
|
+
async function testOverwrite(filename: string): Promise<boolean> {
|
|
389
|
+
// Check if we need to create a new folder
|
|
390
|
+
const _folder = path.dirname(filename);
|
|
391
|
+
if (!fs.existsSync(_folder)) {
|
|
392
|
+
console.log('Need to create directory: ', _folder);
|
|
393
|
+
// makeDir(_folder);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const _stat = fs.statSync(filename);
|
|
397
|
+
if (_stat.isDirectory()) {
|
|
398
|
+
console.log(': ', filename);
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (!fs.existsSync(filename))
|
|
403
|
+
return true;
|
|
404
|
+
|
|
405
|
+
if (options.n) {
|
|
406
|
+
return false;
|
|
407
|
+
} else if (options.o) {
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return new Promise((resolve) => {
|
|
412
|
+
process.stdin.setRawMode(true);
|
|
413
|
+
process.stdin.resume();
|
|
414
|
+
process.stdout.write("file exists, Overwrite? (y/n/a): ");
|
|
415
|
+
|
|
416
|
+
process.stdin.once('data', (data: Buffer) => {
|
|
417
|
+
const char = data.toString().toLowerCase();
|
|
418
|
+
|
|
419
|
+
// Restore stdin to its previous state
|
|
420
|
+
process.stdin.setRawMode(false);
|
|
421
|
+
process.stdin.pause();
|
|
422
|
+
process.stdout.write(char);
|
|
423
|
+
|
|
424
|
+
if (char === 'y') {
|
|
425
|
+
resolve(true);
|
|
426
|
+
} else if (char === 'a') {
|
|
427
|
+
prt(" Aborted\n");
|
|
428
|
+
exit(0);
|
|
429
|
+
} else {
|
|
430
|
+
resolve(false);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Prompts user to confirm timestamp upgrade
|
|
438
|
+
* @returns Promise<boolean> indicating user's choice
|
|
439
|
+
*/
|
|
440
|
+
async function askUpgrade(): Promise<boolean> {
|
|
441
|
+
return new Promise((resolve) => {
|
|
442
|
+
process.stdin.setRawMode(true);
|
|
443
|
+
process.stdin.resume();
|
|
444
|
+
process.stdout.write("Upgrade NeoTimestamp? (y/n): ");
|
|
445
|
+
|
|
446
|
+
process.stdin.once('data', (data: Buffer) => {
|
|
447
|
+
const char = data.toString().toLowerCase();
|
|
448
|
+
|
|
449
|
+
// Restore stdin to its previous state
|
|
450
|
+
process.stdin.setRawMode(false);
|
|
451
|
+
process.stdin.pause();
|
|
452
|
+
process.stdout.write(char + '\n');
|
|
453
|
+
|
|
454
|
+
if (char === 'y') {
|
|
455
|
+
resolve(true);
|
|
456
|
+
} else {
|
|
457
|
+
resolve(false);
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Prompts for password when extracting encrypted files
|
|
465
|
+
* @param entry - ZIP entry requiring password
|
|
466
|
+
* @param retry - Boolean indicating if this is a retry attempt
|
|
467
|
+
* @returns Promise<string> containing the entered password
|
|
468
|
+
*/
|
|
469
|
+
async function inputPassword(entry: ZipEntry, retry: boolean): Promise<string> {
|
|
470
|
+
const rl = readline.createInterface({
|
|
471
|
+
input: process.stdin,
|
|
472
|
+
output: process.stdout,
|
|
473
|
+
terminal: true
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
return new Promise<string>((resolve) => {
|
|
477
|
+
rl.question(retry ?
|
|
478
|
+
'password incorrect - renter: ' :
|
|
479
|
+
`[${zipFile}] ${entry.filename} password: `, (input: string) => {
|
|
480
|
+
rl.close();
|
|
481
|
+
resolve(input);
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function prt(msg: string) {
|
|
487
|
+
process.stdout.write(msg);
|
|
488
|
+
}
|