@@ -88,7 +88,7 @@ maybe_file(Req, Prefix, Dir) ->
88
88
89
89
% % santize the path ensuring the request doesn't access any parent
90
90
% % directories ... and reattach the slash if deemed safe
91
- SafePath = case filename : safe_relative_path (RawPath ) of
91
+ SafePath = case safe_relative_path (RawPath ) of
92
92
unsafe ->
93
93
throw (? NOT_FOUND );
94
94
% % return type quirk work around
@@ -110,3 +110,43 @@ maybe_file(Req, Prefix, Dir) ->
110
110
_ ->
111
111
nothing
112
112
end .
113
+
114
+
115
+ % % OTP_RELEASE macro was introduced in 21, `filename:safe_relative_path/1' in
116
+ % % 19.3.
117
+ -ifdef (OTP_RELEASE ).
118
+ -ifdef (? OTP_RELEASE >= 21 ).
119
+ safe_relative_path (Path ) ->
120
+ filename :safe_relative_path (Path ).
121
+ -endif .
122
+ -else .
123
+
124
+ % % @doc Backport of `filename:safe_relative_path/1' from 19.3. This code was
125
+ % % lifted from:
126
+ % % https://github.com/erlang/otp/blob/master/lib/stdlib/src/filename.erl#L811
127
+ -spec safe_relative_path (binary ()) -> unsafe | file :name_all ().
128
+ safe_relative_path (Path ) ->
129
+ case filename :pathtype (Path ) of
130
+ relative ->
131
+ Cs0 = filename :split (Path ),
132
+ safe_relative_path_1 (Cs0 , []);
133
+ _ ->
134
+ unsafe
135
+ end .
136
+
137
+ safe_relative_path_1 ([<<" ." >>|T ], Acc ) ->
138
+ safe_relative_path_1 (T , Acc );
139
+ safe_relative_path_1 ([<<" .." >>|T ], Acc ) ->
140
+ climb (T , Acc );
141
+ safe_relative_path_1 ([H |T ], Acc ) ->
142
+ safe_relative_path_1 (T , [H |Acc ]);
143
+ safe_relative_path_1 ([], []) ->
144
+ [];
145
+ safe_relative_path_1 ([], Acc ) ->
146
+ filename :join (lists :reverse (Acc )).
147
+
148
+ climb (_ , []) ->
149
+ unsafe ;
150
+ climb (T , [_ |Acc ]) ->
151
+ safe_relative_path_1 (T , Acc ).
152
+ -endif .
0 commit comments