@@ -34,6 +34,8 @@ public static function parse($entry)
34
34
*
35
35
* @param string $line
36
36
*
37
+ * @throws \Dotenv\Exception\InvalidFileException
38
+ *
37
39
* @return array
38
40
*/
39
41
private static function splitStringIntoParts ($ line )
@@ -45,6 +47,12 @@ private static function splitStringIntoParts($line)
45
47
list ($ name , $ value ) = array_map ('trim ' , explode ('= ' , $ line , 2 ));
46
48
}
47
49
50
+ if ($ name === '' ) {
51
+ throw new InvalidFileException (
52
+ self ::getErrorMessage ('an unexpected equals ' , $ line )
53
+ );
54
+ }
55
+
48
56
return [$ name , $ value ];
49
57
}
50
58
@@ -53,15 +61,37 @@ private static function splitStringIntoParts($line)
53
61
*
54
62
* @param string $name
55
63
*
64
+ * @throws \Dotenv\Exception\InvalidFileException
65
+ *
56
66
* @return string
57
67
*/
58
68
private static function sanitiseName ($ name )
59
69
{
60
- return trim (str_replace (['export ' , '\'' , '" ' ], '' , $ name ));
70
+ $ name = trim (str_replace (['export ' , '\'' , '" ' ], '' , $ name ));
71
+
72
+ if (!self ::isValidName ($ name )) {
73
+ throw new InvalidFileException (
74
+ self ::getErrorMessage ('an invalid name ' , $ name )
75
+ );
76
+ }
77
+
78
+ return $ name ;
61
79
}
62
80
63
81
/**
64
- * Strips quotes from the environment variable value.
82
+ * Is the given variable name valid?
83
+ *
84
+ * @param string $name
85
+ *
86
+ * @return bool
87
+ */
88
+ private static function isValidName ($ name )
89
+ {
90
+ return preg_match ('~\A[a-zA-Z0-9_.]+\z~ ' , $ name ) === 1 ;
91
+ }
92
+
93
+ /**
94
+ * Strips quotes and comments from the environment variable value.
65
95
*
66
96
* @param string|null $value
67
97
*
@@ -75,46 +105,77 @@ private static function sanitiseValue($value)
75
105
return $ value ;
76
106
}
77
107
78
- if (self ::beginsWithAQuote ($ value )) { // value starts with a quote
79
- $ quote = $ value [0 ];
80
- $ regexPattern = sprintf (
81
- '/^
82
- %1$s # match a quote at the start of the value
83
- ( # capturing sub-pattern used
84
- (?: # we do not need to capture this
85
- [^%1$s \\\\]+ # any character other than a quote or backslash
86
- | \\\\\\\\ # or two backslashes together
87
- | \\\\%1$s # or an escaped quote e.g \"
88
- )* # as many characters that match the previous rules
89
- ) # end of the capturing sub-pattern
90
- %1$s # and the closing quote
91
- .*$ # and discard any string after the closing quote
92
- /mx ' ,
93
- $ quote
94
- );
95
- $ value = preg_replace ($ regexPattern , '$1 ' , $ value );
96
- $ value = str_replace ("\\$ quote " , $ quote , $ value );
97
- $ value = str_replace ('\\\\' , '\\' , $ value );
98
- } else {
99
- $ parts = explode (' # ' , $ value , 2 );
100
- $ value = $ parts [0 ];
101
-
102
- // Unquoted values cannot contain whitespace
103
- if (preg_match ('/\s+/ ' , $ value ) > 0 ) {
104
- // Check if value is a comment (usually triggered when empty value with comment)
105
- if (preg_match ('/^#/ ' , $ value ) > 0 ) {
106
- $ value = '' ;
107
- } else {
108
- throw new InvalidFileException (
109
- 'Dotenv values containing spaces must be surrounded by quotes. '
110
- );
111
- }
108
+ if (self ::beginsWithAQuote ($ value )) {
109
+ return self ::processQuotedValue ($ value );
110
+ }
111
+
112
+ // Strip comments from the left
113
+ $ value = explode (' # ' , $ value , 2 )[0 ];
114
+
115
+ // Unquoted values cannot contain whitespace
116
+ if (preg_match ('/\s+/ ' , $ value ) > 0 ) {
117
+ // Check if value is a comment (usually triggered when empty value with comment)
118
+ if (preg_match ('/^#/ ' , $ value ) > 0 ) {
119
+ $ value = '' ;
120
+ } else {
121
+ throw new InvalidFileException (
122
+ self ::getErrorMessage ('an unexpected space ' , $ value )
123
+ );
112
124
}
113
125
}
114
126
115
127
return $ value ;
116
128
}
117
129
130
+ /**
131
+ * Strips quotes from the environment variable value.
132
+ *
133
+ * @param string $value
134
+ *
135
+ * @return string
136
+ */
137
+ private static function processQuotedValue ($ value )
138
+ {
139
+ $ quote = $ value [0 ];
140
+
141
+ $ pattern = sprintf (
142
+ '/^
143
+ %1$s # match a quote at the start of the value
144
+ ( # capturing sub-pattern used
145
+ (?: # we do not need to capture this
146
+ [^%1$s \\\\]+ # any character other than a quote or backslash
147
+ | \\\\\\\\ # or two backslashes together
148
+ | \\\\%1$s # or an escaped quote e.g \"
149
+ )* # as many characters that match the previous rules
150
+ ) # end of the capturing sub-pattern
151
+ %1$s # and the closing quote
152
+ .*$ # and discard any string after the closing quote
153
+ /mx ' ,
154
+ $ quote
155
+ );
156
+
157
+ $ value = preg_replace ($ pattern , '$1 ' , $ value );
158
+
159
+ return str_replace ('\\\\' , '\\' , str_replace ("\\$ quote " , $ quote , $ value ));
160
+ }
161
+
162
+ /**
163
+ * Generate a friendly error message.
164
+ *
165
+ * @param string $cause
166
+ * @param string $subject
167
+ *
168
+ * @return string
169
+ */
170
+ private static function getErrorMessage ($ cause , $ subject )
171
+ {
172
+ return sprintf (
173
+ 'Failed to parse dotenv file due to %s. Failed at [%s]. ' ,
174
+ $ cause ,
175
+ strtok ($ subject , "\n" )
176
+ );
177
+ }
178
+
118
179
/**
119
180
* Determine if the given string begins with a quote.
120
181
*
0 commit comments