Skip to content
This repository was archived by the owner on Jan 12, 2022. It is now read-only.

Commit b9324c6

Browse files
committed
handle escaping more comprehensively
1 parent 325433c commit b9324c6

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

godotenv.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"errors"
1919
"os"
2020
"os/exec"
21+
"regexp"
2122
"strings"
2223
)
2324

@@ -218,7 +219,11 @@ func parseLine(line string) (key string, value string, err error) {
218219
key = strings.Trim(key, " ")
219220

220221
// Parse the value
221-
value = splitString[1]
222+
value = parseValue(splitString[1])
223+
return
224+
}
225+
226+
func parseValue(value string) string {
222227

223228
// trim
224229
value = strings.Trim(value, " ")
@@ -230,15 +235,23 @@ func parseLine(line string) (key string, value string, err error) {
230235
if first == last && strings.ContainsAny(first, `"'`) {
231236
// pull the quotes off the edges
232237
value = strings.Trim(value, `"'`)
233-
234-
// expand quotes
235-
value = strings.Replace(value, `\"`, `"`, -1)
236-
// expand newlines
237-
value = strings.Replace(value, `\n`, "\n", -1)
238+
// handle escapes
239+
escapeRegex := regexp.MustCompile(`\\.`)
240+
value = escapeRegex.ReplaceAllStringFunc(value, func(match string) string {
241+
c := strings.TrimPrefix(match, `\`)
242+
switch c {
243+
case "n":
244+
return "\n"
245+
case "r":
246+
return "\r"
247+
default:
248+
return c
249+
}
250+
})
238251
}
239252
}
240253

241-
return
254+
return value
242255
}
243256

244257
func isIgnoredLine(line string) bool {

godotenv_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@ func TestParsing(t *testing.T) {
238238
parseAndCompare(t, `FOO="ba#r"`, "FOO", "ba#r")
239239
parseAndCompare(t, "FOO='ba#r'", "FOO", "ba#r")
240240

241+
//newlines and backslashes should be escaped
242+
parseAndCompare(t, `FOO="bar\n\ b\az"`, "FOO", "bar\n baz")
243+
parseAndCompare(t, `FOO="bar\\\n\ b\az"`, "FOO", "bar\\\n baz")
244+
parseAndCompare(t, `FOO="bar\\r\ b\az"`, "FOO", "bar\\r baz")
245+
241246
// it 'throws an error if line format is incorrect' do
242247
// expect{env('lol$wut')}.to raise_error(Dotenv::FormatError)
243248
badlyFormattedLine := "lol$wut"

0 commit comments

Comments
 (0)