diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index 052eba2fcb9..964baad9299 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -162,6 +162,7 @@ func TestCommands(t *testing.T) { "/multibase", "/multibase/decode", "/multibase/encode", + "/multibase/transcode", "/multibase/list", "/name", "/name/publish", diff --git a/core/commands/multibase.go b/core/commands/multibase.go index 6a8525ee51a..83f3ac2b4c6 100644 --- a/core/commands/multibase.go +++ b/core/commands/multibase.go @@ -16,9 +16,10 @@ var MbaseCmd = &cmds.Command{ Tagline: "Encode and decode files or stdin with multibase format", }, Subcommands: map[string]*cmds.Command{ - "encode": mbaseEncodeCmd, - "decode": mbaseDecodeCmd, - "list": basesCmd, + "encode": mbaseEncodeCmd, + "decode": mbaseDecodeCmd, + "transcode": mbaseTranscodeCmd, + "list": basesCmd, }, Extra: CreateCmdExtras(SetDoesNotUseRepo(true)), } @@ -116,3 +117,55 @@ This command expects multibase inside of a file or via stdin: return resp.Emit(reader) }, } + +var mbaseTranscodeCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Transcode multibase string between bases", + LongDescription: ` +This command expects multibase inside of a file or via stdin. + +By default it will use URL-safe base64url encoding, +but one can customize used base with -b: + + > echo -n hello | ipfs multibase encode > file + > cat file + uaGVsbG8 + + > ipfs multibase transcode file -b base16 > transcoded_file + > cat transcoded_file + f68656c6c6f +`, + }, + Arguments: []cmds.Argument{ + cmds.FileArg("encoded_file", true, false, "encoded data to decode").EnableStdin(), + }, + Options: []cmds.Option{ + cmds.StringOption(mbaseOptionName, "multibase encoding").WithDefault("base64url"), + }, + Run: func(req *cmds.Request, resp cmds.ResponseEmitter, env cmds.Environment) error { + if err := req.ParseBodyArgs(); err != nil { + return err + } + encoderName, _ := req.Options[mbaseOptionName].(string) + encoder, err := mbase.EncoderByName(encoderName) + if err != nil { + return err + } + files := req.Files.Entries() + file, err := cmdenv.GetFileArg(files) + if err != nil { + return fmt.Errorf("failed to access file: %w", err) + } + encoded_data, err := ioutil.ReadAll(file) + if err != nil { + return fmt.Errorf("failed to read file contents: %w", err) + } + _, data, err := mbase.Decode(string(encoded_data)) + if err != nil { + return fmt.Errorf("failed to decode multibase: %w", err) + } + encoded := encoder.Encode(data) + reader := strings.NewReader(encoded) + return resp.Emit(reader) + }, +} diff --git a/test/sharness/t0295-multibase.sh b/test/sharness/t0295-multibase.sh index f428d8daf70..da59b41f5a0 100755 --- a/test/sharness/t0295-multibase.sh +++ b/test/sharness/t0295-multibase.sh @@ -74,6 +74,19 @@ test_expect_success "multibase encode+decode roundtrip" ' test_cmp actual expected ' +test_expect_success "mutlibase transcode works (stdin)" ' + echo -n f68656c6c6f > expected && + echo -n uaGVsbG8 | ipfs multibase transcode -b base16 > actual && + test_cmp actual expected +' + +test_expect_success "multibase transcode works (file)" ' + echo -n uaGVsbG8 > file && + echo -n f68656c6c6f > expected && + ipfs multibase transcode ./file -b base16> actual && + test_cmp actual expected +' + test_expect_success "multibase error on unknown multibase prefix" ' echo "Error: failed to decode multibase: selected encoding not supported" > expected && echo -n ę-that-should-do-the-trick | ipfs multibase decode 2> actual ;