update base64 implementation to newer crate (#7739)

# Description

This PR updates the base64 crate, which has changed significantly, so
all the base64 implementations had to be changed too. Tests pass. I hope
that's enough.

# User-Facing Changes

None, except added a new character encoding imap-mutf7 as mutf7.

# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
This commit is contained in:
Darren Schroeder
2023-01-13 07:16:14 -06:00
committed by GitHub
parent 2ee2370a71
commit 835bbb2e44
5 changed files with 111 additions and 54 deletions

View File

@ -1,19 +1,16 @@
use base64::encode;
use base64::{alphabet, engine::general_purpose::PAD, engine::GeneralPurpose, Engine};
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::util::BufferedReader;
use nu_protocol::RawStream;
use nu_protocol::{
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use reqwest::blocking::Response;
use reqwest::StatusCode;
use std::collections::HashMap;
use std::io::BufReader;
use reqwest::StatusCode;
use std::path::PathBuf;
use std::str::FromStr;
use std::time::Duration;
@ -165,10 +162,24 @@ fn helper(
let timeout = args.timeout;
let headers = args.headers;
let raw = args.raw;
let base64_engine = GeneralPurpose::new(&alphabet::STANDARD, PAD);
let login = match (user, password) {
(Some(user), Some(password)) => Some(encode(format!("{}:{}", user, password))),
(Some(user), _) => Some(encode(format!("{}:", user))),
(_, Some(password)) => Some(encode(format!(":{}", password))),
(Some(user), Some(password)) => {
let mut enc_str = String::new();
base64_engine.encode_string(&format!("{}:{}", user, password), &mut enc_str);
Some(enc_str)
}
(Some(user), _) => {
let mut enc_str = String::new();
base64_engine.encode_string(&format!("{}:", user), &mut enc_str);
Some(enc_str)
}
(_, Some(password)) => {
let mut enc_str = String::new();
base64_engine.encode_string(&format!(":{}", password), &mut enc_str);
Some(enc_str)
}
_ => None,
};

View File

@ -1,19 +1,18 @@
use crate::formats::value_to_json_value;
use base64::encode;
use base64::{alphabet, engine::general_purpose::PAD, engine::GeneralPurpose, Engine};
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::util::BufferedReader;
use nu_protocol::RawStream;
use reqwest::{blocking::Response, StatusCode};
use std::path::PathBuf;
use std::str::FromStr;
use nu_protocol::{
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use reqwest::{blocking::Response, StatusCode};
use std::collections::HashMap;
use std::io::BufReader;
use std::path::PathBuf;
use std::str::FromStr;
#[derive(Clone)]
pub struct SubCommand;
@ -186,9 +185,19 @@ fn helper(
let headers = args.headers;
let location = url;
let raw = args.raw;
let base64_engine = GeneralPurpose::new(&alphabet::STANDARD, PAD);
let login = match (user, password) {
(Some(user), Some(password)) => Some(encode(&format!("{}:{}", user, password))),
(Some(user), _) => Some(encode(&format!("{}:", user))),
(Some(user), Some(password)) => {
let mut enc_str = String::new();
base64_engine.encode_string(&format!("{}:{}", user, password), &mut enc_str);
Some(enc_str)
}
(Some(user), _) => {
let mut enc_str = String::new();
base64_engine.encode_string(&format!("{}:", user), &mut enc_str);
Some(enc_str)
}
_ => None,
};

View File

@ -1,5 +1,8 @@
use crate::input_handler::{operate as general_operate, CmdArgument};
use base64::{decode_config, encode_config};
use base64::{
alphabet, engine::general_purpose::NO_PAD, engine::general_purpose::PAD,
engine::GeneralPurpose, Engine,
};
use nu_engine::CallExt;
use nu_protocol::ast::{Call, CellPath};
use nu_protocol::engine::{EngineState, Stack};
@ -7,7 +10,7 @@ use nu_protocol::{PipelineData, ShellError, Span, Spanned, Value};
pub const CHARACTER_SET_DESC: &str = "specify the character rules for encoding the input.\n\
\tValid values are 'standard', 'standard-no-padding', 'url-safe', 'url-safe-no-padding',\
'binhex', 'bcrypt', 'crypt'";
'binhex', 'bcrypt', 'crypt', 'mutf7'";
#[derive(Clone)]
pub struct Base64Config {
@ -78,14 +81,15 @@ fn action(
let output_binary = args.binary;
let config_character_set = &base64_config.character_set;
let base64_config_enum: base64::Config = match config_character_set.item.as_str() {
"standard" => base64::STANDARD,
"standard-no-padding" => base64::STANDARD_NO_PAD,
"url-safe" => base64::URL_SAFE,
"url-safe-no-padding" => base64::URL_SAFE_NO_PAD,
"binhex" => base64::BINHEX,
"bcrypt" => base64::BCRYPT,
"crypt" => base64::CRYPT,
let base64_engine: GeneralPurpose = match config_character_set.item.as_str() {
"standard" => GeneralPurpose::new(&alphabet::STANDARD, PAD),
"standard-no-padding" => GeneralPurpose::new(&alphabet::STANDARD, NO_PAD),
"url-safe" => GeneralPurpose::new(&alphabet::URL_SAFE, PAD),
"url-safe-no-padding" => GeneralPurpose::new(&alphabet::URL_SAFE, NO_PAD),
"bcrypt" => GeneralPurpose::new(&alphabet::BCRYPT, NO_PAD),
"binhex" => GeneralPurpose::new(&alphabet::BIN_HEX, NO_PAD),
"crypt" => GeneralPurpose::new(&alphabet::CRYPT, NO_PAD),
"mutf7" => GeneralPurpose::new(&alphabet::IMAP_MUTF7, NO_PAD),
not_valid => return Value::Error { error:ShellError::GenericError(
"value is not an accepted character set".to_string(),
format!(
@ -102,7 +106,24 @@ fn action(
Value::Error { .. } => input.clone(),
Value::Binary { val, .. } => match base64_config.action_type {
ActionType::Encode => {
Value::string(encode_config(val, base64_config_enum), command_span)
let mut enc_vec = Vec::new();
enc_vec.resize(val.len() * 4 / 3 + 4, 0);
let bytes_written = match base64_engine.encode_slice(val, &mut enc_vec) {
Ok(bytes_written) => bytes_written,
Err(err) => {
return Value::Error {
error: ShellError::GenericError(
"Error encoding data".into(),
err.to_string(),
Some(Span::unknown()),
None,
Vec::new(),
),
}
}
};
enc_vec.truncate(bytes_written);
Value::string(std::str::from_utf8(&enc_vec).unwrap_or(""), command_span)
}
ActionType::Decode => Value::Error {
error: ShellError::UnsupportedInput(
@ -120,7 +141,9 @@ fn action(
} => {
match base64_config.action_type {
ActionType::Encode => {
Value::string(encode_config(val, base64_config_enum), command_span)
let mut enc_str = String::new();
base64_engine.encode_string(val, &mut enc_str);
Value::string(enc_str, command_span)
}
ActionType::Decode => {
@ -128,7 +151,8 @@ fn action(
let val = val.clone();
let val = val.replace("\r\n", "").replace('\n', "");
match decode_config(&val, base64_config_enum) {
//match Engine::decode_string(&val, base64_engine) {
match base64_engine.decode(&val) {
Ok(decoded_value) => {
if output_binary {
Value::binary(decoded_value, command_span)