@@ -34,15 +34,16 @@ public class DotenvParser {
34
34
private final boolean throwIfMissing ;
35
35
private final boolean throwIfMalformed ;
36
36
37
- private final Predicate <String > isWhiteSpace = s -> matches (WHITE_SPACE_REGEX , s );
38
- private final Predicate <String > isComment = s -> s .startsWith ("#" ) || s .startsWith ("////" );
39
- private final Predicate <String > isQuoted = s -> s .startsWith ("\" " ) && s .endsWith ("\" " );
37
+ private static final Predicate <String > isWhiteSpace = s -> matches (WHITE_SPACE_REGEX , s );
38
+ private static final Predicate <String > isComment = s -> s .startsWith ("#" ) || s .startsWith ("////" );
39
+ private static final Predicate <String > isQuoted = s -> s . length () > 1 && s .startsWith ("\" " ) && s .endsWith ("\" " );
40
40
private final Function <String , DotenvEntry > parseLine = s -> matchEntry (DOTENV_ENTRY_REGEX , s );
41
41
42
42
/**
43
43
* Creates a dotenv parser
44
- * @param reader the dotenv reader
45
- * @param throwIfMissing if true, throws when the .env file is missing
44
+ *
45
+ * @param reader the dotenv reader
46
+ * @param throwIfMissing if true, throws when the .env file is missing
46
47
* @param throwIfMalformed if true, throws when the .env file is malformed
47
48
*/
48
49
public DotenvParser (final DotenvReader reader , final boolean throwIfMissing , final boolean throwIfMalformed ) {
@@ -53,6 +54,7 @@ public DotenvParser(final DotenvReader reader, final boolean throwIfMissing, fin
53
54
54
55
/**
55
56
* (Internal) parse the .env file
57
+ *
56
58
* @return a list of DotenvEntries
57
59
* @throws DotenvException if an error is encountered during the parse
58
60
*/
@@ -77,8 +79,13 @@ private void addNewEntry(final List<DotenvEntry> entries, final String line) {
77
79
return ;
78
80
}
79
81
82
+ if (!QuotedStringValidator .isValid (entry .getValue ())) {
83
+ if (throwIfMalformed )
84
+ throw new DotenvException ("Malformed entry, unmatched quotes " + line );
85
+ return ;
86
+ }
80
87
final var key = entry .getKey ();
81
- final var value = normalizeValue (entry .getValue ());
88
+ final var value = QuotedStringValidator . stripQuotes (entry .getValue ());
82
89
entries .add (new DotenvEntry (key , value ));
83
90
}
84
91
@@ -94,11 +101,6 @@ private List<String> lines() throws DotenvException {
94
101
}
95
102
}
96
103
97
- private String normalizeValue (final String value ) {
98
- final var tr = value .trim ();
99
- return isQuoted .test (tr ) ? tr .substring (1 , value .length () - 1 ) : tr ;
100
- }
101
-
102
104
private static boolean matches (final Pattern regex , final String text ) {
103
105
return regex .matcher (text ).matches ();
104
106
}
@@ -114,4 +116,40 @@ private static DotenvEntry matchEntry(final Pattern regex, final String text) {
114
116
private static boolean isBlank (String s ) {
115
117
return s == null || s .trim ().isEmpty ();
116
118
}
119
+
120
+ /**
121
+ * Internal: Validates quoted strings
122
+ */
123
+ private static class QuotedStringValidator {
124
+ private static boolean isValid (String input ) {
125
+ final var s = input .trim ();
126
+ if (!s .startsWith ("\" " ) && !s .endsWith ("\" " )) {
127
+ // not quoted, its valid
128
+ return true ;
129
+ }
130
+ if (input .length () == 1 || !(s .startsWith ("\" " ) && s .endsWith ("\" " ))) {
131
+ // doesn't start and end with quote
132
+ return false ;
133
+ }
134
+ // remove start end quote
135
+ var content = s .substring (1 , s .length () - 1 );
136
+ var quotePattern = Pattern .compile ("\" " );
137
+ var matcher = quotePattern .matcher (content );
138
+
139
+ // Check for unescaped quotes
140
+ while (matcher .find ()) {
141
+ int quoteIndex = matcher .start ();
142
+ // Check if the quote is escaped
143
+ if (quoteIndex == 0 || content .charAt (quoteIndex - 1 ) != '\\' ) {
144
+ return false ; // unescaped quote found
145
+ }
146
+ }
147
+ return true ; // No unescaped quotes found
148
+ }
149
+ private static String stripQuotes (String input ) {
150
+ var tr = input .trim ();
151
+ return isQuoted .test (tr ) ? tr .substring (1 , input .length () - 1 ) : tr ;
152
+ }
153
+ }
117
154
}
155
+
0 commit comments