Implement dir type and add Zstd compression
This commit is contained in:
parent
6e71ba1c1c
commit
5b976e6bac
89
config.go
89
config.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/tar"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/pkg/browser"
|
"github.com/pkg/browser"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
@ -10,6 +11,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create config type to store action type and data
|
// Create config type to store action type and data
|
||||||
@ -63,6 +65,42 @@ func (config *Config) CollectFiles(dir string) {
|
|||||||
if err != nil { log.Fatal().Err(err).Msg("Error copying data to file") }
|
if err != nil { log.Fatal().Err(err).Msg("Error copying data to file") }
|
||||||
// Replace file path in config.ActionData with file name
|
// Replace file path in config.ActionData with file name
|
||||||
config.ActionData = filepath.Base(config.ActionData)
|
config.ActionData = filepath.Base(config.ActionData)
|
||||||
|
} else if config.ActionType == "dir" {
|
||||||
|
// Create tar archive
|
||||||
|
tarFile, err := os.Create(dir + "/" + filepath.Base(config.ActionData) + ".tar")
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error creating file") }
|
||||||
|
// Close tar file at the end of this function
|
||||||
|
defer tarFile.Close()
|
||||||
|
// Create writer for tar archive
|
||||||
|
tarArchiver := tar.NewWriter(tarFile)
|
||||||
|
// Close archiver at the end of this function
|
||||||
|
defer tarArchiver.Close()
|
||||||
|
// Walk given directory
|
||||||
|
err = filepath.Walk(config.ActionData, func(path string, info os.FileInfo, err error) error {
|
||||||
|
// Return if error walking
|
||||||
|
if err != nil { return err }
|
||||||
|
// Skip if file is not normal mode
|
||||||
|
if !info.Mode().IsRegular() { return nil }
|
||||||
|
// Create tar header for file
|
||||||
|
header, err := tar.FileInfoHeader(info, info.Name())
|
||||||
|
if err != nil { return err }
|
||||||
|
// Change header name to reflect decompressed filepath
|
||||||
|
header.Name = strings.TrimPrefix(strings.ReplaceAll(path, config.ActionData, ""), string(filepath.Separator))
|
||||||
|
// Write header to archive
|
||||||
|
if err := tarArchiver.WriteHeader(header); err != nil { return err }
|
||||||
|
// Open source file
|
||||||
|
src, err := os.Open(path)
|
||||||
|
if err != nil { return err }
|
||||||
|
// Close source file at the end of this function
|
||||||
|
defer src.Close()
|
||||||
|
// Copy source bytes to tar archive
|
||||||
|
if _, err := io.Copy(tarArchiver, src); err != nil { return err }
|
||||||
|
// Return at the end of the function
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error creating tar archive") }
|
||||||
|
// Set config data to base path for receiver
|
||||||
|
config.ActionData = filepath.Base(config.ActionData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +118,9 @@ func (config *Config) ReadFile(filePath string) {
|
|||||||
|
|
||||||
// Execute action specified in config
|
// Execute action specified in config
|
||||||
func (config *Config) ExecuteAction(srcDir string) {
|
func (config *Config) ExecuteAction(srcDir string) {
|
||||||
|
// Get user's home directory
|
||||||
|
homeDir, err := os.UserHomeDir()
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error getting home directory") }
|
||||||
// Use ConsoleWriter logger
|
// Use ConsoleWriter logger
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{})
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{})
|
||||||
// If action is file
|
// If action is file
|
||||||
@ -89,9 +130,6 @@ func (config *Config) ExecuteAction(srcDir string) {
|
|||||||
if err != nil { log.Fatal().Err(err).Msg("Error reading file from config") }
|
if err != nil { log.Fatal().Err(err).Msg("Error reading file from config") }
|
||||||
// Close source file at the end of this function
|
// Close source file at the end of this function
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
// Get user's home directory
|
|
||||||
homeDir, err := os.UserHomeDir()
|
|
||||||
if err != nil { log.Fatal().Err(err).Msg("Error getting home directory") }
|
|
||||||
// Create file in user's Downloads directory
|
// Create file in user's Downloads directory
|
||||||
dst, err := os.Create(homeDir + "/Downloads/" + config.ActionData)
|
dst, err := os.Create(homeDir + "/Downloads/" + config.ActionData)
|
||||||
if err != nil { log.Fatal().Err(err).Msg("Error creating file") }
|
if err != nil { log.Fatal().Err(err).Msg("Error creating file") }
|
||||||
@ -105,6 +143,51 @@ func (config *Config) ExecuteAction(srcDir string) {
|
|||||||
// Attempt to open URL in browser
|
// Attempt to open URL in browser
|
||||||
err := browser.OpenURL(config.ActionData)
|
err := browser.OpenURL(config.ActionData)
|
||||||
if err != nil { log.Fatal().Err(err).Msg("Error opening browser") }
|
if err != nil { log.Fatal().Err(err).Msg("Error opening browser") }
|
||||||
|
// If action is dir
|
||||||
|
} else if config.ActionType == "dir" {
|
||||||
|
// Set destination directory to ~/Downloads/{dir name}
|
||||||
|
dstDir := homeDir + "/Downloads/" + config.ActionData
|
||||||
|
// Try to create destination directory
|
||||||
|
err := os.Mkdir(dstDir, 0755)
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error creating directory") }
|
||||||
|
// Try to open tar archive file
|
||||||
|
tarFile, err := os.Open(srcDir + "/" + config.ActionData + ".tar")
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error opening tar archive") }
|
||||||
|
// Close tar archive file at the end of this function
|
||||||
|
defer tarFile.Close()
|
||||||
|
// Create tar reader to unarchive tar archive
|
||||||
|
tarUnarchiver := tar.NewReader(tarFile)
|
||||||
|
// Loop to recursively unarchive tar file
|
||||||
|
unarchiveLoop: for {
|
||||||
|
// Jump to next header in tar archive
|
||||||
|
header, err := tarUnarchiver.Next()
|
||||||
|
switch {
|
||||||
|
// If EOF
|
||||||
|
case err == io.EOF:
|
||||||
|
// break loop
|
||||||
|
break unarchiveLoop
|
||||||
|
case err != nil:
|
||||||
|
log.Fatal().Err(err).Msg("Error unarchiving tar archive")
|
||||||
|
// If nil header
|
||||||
|
case header == nil:
|
||||||
|
// Skip
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Set target path to header name in destination dir
|
||||||
|
targetPath := filepath.Join(dstDir, header.Name)
|
||||||
|
switch header.Typeflag {
|
||||||
|
// If regular file
|
||||||
|
case tar.TypeReg:
|
||||||
|
// Try to create containing folder ignoring errors
|
||||||
|
_ = os.MkdirAll(strings.TrimSuffix(targetPath, filepath.Base(targetPath)), 0755)
|
||||||
|
// Create file with mode contained in header at target path
|
||||||
|
dstFile, err := os.OpenFile(targetPath, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error creating file during unarchiving") }
|
||||||
|
// Copy data from tar archive into file
|
||||||
|
_, err = io.Copy(dstFile, tarUnarchiver)
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error copying data to file") }
|
||||||
|
}
|
||||||
|
}
|
||||||
// Catchall
|
// Catchall
|
||||||
} else {
|
} else {
|
||||||
// Log unknown action type
|
// Log unknown action type
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"github.com/klauspost/compress/zstd"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"io"
|
"io"
|
||||||
@ -17,12 +19,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Encrypt given file using the shared key
|
// Encrypt given file using the shared key
|
||||||
func EncryptFile(filePath string, newFilePath string, sharedKey string) {
|
func CompressAndEncryptFile(filePath string, newFilePath string, sharedKey string) {
|
||||||
// Use ConsoleWriter logger
|
// Use ConsoleWriter logger
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{})
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{})
|
||||||
// Read data from file
|
// Read data from file
|
||||||
data, err := ioutil.ReadFile(filePath)
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error opening file") }
|
||||||
|
compressedBuffer := new(bytes.Buffer)
|
||||||
|
zstdEncoder, err := zstd.NewWriter(compressedBuffer)
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error creating Zstd encoder") }
|
||||||
|
_, err = io.Copy(zstdEncoder, file)
|
||||||
if err != nil { log.Fatal().Err(err).Msg("Error reading file") }
|
if err != nil { log.Fatal().Err(err).Msg("Error reading file") }
|
||||||
|
zstdEncoder.Close()
|
||||||
|
data, err := ioutil.ReadAll(compressedBuffer)
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error reading compressed buffer") }
|
||||||
// Create md5 hash of password in order to make it the required size
|
// Create md5 hash of password in order to make it the required size
|
||||||
md5Hash := md5.New()
|
md5Hash := md5.New()
|
||||||
md5Hash.Write([]byte(sharedKey))
|
md5Hash.Write([]byte(sharedKey))
|
||||||
@ -54,7 +64,7 @@ func EncryptFile(filePath string, newFilePath string, sharedKey string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt given file using the shared key
|
// Decrypt given file using the shared key
|
||||||
func DecryptFile(filePath string, newFilePath string, sharedKey string) {
|
func DecryptAndDecompressFile(filePath string, newFilePath string, sharedKey string) {
|
||||||
// Use ConsoleWriter logger
|
// Use ConsoleWriter logger
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{})
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Hook(FatalHook{})
|
||||||
// Read data from file
|
// Read data from file
|
||||||
@ -76,16 +86,19 @@ func DecryptFile(filePath string, newFilePath string, sharedKey string) {
|
|||||||
// Decrypt data
|
// Decrypt data
|
||||||
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
|
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
|
||||||
if err != nil { log.Fatal().Err(err).Msg("Error decrypting data") }
|
if err != nil { log.Fatal().Err(err).Msg("Error decrypting data") }
|
||||||
|
zstdDecoder, err := zstd.NewReader(bytes.NewBuffer(plaintext))
|
||||||
|
if err != nil { log.Fatal().Err(err).Msg("Error creating Zstd decoder") }
|
||||||
// Create new file
|
// Create new file
|
||||||
newFile, err := os.Create(newFilePath)
|
newFile, err := os.Create(newFilePath)
|
||||||
if err != nil { log.Fatal().Err(err).Msg("Error creating file") }
|
if err != nil { log.Fatal().Err(err).Msg("Error creating file") }
|
||||||
// Defer file close
|
// Defer file close
|
||||||
defer newFile.Close()
|
defer newFile.Close()
|
||||||
// Write ciphertext to new file
|
// Write plaintext to new file
|
||||||
bytesWritten, err := newFile.Write(plaintext)
|
bytesWritten, err := io.Copy(newFile, zstdDecoder)
|
||||||
if err != nil { log.Fatal().Err(err).Msg("Error writing to file") }
|
if err != nil { log.Fatal().Err(err).Msg("Error writing to file") }
|
||||||
|
zstdDecoder.Close()
|
||||||
// Log bytes written and to which file
|
// Log bytes written and to which file
|
||||||
log.Info().Str("file", filepath.Base(newFilePath)).Msg("Wrote " + strconv.Itoa(bytesWritten) + " bytes")
|
log.Info().Str("file", filepath.Base(newFilePath)).Msg("Wrote " + strconv.Itoa(int(bytesWritten)) + " bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encrypt files in given directory using shared key
|
// Encrypt files in given directory using shared key
|
||||||
@ -99,7 +112,7 @@ func EncryptFiles(dir string, sharedKey string) {
|
|||||||
// If file is not a directory and is not the key
|
// If file is not a directory and is not the key
|
||||||
if !info.IsDir() && !strings.Contains(path, "key.aes"){
|
if !info.IsDir() && !strings.Contains(path, "key.aes"){
|
||||||
// Encrypt the file using shared key, appending .enc
|
// Encrypt the file using shared key, appending .enc
|
||||||
EncryptFile(path, path + ".enc", sharedKey)
|
CompressAndEncryptFile(path, path + ".zst.enc", sharedKey)
|
||||||
// Remove unencrypted file
|
// Remove unencrypted file
|
||||||
err := os.Remove(path)
|
err := os.Remove(path)
|
||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
@ -121,7 +134,7 @@ func DecryptFiles(dir string, sharedKey string) {
|
|||||||
// If file is not a directory and is encrypted
|
// If file is not a directory and is encrypted
|
||||||
if !info.IsDir() && strings.Contains(path, ".enc") {
|
if !info.IsDir() && strings.Contains(path, ".enc") {
|
||||||
// Decrypt the file using the shared key, removing .enc
|
// Decrypt the file using the shared key, removing .enc
|
||||||
DecryptFile(path, strings.TrimSuffix(path, ".enc"), sharedKey)
|
DecryptAndDecompressFile(path, strings.TrimSuffix(path, ".zst.enc"), sharedKey)
|
||||||
}
|
}
|
||||||
// Return nil if no errors occurred
|
// Return nil if no errors occurred
|
||||||
return nil
|
return nil
|
||||||
|
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ go 1.15
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/grandcat/zeroconf v1.0.0
|
github.com/grandcat/zeroconf v1.0.0
|
||||||
|
github.com/klauspost/compress v1.11.3
|
||||||
github.com/pkg/browser v0.0.0-20201112035734-206646e67786
|
github.com/pkg/browser v0.0.0-20201112035734-206646e67786
|
||||||
github.com/rs/zerolog v1.20.0
|
github.com/rs/zerolog v1.20.0
|
||||||
)
|
)
|
||||||
|
2
go.sum
2
go.sum
@ -3,6 +3,8 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
|
|||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
|
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
|
||||||
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
|
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
|
||||||
|
github.com/klauspost/compress v1.11.3 h1:dB4Bn0tN3wdCzQxnS8r06kV74qN/TAfaIS0bVE8h3jc=
|
||||||
|
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
|
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
|
||||||
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||||
github.com/pkg/browser v0.0.0-20201112035734-206646e67786 h1:4Gk0Dsp90g2YwfsxDOjvkEIgKGh+2R9FlvormRycveA=
|
github.com/pkg/browser v0.0.0-20201112035734-206646e67786 h1:4Gk0Dsp90g2YwfsxDOjvkEIgKGh+2R9FlvormRycveA=
|
||||||
|
Reference in New Issue
Block a user