diff --git a/files.go b/files.go index 8609567..7d11d6e 100644 --- a/files.go +++ b/files.go @@ -19,7 +19,7 @@ package main import ( "bufio" "bytes" - "encoding/hex" + "ekyu.moe/base91" "errors" "fmt" "github.com/rs/zerolog" @@ -29,10 +29,45 @@ import ( "net" "os" "path/filepath" + "regexp" "strconv" "strings" ) +// Encode byte slice to base91 encoded, escaped string for transmission +func EncodeToSafeString(data []byte) string { + // Encode data to base91 string + base91Data := base91.EncodeToString(data) + // Create regex to match |, ;, and % + escapeRegex := regexp.MustCompile(`[|;%]`) + // Map each character to its escape code + escapeMap := map[string]string{"|": "%7C", ";": "%3B", "%": "%25"} + // Replace all matched characters in accordance with the function + escapedBase91Data := escapeRegex.ReplaceAllStringFunc(base91Data, func(in string) string { + // Return character mapping + return escapeMap[in] + }) + // Return escaped base91 string + return escapedBase91Data +} + +// Decode base91 encoded, escaped string to byte slice +func DecodeSafeString(base91Str string) ([]byte, error) { + // Create regex to match %7C, %3B, %25 + unescapeRegex := regexp.MustCompile(`%7C|%3B|%25`) + // Map each escape code to its character + escapeMap := map[string]string{"%7C": "|", "%3B": ";", "%25": "%"} + // Replace all matched characters in accordance with the function + base91Data := unescapeRegex.ReplaceAllStringFunc(base91Str, func(in string) string { + // Return escape code mapping + return escapeMap[in] + }) + // Decode unescaped base91 string + data := base91.DecodeString(base91Data) + // Return byte slice + return data, nil +} + // Save encrypted key to file func SaveEncryptedKey(encryptedKey []byte, filePath string) { // Use ConsoleWriter logger @@ -100,7 +135,7 @@ connectionLoop: log.Fatal().Err(err).Msg("Error reading key") } // Write saved key to ResponseWriter - _, err = fmt.Fprintln(connection, "OK;"+hex.EncodeToString(key)+";") + _, err = fmt.Fprintln(connection, "OK;"+EncodeToSafeString(key)+";") if err != nil { log.Fatal().Err(err).Msg("Error writing response") } @@ -152,8 +187,8 @@ connectionLoop: // Inform user client has requested a file log.Info().Str("file", file).Msg("File requested") } - // Write file as hex to connection - _, err = fmt.Fprintln(connection, "OK;"+hex.EncodeToString(fileData)+";") + // Write file as base91 to connection + _, err = fmt.Fprintln(connection, "OK;"+EncodeToSafeString(fileData)+";") if err != nil { log.Fatal().Err(err).Msg("Error writing response") } @@ -243,8 +278,8 @@ func RecvFiles(connection net.Conn) { if err != nil { log.Fatal().Err(err).Msg("Error creating file") } - // Decode file data from hex string - fileData, err := hex.DecodeString(strings.TrimSpace(procMessage[1])) + // Decode file data from base91 string + fileData, err := DecodeSafeString(strings.TrimSpace(procMessage[1])) if err != nil { log.Fatal().Err(err).Msg("Error decoding hex") } diff --git a/go.mod b/go.mod index c6bfaf3..b67ed97 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module opensend go 1.15 require ( + ekyu.moe/base91 v0.2.3 github.com/grandcat/zeroconf v1.0.0 github.com/klauspost/compress v1.11.3 github.com/pelletier/go-toml v1.8.1 diff --git a/go.sum b/go.sum index 5e58ece..350c1e3 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +ekyu.moe/base91 v0.2.3 h1:1jCZrrpWjDSMMjjU9LANfQV+n7EHeW0OQ0MO9fpDRHg= +ekyu.moe/base91 v0.2.3/go.mod h1:/qmmaFUj5d0p9xcpj8beZDj33yXrc54eGU+hO/V5vuo= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= diff --git a/keyCrypto.go b/keyCrypto.go index 832c188..5f9d4ba 100644 --- a/keyCrypto.go +++ b/keyCrypto.go @@ -21,7 +21,6 @@ import ( "crypto/rand" "crypto/rsa" "crypto/sha256" - "encoding/hex" "fmt" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -63,8 +62,8 @@ func GetKey(connection net.Conn) []byte { procMessage := strings.Split(strings.TrimSpace(message), ";") // If ok code returned if procMessage[0] == "OK" { - // Decode received hex string into key - key, err := hex.DecodeString(procMessage[1]) + // Decode received safe base91 string into key + key, err := DecodeSafeString(procMessage[1]) if err != nil { log.Fatal().Err(err).Msg("Error reading key") } diff --git a/main.go b/main.go index 9c8a70d..29cf070 100644 --- a/main.go +++ b/main.go @@ -34,6 +34,7 @@ import ( ) var workDir *string +var destDir *string func main() { // Use ConsoleWriter logger @@ -42,8 +43,10 @@ func main() { // Create --send-to flag to send to a specific IP sendTo := flag.String("send-to", "", "Use IP address of receiver instead of mDNS") // Create --dest-dir flag to save to a specified folder - destDir := flag.String("dest-dir", "", "Destination directory for files or dirs sent over opensend") + destDir = flag.String("dest-dir", "", "Destination directory for files or dirs sent over opensend") + // Create --work-dir flag to perform operations in a specified directory workDir = flag.String("work-dir", "", "Working directory for opensend") + // Create --config to select config file to use givenCfgPath := flag.String("config", "", "Opensend config to use") // Create --skip-mdns to skip service registration skipMdns := flag.Bool("skip-mdns", false, "Skip zeroconf service registration (use if mdns fails)") @@ -84,6 +87,15 @@ func main() { } } + // If destination directory flag not provided + if *destDir == "" { + // If receiver flag provided + if *recvFlag { + // Set destination directory to receiver as defined in config + *destDir = ExpandPath(config.Receiver.DestDir) + } + } + // If target flag provided if *targetFlag != "" { // Set IP to target's IP