137 lines
2.9 KiB
Go
137 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(closeCmd)
|
|
closeCmd.Flags().StringVarP(&closeFlagOutput, "output", "o", "", "specify output file (`-` for stdout)")
|
|
}
|
|
|
|
var (
|
|
closeFlagOutput string
|
|
closeCmdHelp = "usage: jess close <file> with <envelope name>"
|
|
|
|
closeCmd = &cobra.Command{
|
|
Use: "close <file> with <envelope name>",
|
|
Short: "encrypt file",
|
|
Long: "encrypt file with the given envelope. Use `-` to use stdin",
|
|
DisableFlagsInUseLine: true,
|
|
PreRunE: requireTrustStore,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
registerPasswordCallbacks()
|
|
|
|
// check args
|
|
if len(args) != 3 || args[1] != "with" {
|
|
return errors.New(closeCmdHelp)
|
|
}
|
|
|
|
// get envelope
|
|
envelope, err := trustStore.GetEnvelope(args[2])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// create session (check envelope)
|
|
session, err := envelope.Correspondence(trustStore)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// check filenames
|
|
filename := args[0]
|
|
outputFilename := closeFlagOutput
|
|
if outputFilename == "" {
|
|
if strings.HasSuffix(filename, letterFileExtension) {
|
|
return errors.New("cannot automatically derive output filename, please specify with --output")
|
|
}
|
|
outputFilename = filename + letterFileExtension
|
|
}
|
|
// check input file
|
|
if filename != "-" {
|
|
fileInfo, err := os.Stat(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if fileInfo.Size() > warnFileSize {
|
|
confirmed, err := confirm("Input file is really big (%s) and jess needs to load it fully to memory, continue?", true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !confirmed {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
// check output file
|
|
if outputFilename != "-" {
|
|
_, err = os.Stat(outputFilename)
|
|
if err == nil {
|
|
confirmed, err := confirm("Output file already exists, overwrite?", true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !confirmed {
|
|
return nil
|
|
}
|
|
} else if !errors.Is(err, fs.ErrNotExist) {
|
|
return fmt.Errorf("failed to access output file: %w", err)
|
|
}
|
|
}
|
|
|
|
// load file
|
|
var data []byte
|
|
if filename == "-" {
|
|
data, err = io.ReadAll(os.Stdin)
|
|
} else {
|
|
data, err = os.ReadFile(filename)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// encrypt
|
|
letter, err := session.Close(data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// to file format
|
|
c, err := letter.ToFileFormat()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// open file for writing
|
|
var file *os.File
|
|
if outputFilename == "-" {
|
|
file = os.Stdout
|
|
} else {
|
|
file, err = os.OpenFile(
|
|
outputFilename,
|
|
os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
|
|
0o0600,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// write
|
|
err = c.WriteAllTo(file)
|
|
if err != nil {
|
|
_ = file.Close()
|
|
return err
|
|
}
|
|
return file.Close()
|
|
},
|
|
}
|
|
)
|