mirror of
https://github.com/uutils/coreutils
synced 2024-12-13 06:42:42 +00:00
basenc: add utility
basenc is a brand-new gnu core utility (added less than 3 years ago!), which enables some more encodings.
This commit is contained in:
parent
158a8a387b
commit
b8c383e210
12 changed files with 290 additions and 34 deletions
|
@ -68,6 +68,7 @@ splitn
|
||||||
trunc
|
trunc
|
||||||
|
|
||||||
# * uutils
|
# * uutils
|
||||||
|
basenc
|
||||||
chcon
|
chcon
|
||||||
chgrp
|
chgrp
|
||||||
chmod
|
chmod
|
||||||
|
|
43
Cargo.lock
generated
43
Cargo.lock
generated
|
@ -308,6 +308,7 @@ dependencies = [
|
||||||
"uu_base32",
|
"uu_base32",
|
||||||
"uu_base64",
|
"uu_base64",
|
||||||
"uu_basename",
|
"uu_basename",
|
||||||
|
"uu_basenc",
|
||||||
"uu_cat",
|
"uu_cat",
|
||||||
"uu_chgrp",
|
"uu_chgrp",
|
||||||
"uu_chmod",
|
"uu_chmod",
|
||||||
|
@ -595,9 +596,29 @@ checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "data-encoding"
|
name = "data-encoding"
|
||||||
version = "2.1.2"
|
version = "2.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97"
|
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "data-encoding-macro"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86927b7cd2fe88fa698b87404b287ab98d1a0063a34071d92e575b72d3029aca"
|
||||||
|
dependencies = [
|
||||||
|
"data-encoding",
|
||||||
|
"data-encoding-macro-internal",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "data-encoding-macro-internal"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5bbed42daaa95e780b60a50546aa345b8413a1e46f9a40a12907d3598f038db"
|
||||||
|
dependencies = [
|
||||||
|
"data-encoding",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "diff"
|
name = "diff"
|
||||||
|
@ -1959,6 +1980,16 @@ dependencies = [
|
||||||
"uucore_procs",
|
"uucore_procs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uu_basenc"
|
||||||
|
version = "0.0.7"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"uu_base32",
|
||||||
|
"uucore",
|
||||||
|
"uucore_procs",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uu_cat"
|
name = "uu_cat"
|
||||||
version = "0.0.7"
|
version = "0.0.7"
|
||||||
|
@ -2990,6 +3021,7 @@ version = "0.0.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
|
"data-encoding-macro",
|
||||||
"dns-lookup",
|
"dns-lookup",
|
||||||
"dunce",
|
"dunce",
|
||||||
"getopts",
|
"getopts",
|
||||||
|
@ -3002,6 +3034,7 @@ dependencies = [
|
||||||
"time",
|
"time",
|
||||||
"wild",
|
"wild",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
|
"z85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3129,3 +3162,9 @@ checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "z85"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ac8b56e4f9906a4ef5412875e9ce448364023335cec645fd457ecf51d4f2781"
|
||||||
|
|
|
@ -35,6 +35,7 @@ feat_common_core = [
|
||||||
"base32",
|
"base32",
|
||||||
"base64",
|
"base64",
|
||||||
"basename",
|
"basename",
|
||||||
|
"basenc",
|
||||||
"cat",
|
"cat",
|
||||||
"cksum",
|
"cksum",
|
||||||
"comm",
|
"comm",
|
||||||
|
@ -245,6 +246,7 @@ arch = { optional=true, version="0.0.7", package="uu_arch", path="src/uu/arc
|
||||||
base32 = { optional=true, version="0.0.7", package="uu_base32", path="src/uu/base32" }
|
base32 = { optional=true, version="0.0.7", package="uu_base32", path="src/uu/base32" }
|
||||||
base64 = { optional=true, version="0.0.7", package="uu_base64", path="src/uu/base64" }
|
base64 = { optional=true, version="0.0.7", package="uu_base64", path="src/uu/base64" }
|
||||||
basename = { optional=true, version="0.0.7", package="uu_basename", path="src/uu/basename" }
|
basename = { optional=true, version="0.0.7", package="uu_basename", path="src/uu/basename" }
|
||||||
|
basenc = { optional=true, version="0.0.7", package="uu_basenc", path="src/uu/basenc" }
|
||||||
cat = { optional=true, version="0.0.7", package="uu_cat", path="src/uu/cat" }
|
cat = { optional=true, version="0.0.7", package="uu_cat", path="src/uu/cat" }
|
||||||
chgrp = { optional=true, version="0.0.7", package="uu_chgrp", path="src/uu/chgrp" }
|
chgrp = { optional=true, version="0.0.7", package="uu_chgrp", path="src/uu/chgrp" }
|
||||||
chmod = { optional=true, version="0.0.7", package="uu_chmod", path="src/uu/chmod" }
|
chmod = { optional=true, version="0.0.7", package="uu_chmod", path="src/uu/chmod" }
|
||||||
|
|
29
README.md
29
README.md
|
@ -369,20 +369,21 @@ To contribute to uutils, please see [CONTRIBUTING](CONTRIBUTING.md).
|
||||||
| base32 | date | runcon |
|
| base32 | date | runcon |
|
||||||
| base64 | dd | stty |
|
| base64 | dd | stty |
|
||||||
| basename | df | |
|
| basename | df | |
|
||||||
| cat | expr | |
|
| basenc | expr | |
|
||||||
| chgrp | install | |
|
| cat | install | |
|
||||||
| chmod | join | |
|
| chgrp | join | |
|
||||||
| chown | ls | |
|
| chmod | ls | |
|
||||||
| chroot | more | |
|
| chown | more | |
|
||||||
| cksum | numfmt | |
|
| chroot | numfmt | |
|
||||||
| comm | od (`--strings` and 128-bit data types missing) |
|
| cksum | od (`--strings` and 128-bit data types missing) |
|
||||||
| csplit | pr | |
|
| comm | pr | |
|
||||||
| cut | printf | |
|
| csplit | printf | |
|
||||||
| dircolors | sort | |
|
| cut | sort | |
|
||||||
| dirname | split | |
|
| dircolors | split | |
|
||||||
| du | tac | |
|
| dirname | tac | |
|
||||||
| echo | tail | |
|
| du | tail | |
|
||||||
| env | test | |
|
| echo | test | |
|
||||||
|
| env | | |
|
||||||
| expand | | |
|
| expand | | |
|
||||||
| factor | | |
|
| factor | | |
|
||||||
| false | | |
|
| false | | |
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub mod options {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
fn from(app_name: &str, options: clap::ArgMatches) -> Result<Config, String> {
|
pub fn from(app_name: &str, options: &clap::ArgMatches) -> Result<Config, String> {
|
||||||
let file: Option<String> = match options.values_of(options::FILE) {
|
let file: Option<String> = match options.values_of(options::FILE) {
|
||||||
Some(mut values) => {
|
Some(mut values) => {
|
||||||
let name = values.next().unwrap();
|
let name = values.next().unwrap();
|
||||||
|
@ -85,7 +85,7 @@ pub fn parse_base_cmd_args(
|
||||||
let arg_list = args
|
let arg_list = args
|
||||||
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||||
.accept_any();
|
.accept_any();
|
||||||
Config::from(name, app.get_matches_from(arg_list))
|
Config::from(name, &app.get_matches_from(arg_list))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn base_app<'a>(name: &str, version: &'a str, about: &'a str) -> App<'static, 'a> {
|
pub fn base_app<'a>(name: &str, version: &'a str, about: &'a str) -> App<'static, 'a> {
|
||||||
|
@ -145,8 +145,18 @@ pub fn handle_input<R: Read>(
|
||||||
}
|
}
|
||||||
|
|
||||||
if !decode {
|
if !decode {
|
||||||
let encoded = data.encode();
|
match data.encode() {
|
||||||
wrap_print(&data, encoded);
|
Ok(s) => {
|
||||||
|
wrap_print(&data, s);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!(
|
||||||
|
"{}: error: invalid input (length must be multiple of 4 characters)",
|
||||||
|
name
|
||||||
|
);
|
||||||
|
exit!(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
match data.decode() {
|
match data.decode() {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
|
|
25
src/uu/basenc/Cargo.toml
Normal file
25
src/uu/basenc/Cargo.toml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
[package]
|
||||||
|
name = "uu_basenc"
|
||||||
|
version = "0.0.7"
|
||||||
|
authors = ["uutils developers"]
|
||||||
|
license = "MIT"
|
||||||
|
description = "basenc ~ (uutils) decode/encode input"
|
||||||
|
|
||||||
|
homepage = "https://github.com/uutils/coreutils"
|
||||||
|
repository = "https://github.com/uutils/coreutils/tree/master/src/uu/basenc"
|
||||||
|
keywords = ["coreutils", "uutils", "cross-platform", "cli", "utility"]
|
||||||
|
categories = ["command-line-utilities"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "src/basenc.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
|
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||||
|
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
uu_base32 = { version=">=0.0.6", package="uu_base32", path="../base32"}
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "basenc"
|
||||||
|
path = "src/main.rs"
|
95
src/uu/basenc/src/basenc.rs
Normal file
95
src/uu/basenc/src/basenc.rs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// This file is part of the uutils coreutils package.
|
||||||
|
//
|
||||||
|
// (c) Jordy Dickinson <jordy.dickinson@gmail.com>
|
||||||
|
// (c) Jian Zeng <anonymousknight96@gmail.com>
|
||||||
|
//
|
||||||
|
// For the full copyright and license information, please view the LICENSE file
|
||||||
|
// that was distributed with this source code.
|
||||||
|
|
||||||
|
//spell-checker:ignore (args) lsbf msbf
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate uucore;
|
||||||
|
|
||||||
|
use clap::{crate_version, App, Arg};
|
||||||
|
use uu_base32::base_common::{self, Config};
|
||||||
|
|
||||||
|
use uucore::{encoding::Format, InvalidEncodingHandling};
|
||||||
|
|
||||||
|
use std::io::{stdin, Read};
|
||||||
|
|
||||||
|
static ABOUT: &str = "
|
||||||
|
With no FILE, or when FILE is -, read standard input.
|
||||||
|
|
||||||
|
When decoding, the input may contain newlines in addition to the bytes of
|
||||||
|
the formal alphabet. Use --ignore-garbage to attempt to recover
|
||||||
|
from any other non-alphabet bytes in the encoded stream.
|
||||||
|
";
|
||||||
|
|
||||||
|
static BASE_CMD_PARSE_ERROR: i32 = 1;
|
||||||
|
|
||||||
|
const ENCODINGS: &[(&str, Format)] = &[
|
||||||
|
("base64", Format::Base64),
|
||||||
|
("base64url", Format::Base64Url),
|
||||||
|
("base32", Format::Base32),
|
||||||
|
("base32hex", Format::Base32Hex),
|
||||||
|
("base16", Format::Base16),
|
||||||
|
("base2lsbf", Format::Base2Lsbf),
|
||||||
|
("base2msbf", Format::Base2Msbf),
|
||||||
|
("z85", Format::Z85),
|
||||||
|
// common abbreviations. TODO: once we have clap 3.0 we can use `AppSettings::InferLongArgs` to get all abbreviations automatically
|
||||||
|
("base2l", Format::Base2Lsbf),
|
||||||
|
("base2m", Format::Base2Msbf),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn get_usage() -> String {
|
||||||
|
format!("{0} [OPTION]... [FILE]", executable!())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uu_app() -> App<'static, 'static> {
|
||||||
|
let mut app = base_common::base_app(executable!(), crate_version!(), ABOUT);
|
||||||
|
for encoding in ENCODINGS {
|
||||||
|
app = app.arg(Arg::with_name(encoding.0).long(encoding.0));
|
||||||
|
}
|
||||||
|
app
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_cmd_args(args: impl uucore::Args) -> (Config, Format) {
|
||||||
|
let usage = get_usage();
|
||||||
|
let matches = uu_app().usage(&usage[..]).get_matches_from(
|
||||||
|
args.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||||
|
.accept_any(),
|
||||||
|
);
|
||||||
|
let format = ENCODINGS
|
||||||
|
.iter()
|
||||||
|
.find(|encoding| matches.is_present(encoding.0))
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
show_usage_error!("missing encoding type");
|
||||||
|
std::process::exit(1)
|
||||||
|
})
|
||||||
|
.1;
|
||||||
|
(
|
||||||
|
Config::from("basenc", &matches).unwrap_or_else(|s| crash!(BASE_CMD_PARSE_ERROR, "{}", s)),
|
||||||
|
format,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
|
let name = executable!();
|
||||||
|
let (config, format) = parse_cmd_args(args);
|
||||||
|
// Create a reference to stdin so we can return a locked stdin from
|
||||||
|
// parse_base_cmd_args
|
||||||
|
let stdin_raw = stdin();
|
||||||
|
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw);
|
||||||
|
|
||||||
|
base_common::handle_input(
|
||||||
|
&mut input,
|
||||||
|
format,
|
||||||
|
config.wrap_cols,
|
||||||
|
config.ignore_garbage,
|
||||||
|
config.decode,
|
||||||
|
name,
|
||||||
|
);
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
1
src/uu/basenc/src/main.rs
Normal file
1
src/uu/basenc/src/main.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uucore_procs::main!(uu_basenc);
|
|
@ -27,7 +27,9 @@ nix = { version="<= 0.13", optional=true }
|
||||||
platform-info = { version="<= 0.1", optional=true }
|
platform-info = { version="<= 0.1", optional=true }
|
||||||
time = { version="<= 0.1.43", optional=true }
|
time = { version="<= 0.1.43", optional=true }
|
||||||
# * "problem" dependencies (pinned)
|
# * "problem" dependencies (pinned)
|
||||||
data-encoding = { version="~2.1", optional=true } ## data-encoding: require v2.1; but v2.2.0 breaks the build for MinSRV v1.31.0
|
data-encoding = { version="2.1", optional=true }
|
||||||
|
data-encoding-macro = { version="0.1.12", optional=true }
|
||||||
|
z85 = { version="3.0.3", optional=true }
|
||||||
libc = { version="0.2.15, <= 0.2.85", optional=true } ## libc: initial utmp support added in v0.2.15; but v0.2.68 breaks the build for MinSRV v1.31.0
|
libc = { version="0.2.15, <= 0.2.85", optional=true } ## libc: initial utmp support added in v0.2.15; but v0.2.68 breaks the build for MinSRV v1.31.0
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -43,7 +45,7 @@ termion = "1.5"
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
# * non-default features
|
# * non-default features
|
||||||
encoding = ["data-encoding", "thiserror"]
|
encoding = ["data-encoding", "data-encoding-macro", "z85", "thiserror"]
|
||||||
entries = ["libc"]
|
entries = ["libc"]
|
||||||
fs = ["libc"]
|
fs = ["libc"]
|
||||||
fsext = ["libc", "time"]
|
fsext = ["libc", "time"]
|
||||||
|
|
|
@ -5,45 +5,95 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
// spell-checker:ignore (strings) ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
// spell-checker:ignore (strings) ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUV
|
||||||
|
// spell-checker:ignore (encodings) lsbf msbf hexupper
|
||||||
|
|
||||||
extern crate data_encoding;
|
use data_encoding::{self, BASE32, BASE64};
|
||||||
|
|
||||||
use self::data_encoding::{DecodeError, BASE32, BASE64};
|
|
||||||
|
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
|
use data_encoding::{Encoding, BASE32HEX, BASE64URL, HEXUPPER};
|
||||||
|
use data_encoding_macro::new_encoding;
|
||||||
#[cfg(feature = "thiserror")]
|
#[cfg(feature = "thiserror")]
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum EncodingError {
|
pub enum DecodeError {
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
Decode(#[from] DecodeError),
|
Decode(#[from] data_encoding::DecodeError),
|
||||||
|
#[error("{}", _0)]
|
||||||
|
DecodeZ85(#[from] z85::DecodeError),
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DecodeResult = Result<Vec<u8>, EncodingError>;
|
pub enum EncodeError {
|
||||||
|
Z85InputLenNotMultipleOf4,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DecodeResult = Result<Vec<u8>, DecodeError>;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Format {
|
pub enum Format {
|
||||||
Base32,
|
|
||||||
Base64,
|
Base64,
|
||||||
|
Base64Url,
|
||||||
|
Base32,
|
||||||
|
Base32Hex,
|
||||||
|
Base16,
|
||||||
|
Base2Lsbf,
|
||||||
|
Base2Msbf,
|
||||||
|
Z85,
|
||||||
}
|
}
|
||||||
use self::Format::*;
|
use self::Format::*;
|
||||||
|
|
||||||
pub fn encode(f: Format, input: &[u8]) -> String {
|
const BASE2LSBF: Encoding = new_encoding! {
|
||||||
match f {
|
symbols: "01",
|
||||||
|
bit_order: LeastSignificantFirst,
|
||||||
|
};
|
||||||
|
const BASE2MSBF: Encoding = new_encoding! {
|
||||||
|
symbols: "01",
|
||||||
|
bit_order: MostSignificantFirst,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn encode(f: Format, input: &[u8]) -> Result<String, EncodeError> {
|
||||||
|
Ok(match f {
|
||||||
Base32 => BASE32.encode(input),
|
Base32 => BASE32.encode(input),
|
||||||
Base64 => BASE64.encode(input),
|
Base64 => BASE64.encode(input),
|
||||||
|
Base64Url => BASE64URL.encode(input),
|
||||||
|
Base32Hex => BASE32HEX.encode(input),
|
||||||
|
Base16 => HEXUPPER.encode(input),
|
||||||
|
Base2Lsbf => BASE2LSBF.encode(input),
|
||||||
|
Base2Msbf => BASE2MSBF.encode(input),
|
||||||
|
Z85 => {
|
||||||
|
// According to the spec we should not accept inputs whose len is not a multiple of 4.
|
||||||
|
// However, the z85 crate implements a padded encoding and accepts such inputs. We have to manually check for them.
|
||||||
|
if input.len() % 4 != 0 {
|
||||||
|
return Err(EncodeError::Z85InputLenNotMultipleOf4);
|
||||||
|
} else {
|
||||||
|
z85::encode(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn decode(f: Format, input: &[u8]) -> DecodeResult {
|
pub fn decode(f: Format, input: &[u8]) -> DecodeResult {
|
||||||
Ok(match f {
|
Ok(match f {
|
||||||
Base32 => BASE32.decode(input)?,
|
Base32 => BASE32.decode(input)?,
|
||||||
Base64 => BASE64.decode(input)?,
|
Base64 => BASE64.decode(input)?,
|
||||||
|
Base64Url => BASE64URL.decode(input)?,
|
||||||
|
Base32Hex => BASE32HEX.decode(input)?,
|
||||||
|
Base16 => HEXUPPER.decode(input)?,
|
||||||
|
Base2Lsbf => BASE2LSBF.decode(input)?,
|
||||||
|
Base2Msbf => BASE2MSBF.decode(input)?,
|
||||||
|
Z85 => {
|
||||||
|
// The z85 crate implements a padded encoding by using a leading '#' which is otherwise not allowed.
|
||||||
|
// We manually check for a leading '#' and return an error ourselves.
|
||||||
|
if input.starts_with(&[b'#']) {
|
||||||
|
return Err(z85::DecodeError::InvalidByte(0, b'#').into());
|
||||||
|
} else {
|
||||||
|
z85::decode(input)?
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +115,12 @@ impl<R: Read> Data<R> {
|
||||||
alphabet: match format {
|
alphabet: match format {
|
||||||
Base32 => b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
|
Base32 => b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
|
||||||
Base64 => b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=+/",
|
Base64 => b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=+/",
|
||||||
|
Base64Url => b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=_-",
|
||||||
|
Base32Hex => b"0123456789ABCDEFGHIJKLMNOPQRSTUV=",
|
||||||
|
Base16 => b"0123456789ABCDEF",
|
||||||
|
Base2Lsbf => b"01",
|
||||||
|
Base2Msbf => b"01",
|
||||||
|
Z85 => b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +146,7 @@ impl<R: Read> Data<R> {
|
||||||
decode(self.format, &buf)
|
decode(self.format, &buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode(&mut self) -> String {
|
pub fn encode(&mut self) -> Result<String, EncodeError> {
|
||||||
let mut buf: Vec<u8> = vec![];
|
let mut buf: Vec<u8> = vec![];
|
||||||
self.input.read_to_end(&mut buf).unwrap();
|
self.input.read_to_end(&mut buf).unwrap();
|
||||||
encode(self.format, buf.as_slice())
|
encode(self.format, buf.as_slice())
|
||||||
|
|
16
tests/by-util/test_basenc.rs
Normal file
16
tests/by-util/test_basenc.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
use crate::common::util::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_z85_not_padded() {
|
||||||
|
// The z85 crate deviates from the standard in some cases; we have to catch those
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--z85", "-d"])
|
||||||
|
.pipe_in("##########")
|
||||||
|
.fails()
|
||||||
|
.stderr_only("basenc: error: invalid input");
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--z85"])
|
||||||
|
.pipe_in("123")
|
||||||
|
.fails()
|
||||||
|
.stderr_only("basenc: error: invalid input (length must be multiple of 4 characters)");
|
||||||
|
}
|
|
@ -123,6 +123,14 @@ test -f "${BUILDDIR}/getlimits" || cp src/getlimits "${BUILDDIR}"
|
||||||
# When decoding an invalid base32/64 string, gnu writes everything it was able to decode until
|
# When decoding an invalid base32/64 string, gnu writes everything it was able to decode until
|
||||||
# it hit the decode error, while we don't write anything if the input is invalid.
|
# it hit the decode error, while we don't write anything if the input is invalid.
|
||||||
sed -i "s/\(baddecode.*OUT=>\"\).*\"/\1\"/g" tests/misc/base64.pl
|
sed -i "s/\(baddecode.*OUT=>\"\).*\"/\1\"/g" tests/misc/base64.pl
|
||||||
|
sed -i "s/\(\(b2[ml]_[69]\|b32h_[56]\|z85_8\|z85_35\).*OUT=>\)[^}]*\(.*\)/\1\"\"\3/g" tests/misc/basenc.pl
|
||||||
|
|
||||||
|
# add "error: " to the expected error message
|
||||||
|
sed -i "s/\$prog: invalid input/\$prog: error: invalid input/g" tests/misc/basenc.pl
|
||||||
|
|
||||||
|
# basenc: swap out error message for unexpected arg
|
||||||
|
sed -i "s/ {ERR=>\"\$prog: foobar\\\\n\" \. \$try_help }/ {ERR=>\"error: Found argument '--foobar' which wasn't expected, or isn't valid in this context\n\nUSAGE:\n basenc [OPTION]... [FILE]\n\nFor more information try --help\n\"}]/" tests/misc/basenc.pl
|
||||||
|
sed -i "s/ {ERR_SUBST=>\"s\/(unrecognized|unknown) option \[-' \]\*foobar\[' \]\*\/foobar\/\"}],//" tests/misc/basenc.pl
|
||||||
|
|
||||||
# Remove the check whether a util was built. Otherwise tests against utils like "arch" are not run.
|
# Remove the check whether a util was built. Otherwise tests against utils like "arch" are not run.
|
||||||
sed -i "s|require_built_ |# require_built_ |g" init.cfg
|
sed -i "s|require_built_ |# require_built_ |g" init.cfg
|
||||||
|
|
Loading…
Reference in a new issue