safing-jess/cmd/cmd-close.go
2022-10-11 12:48:24 +02:00

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()
},
}
)