1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 package org.eclipse.jgit.transport;
46
47 import java.io.IOException;
48 import java.net.URISyntaxException;
49 import java.text.MessageFormat;
50 import java.util.Set;
51 import java.util.function.Supplier;
52
53 import org.eclipse.jgit.errors.ConfigInvalidException;
54 import org.eclipse.jgit.internal.JGitText;
55 import org.eclipse.jgit.lib.Config;
56 import org.eclipse.jgit.lib.StoredConfig;
57 import org.eclipse.jgit.util.StringUtils;
58 import org.eclipse.jgit.util.SystemReader;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62
63
64
65
66
67
68
69
70 public class HttpConfig {
71
72 private static final Logger LOG = LoggerFactory.getLogger(HttpConfig.class);
73
74 private static final String FTP = "ftp";
75
76
77 public static final String HTTP = "http";
78
79
80 public static final String FOLLOW_REDIRECTS_KEY = "followRedirects";
81
82
83 public static final String MAX_REDIRECTS_KEY = "maxRedirects";
84
85
86 public static final String POST_BUFFER_KEY = "postBuffer";
87
88
89 public static final String SSL_VERIFY_KEY = "sslVerify";
90
91 private static final String MAX_REDIRECT_SYSTEM_PROPERTY = "http.maxRedirects";
92
93 private static final int DEFAULT_MAX_REDIRECTS = 5;
94
95 private static final int MAX_REDIRECTS = (new Supplier<Integer>() {
96
97 @Override
98 public Integer get() {
99 String rawValue = SystemReader.getInstance()
100 .getProperty(MAX_REDIRECT_SYSTEM_PROPERTY);
101 Integer value = Integer.valueOf(DEFAULT_MAX_REDIRECTS);
102 if (rawValue != null) {
103 try {
104 value = Integer.valueOf(Integer.parseUnsignedInt(rawValue));
105 } catch (NumberFormatException e) {
106 LOG.warn(MessageFormat.format(
107 JGitText.get().invalidSystemProperty,
108 MAX_REDIRECT_SYSTEM_PROPERTY, rawValue, value));
109 }
110 }
111 return value;
112 }
113 }).get().intValue();
114
115
116
117
118 public enum HttpRedirectMode implements Config.ConfigEnum {
119
120
121 TRUE("true"),
122
123
124
125
126 INITIAL("initial"),
127
128 FALSE("false");
129
130 private final String configValue;
131
132 private HttpRedirectMode(String configValue) {
133 this.configValue = configValue;
134 }
135
136 @Override
137 public String toConfigValue() {
138 return configValue;
139 }
140
141 @Override
142 public boolean matchConfigValue(String s) {
143 return configValue.equals(s);
144 }
145 }
146
147 private int postBuffer;
148
149 private boolean sslVerify;
150
151 private HttpRedirectMode followRedirects;
152
153 private int maxRedirects;
154
155
156
157
158
159
160 public int getPostBuffer() {
161 return postBuffer;
162 }
163
164
165
166
167
168
169 public boolean isSslVerify() {
170 return sslVerify;
171 }
172
173
174
175
176
177
178 public HttpRedirectMode getFollowRedirects() {
179 return followRedirects;
180 }
181
182
183
184
185
186
187 public int getMaxRedirects() {
188 return maxRedirects;
189 }
190
191
192
193
194
195
196
197
198
199
200 public HttpConfig(Config config, URIish uri) {
201 init(config, uri);
202 }
203
204
205
206
207
208
209
210
211 public HttpConfig(URIish uri) {
212 StoredConfig userConfig = null;
213 try {
214 userConfig = SystemReader.getInstance().getUserConfig();
215 } catch (IOException | ConfigInvalidException e) {
216
217 LOG.error(e.getMessage(), e);
218 init(new Config(), uri);
219 return;
220 }
221 init(userConfig, uri);
222 }
223
224 private void init(Config config, URIish uri) {
225
226 int postBufferSize = config.getInt(HTTP, POST_BUFFER_KEY,
227 1 * 1024 * 1024);
228 boolean sslVerifyFlag = config.getBoolean(HTTP, SSL_VERIFY_KEY, true);
229 HttpRedirectMode followRedirectsMode = config.getEnum(
230 HttpRedirectMode.values(), HTTP, null,
231 FOLLOW_REDIRECTS_KEY, HttpRedirectMode.INITIAL);
232 int redirectLimit = config.getInt(HTTP, MAX_REDIRECTS_KEY,
233 MAX_REDIRECTS);
234 if (redirectLimit < 0) {
235 redirectLimit = MAX_REDIRECTS;
236 }
237 String match = findMatch(config.getSubsections(HTTP), uri);
238 if (match != null) {
239
240 postBufferSize = config.getInt(HTTP, match, POST_BUFFER_KEY,
241 postBufferSize);
242 sslVerifyFlag = config.getBoolean(HTTP, match, SSL_VERIFY_KEY,
243 sslVerifyFlag);
244 followRedirectsMode = config.getEnum(HttpRedirectMode.values(),
245 HTTP, match, FOLLOW_REDIRECTS_KEY, followRedirectsMode);
246 int newMaxRedirects = config.getInt(HTTP, match, MAX_REDIRECTS_KEY,
247 redirectLimit);
248 if (newMaxRedirects >= 0) {
249 redirectLimit = newMaxRedirects;
250 }
251 }
252 postBuffer = postBufferSize;
253 sslVerify = sslVerifyFlag;
254 followRedirects = followRedirectsMode;
255 maxRedirects = redirectLimit;
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269 private String findMatch(Set<String> names, URIish uri) {
270 String bestMatch = null;
271 int bestMatchLength = -1;
272 boolean withUser = false;
273 String uPath = uri.getPath();
274 boolean hasPath = !StringUtils.isEmptyOrNull(uPath);
275 if (hasPath) {
276 uPath = normalize(uPath);
277 if (uPath == null) {
278
279 return null;
280 }
281 }
282 for (String s : names) {
283 try {
284 URIish candidate = new URIish(s);
285
286 if (!compare(uri.getScheme(), candidate.getScheme())
287 || !compare(uri.getHost(), candidate.getHost())) {
288 continue;
289 }
290
291 if (defaultedPort(uri.getPort(),
292 uri.getScheme()) != defaultedPort(candidate.getPort(),
293 candidate.getScheme())) {
294 continue;
295 }
296
297 boolean hasUser = false;
298 if (candidate.getUser() != null) {
299 if (!candidate.getUser().equals(uri.getUser())) {
300 continue;
301 }
302 hasUser = true;
303 }
304
305 String cPath = candidate.getPath();
306 int matchLength = -1;
307 if (StringUtils.isEmptyOrNull(cPath)) {
308 matchLength = 0;
309 } else {
310 if (!hasPath) {
311 continue;
312 }
313
314 matchLength = segmentCompare(uPath, cPath);
315 if (matchLength < 0) {
316 continue;
317 }
318 }
319
320
321
322 if (matchLength > bestMatchLength || !withUser && hasUser
323 && matchLength >= 0 && matchLength == bestMatchLength) {
324 bestMatch = s;
325 bestMatchLength = matchLength;
326 withUser = hasUser;
327 }
328 } catch (URISyntaxException e) {
329 LOG.warn(MessageFormat
330 .format(JGitText.get().httpConfigInvalidURL, s));
331 }
332 }
333 return bestMatch;
334 }
335
336 private boolean compare(String a, String b) {
337 if (a == null) {
338 return b == null;
339 }
340 return a.equalsIgnoreCase(b);
341 }
342
343 private int defaultedPort(int port, String scheme) {
344 if (port >= 0) {
345 return port;
346 }
347 if (FTP.equalsIgnoreCase(scheme)) {
348 return 21;
349 } else if (HTTP.equalsIgnoreCase(scheme)) {
350 return 80;
351 } else {
352 return 443;
353 }
354 }
355
356 static int segmentCompare(String uriPath, String m) {
357
358
359 String matchPath = normalize(m);
360 if (matchPath == null || !uriPath.startsWith(matchPath)) {
361 return -1;
362 }
363
364
365
366 int uLength = uriPath.length();
367 int mLength = matchPath.length();
368 if (mLength == uLength || matchPath.charAt(mLength - 1) == '/'
369 || mLength < uLength && uriPath.charAt(mLength) == '/') {
370 return mLength;
371 }
372 return -1;
373 }
374
375 static String normalize(String path) {
376
377 int i = 0;
378 int length = path.length();
379 StringBuilder builder = new StringBuilder(length);
380 builder.append('/');
381 if (length > 0 && path.charAt(0) == '/') {
382 i = 1;
383 }
384 while (i < length) {
385 int slash = path.indexOf('/', i);
386 if (slash < 0) {
387 slash = length;
388 }
389 if (slash == i || slash == i + 1 && path.charAt(i) == '.') {
390
391 } else if (slash == i + 2 && path.charAt(i) == '.'
392 && path.charAt(i + 1) == '.') {
393
394 int l = builder.length() - 2;
395 while (l >= 0 && builder.charAt(l) != '/') {
396 l--;
397 }
398 if (l < 0) {
399 LOG.warn(MessageFormat.format(
400 JGitText.get().httpConfigCannotNormalizeURL, path));
401 return null;
402 }
403 builder.setLength(l + 1);
404 } else {
405
406 builder.append(path, i, Math.min(length, slash + 1));
407 }
408 i = slash + 1;
409 }
410 if (builder.length() > 1 && builder.charAt(builder.length() - 1) == '/'
411 && length > 0 && path.charAt(length - 1) != '/') {
412
413
414 builder.setLength(builder.length() - 1);
415 }
416 return builder.toString();
417 }
418 }