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