| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.core; | 5 part of dart.core; |
| 6 | 6 |
| 7 // Frequently used character codes. | 7 // Frequently used character codes. |
| 8 const int _SPACE = 0x20; | 8 const int _SPACE = 0x20; |
| 9 const int _PERCENT = 0x25; | 9 const int _PERCENT = 0x25; |
| 10 const int _PLUS = 0x2B; | 10 const int _PLUS = 0x2B; |
| (...skipping 4305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4316 return new _SimpleUri(newUri, | 4316 return new _SimpleUri(newUri, |
| 4317 base._schemeEnd, | 4317 base._schemeEnd, |
| 4318 base._hostStart, | 4318 base._hostStart, |
| 4319 base._portStart, | 4319 base._portStart, |
| 4320 base._pathStart, | 4320 base._pathStart, |
| 4321 ref._queryStart + delta, | 4321 ref._queryStart + delta, |
| 4322 ref._fragmentStart + delta, | 4322 ref._fragmentStart + delta, |
| 4323 base._schemeCache); | 4323 base._schemeCache); |
| 4324 } | 4324 } |
| 4325 // Merge paths. | 4325 // Merge paths. |
| 4326 if (base._uri.startsWith("../", base._pathStart)) { | |
| 4327 // Complex rare case, go slow. | |
| 4328 return _toNonSimple().resolveUri(ref); | |
| 4329 } | |
| 4330 | 4326 |
| 4331 // The RFC 3986 algorithm merges the base path without its final segment | 4327 // The RFC 3986 algorithm merges the base path without its final segment |
| 4332 // (anything after the final "/", or everything if the base path doesn't | 4328 // (anything after the final "/", or everything if the base path doesn't |
| 4333 // contain any "/"), and the reference path. | 4329 // contain any "/"), and the reference path. |
| 4334 // Then it removes "." and ".." segments using the remove-dot-segment | 4330 // Then it removes "." and ".." segments using the remove-dot-segment |
| 4335 // algorithm. | 4331 // algorithm. |
| 4336 // This code combines the two steps. It is simplified by knowing that | 4332 // This code combines the two steps. It is simplified by knowing that |
| 4337 // the base path contains no "." or ".." segments, and the reference | 4333 // the base path contains no "." or ".." segments, and the reference |
| 4338 // path can only contain leading ".." segments. | 4334 // path can only contain leading ".." segments. |
| 4339 | 4335 |
| 4340 String baseUri = base._uri; | 4336 String baseUri = base._uri; |
| 4341 String refUri = ref._uri; | 4337 String refUri = ref._uri; |
| 4342 int baseStart = base._pathStart; | 4338 int baseStart = base._pathStart; |
| 4343 int baseEnd = base._queryStart; | 4339 int baseEnd = base._queryStart; |
| 4340 while (baseUri.startsWith("../", baseStart)) baseStart += 3; |
| 4344 int refStart = ref._pathStart; | 4341 int refStart = ref._pathStart; |
| 4345 int refEnd = ref._queryStart; | 4342 int refEnd = ref._queryStart; |
| 4346 int backCount = 1; | |
| 4347 | 4343 |
| 4348 int slashCount = 0; | 4344 /// Count of leading ".." segments in reference path. |
| 4349 | 4345 /// The count is decremented when the segment is matched with a |
| 4350 // Count leading ".." segments in reference path. | 4346 /// segment of the base path, and both are then omitted from the result. |
| 4347 int backCount = 0; |
| 4348 /// Count "../" segments and advance `refStart` to after the segments. |
| 4351 while (refStart + 3 <= refEnd && refUri.startsWith("../", refStart)) { | 4349 while (refStart + 3 <= refEnd && refUri.startsWith("../", refStart)) { |
| 4352 refStart += 3; | 4350 refStart += 3; |
| 4353 backCount += 1; | 4351 backCount += 1; |
| 4354 } | 4352 } |
| 4355 | 4353 |
| 4356 // Extra slash inserted between base and reference path parts if | 4354 // Extra slash inserted between base and reference path parts if |
| 4357 // the base path contains any slashes. | 4355 // the base path contains any slashes, or empty string if none. |
| 4358 // (We could use a slash from the base path in most cases, but not if | 4356 // (We could use a slash from the base path in most cases, but not if |
| 4359 // we remove the entire base path). | 4357 // we remove the entire base path). |
| 4360 String insert = ""; | 4358 String insert = ""; |
| 4359 |
| 4360 /// Remove segments from the base path. |
| 4361 /// Start with the segment trailing the last slash, |
| 4362 /// then remove segments for each leading "../" segment |
| 4363 /// from the reference path, or as many of them as are available. |
| 4361 while (baseEnd > baseStart) { | 4364 while (baseEnd > baseStart) { |
| 4362 baseEnd--; | 4365 baseEnd--; |
| 4363 int char = baseUri.codeUnitAt(baseEnd); | 4366 int char = baseUri.codeUnitAt(baseEnd); |
| 4364 if (char == _SLASH) { | 4367 if (char == _SLASH) { |
| 4365 insert = "/"; | 4368 insert = "/"; |
| 4369 if (backCount == 0) break; |
| 4366 backCount--; | 4370 backCount--; |
| 4367 if (backCount == 0) break; | |
| 4368 } | 4371 } |
| 4369 } | 4372 } |
| 4370 // If the base URI has no scheme or authority (`_pathStart == 0`) | 4373 |
| 4371 // and a relative path, and we reached the beginning of the path, | 4374 if (baseEnd == baseStart && !base.hasScheme && !base.hasAbsolutePath) { |
| 4372 // we have a special case. | 4375 // If the base is *just* a relative path (no scheme or authority), |
| 4373 if (baseEnd == 0 && !base.hasAbsolutePath) { | 4376 // then merging with another relative path doesn't follow the |
| 4374 // Non-RFC 3986 behavior when resolving a purely relative path on top of | 4377 // RFC-3986 behavior. |
| 4375 // another relative path: Don't make the result absolute. | 4378 // Don't need to check `base.hasAuthority` since the base path is |
| 4379 // non-empty - if there is an authority, a non-empty path is absolute. |
| 4380 |
| 4381 // We reached the start of the base path, and want to stay relative, |
| 4382 // so don't insert a slash. |
| 4376 insert = ""; | 4383 insert = ""; |
| 4384 // If we reached the start of the base path with more "../" left over |
| 4385 // in the reference path, include those segments in the result. |
| 4386 refStart -= backCount * 3; |
| 4377 } | 4387 } |
| 4378 | 4388 |
| 4379 var delta = baseEnd - refStart + insert.length; | 4389 var delta = baseEnd - refStart + insert.length; |
| 4380 var newUri = "${base._uri.substring(0, baseEnd)}$insert" | 4390 var newUri = "${base._uri.substring(0, baseEnd)}$insert" |
| 4381 "${ref._uri.substring(refStart)}"; | 4391 "${ref._uri.substring(refStart)}"; |
| 4382 | 4392 |
| 4383 return new _SimpleUri(newUri, | 4393 return new _SimpleUri(newUri, |
| 4384 base._schemeEnd, | 4394 base._schemeEnd, |
| 4385 base._hostStart, | 4395 base._hostStart, |
| 4386 base._portStart, | 4396 base._portStart, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4458 int delta = (text.codeUnitAt(start + 4) ^ _COLON) * 3; | 4468 int delta = (text.codeUnitAt(start + 4) ^ _COLON) * 3; |
| 4459 delta |= text.codeUnitAt(start) ^ 0x64 /*d*/; | 4469 delta |= text.codeUnitAt(start) ^ 0x64 /*d*/; |
| 4460 delta |= text.codeUnitAt(start + 1) ^ 0x61 /*a*/; | 4470 delta |= text.codeUnitAt(start + 1) ^ 0x61 /*a*/; |
| 4461 delta |= text.codeUnitAt(start + 2) ^ 0x74 /*t*/; | 4471 delta |= text.codeUnitAt(start + 2) ^ 0x74 /*t*/; |
| 4462 delta |= text.codeUnitAt(start + 3) ^ 0x61 /*a*/; | 4472 delta |= text.codeUnitAt(start + 3) ^ 0x61 /*a*/; |
| 4463 return delta; | 4473 return delta; |
| 4464 } | 4474 } |
| 4465 | 4475 |
| 4466 /// Helper function returning the length of a string, or `0` for `null`. | 4476 /// Helper function returning the length of a string, or `0` for `null`. |
| 4467 int _stringOrNullLength(String s) => (s == null) ? 0 : s.length; | 4477 int _stringOrNullLength(String s) => (s == null) ? 0 : s.length; |
| OLD | NEW |