// Copyright Epic Games, Inc. All Rights Reserved. #include "print_cmd.h" #include #include #include #include #include #include #include using namespace std::literals; namespace zen { static void PrintCbObject(CbObject Object) { ExtendableStringBuilder<1024> ObjStr; CompactBinaryToJson(Object, ObjStr); ZEN_CONSOLE("{}", ObjStr); } static void PrintCompactBinary(IoBuffer Data) { ExtendableStringBuilder<1024> StreamString; CompactBinaryToJson(Data.GetView(), StreamString); ZEN_CONSOLE("{}", StreamString); } PrintCommand::PrintCommand() { m_Options.add_options()("h,help", "Print help"); m_Options.add_option("", "s", "source", "Object payload file (use '-' to read from STDIN)", cxxopts::value(m_Filename), ""); m_Options.parse_positional({"source"}); } PrintCommand::~PrintCommand() = default; int PrintCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions); if (!ParseOptions(argc, argv)) { return 0; } // Validate arguments if (m_Filename.empty()) throw std::runtime_error("No file specified"); FileContents Fc; if (m_Filename == "-") { Fc = ReadStdIn(); } else { Fc = ReadFile(m_Filename); } if (Fc.ErrorCode) { ZEN_ERROR("Failed to read file '{}': {}", m_Filename, Fc.ErrorCode.message()); return 1; } IoBuffer Data = Fc.Flatten(); IoHash RawHash; uint64_t RawSize; if (CompressedBuffer::ValidateCompressedHeader(Data, RawHash, RawSize)) { ZEN_CONSOLE("Compressed binary: size {}, raw size {}, hash: {}", Data.GetSize(), RawSize, RawHash); } else if (IsPackageMessage(Data)) { CbPackage Package = ParsePackageMessage(Data); CbObject Object = Package.GetObject(); std::span Attachments = Package.GetAttachments(); ZEN_CONSOLE("Package - {} attachments, object hash {}", Package.GetAttachments().size(), Package.GetObjectHash()); ZEN_CONSOLE(""); int AttachmentIndex = 1; for (const CbAttachment& Attachment : Attachments) { std::string AttachmentSize = "n/a"; const char* AttachmentType = "unknown"; if (Attachment.IsCompressedBinary()) { AttachmentType = "Compressed"; AttachmentSize = fmt::format("{} ({} uncompressed)", Attachment.AsCompressedBinary().GetCompressedSize(), Attachment.AsCompressedBinary().DecodeRawSize()); } else if (Attachment.IsBinary()) { AttachmentType = "Binary"; AttachmentSize = fmt::format("{}", Attachment.AsBinary().GetSize()); } else if (Attachment.IsObject()) { AttachmentType = "Object"; AttachmentSize = fmt::format("{}", Attachment.AsObject().GetSize()); } else if (Attachment.IsNull()) { AttachmentType = "null"; } ZEN_CONSOLE("Attachment #{} : {}, {}, size {}", AttachmentIndex, Attachment.GetHash(), AttachmentType, AttachmentSize); ++AttachmentIndex; } ZEN_CONSOLE("---8<---"); PrintCbObject(Object); } else if (CbValidateError Result = ValidateCompactBinary(Data, CbValidateMode::Default | CbValidateMode::Names | CbValidateMode::Format | CbValidateMode::Package | CbValidateMode::PackageHash); Result == CbValidateError::None) { PrintCompactBinary(Data); } else { ZEN_ERROR("Data in file '{}' does not appear to be compact binary (validation error {:#x})", m_Filename, uint32_t(Result)); return 1; } return 0; } ////////////////////////////////////////////////////////////////////////// PrintPackageCommand::PrintPackageCommand() { m_Options.add_options()("h,help", "Print help"); m_Options.add_option("", "s", "source", "Package payload file", cxxopts::value(m_Filename), ""); m_Options.parse_positional({"source"}); } PrintPackageCommand::~PrintPackageCommand() { } int PrintPackageCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions); if (!ParseOptions(argc, argv)) { return 0; } // Validate arguments if (m_Filename.empty()) throw std::runtime_error("No file specified"); FileContents Fc = ReadFile(m_Filename); IoBuffer Data = Fc.Flatten(); CbPackage Package; bool Ok = Package.TryLoad(Data) || legacy::TryLoadCbPackage(Package, Data, &UniqueBuffer::Alloc); if (Ok) { ExtendableStringBuilder<1024> ObjStr; CompactBinaryToJson(Package.GetObject(), ObjStr); ZEN_CONSOLE("{}", ObjStr); } else { ZEN_ERROR("error: malformed package?"); } return 0; } } // namespace zen