OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library path.context; | 5 library path.context; |
6 | 6 |
7 import 'characters.dart' as chars; | 7 import 'characters.dart' as chars; |
8 import 'internal_style.dart'; | 8 import 'internal_style.dart'; |
9 import 'style.dart'; | 9 import 'style.dart'; |
10 import 'parsed_path.dart'; | 10 import 'parsed_path.dart'; |
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 | 609 |
610 // Ignore multiple separators in a row. | 610 // Ignore multiple separators in a row. |
611 if (parentIsSeparator && style.isSeparator(lastCodeUnit)) { | 611 if (parentIsSeparator && style.isSeparator(lastCodeUnit)) { |
612 parentIndex++; | 612 parentIndex++; |
613 continue; | 613 continue; |
614 } else if (childIsSeparator && style.isSeparator(lastCodeUnit)) { | 614 } else if (childIsSeparator && style.isSeparator(lastCodeUnit)) { |
615 childIndex++; | 615 childIndex++; |
616 continue; | 616 continue; |
617 } | 617 } |
618 | 618 |
619 // If a dot comes after a separator or another dot, it may be a | 619 if (parentCodeUnit == chars.PERIOD) { |
620 // directory traversal operator. Otherwise, it's just a normal | 620 // If a dot comes after a separator, it may be a directory traversal |
621 // non-matching character. | 621 // operator. To check that, we need to know if it's followed by either |
622 // | 622 // "/" or "./". Otherwise, it's just a normal non-matching character. |
623 // isWithin("foo/./bar", "foo/bar/baz") //=> true | 623 // |
624 // isWithin("foo/bar/../baz", "foo/bar/.foo") //=> false | 624 // isWithin("foo/./bar", "foo/bar/baz") //=> true |
625 // | 625 // isWithin("foo/bar/../baz", "foo/bar/.foo") //=> false |
626 // We could stay on the fast path for "/./", but that adds a lot of | 626 if (style.isSeparator(lastCodeUnit)) { |
627 // complexity and isn't likely to come up much in practice. | 627 parentIndex++; |
628 if ((parentCodeUnit == chars.PERIOD || childCodeUnit == chars.PERIOD) && | 628 |
629 (style.isSeparator(lastCodeUnit) || lastCodeUnit == chars.PERIOD)) { | 629 // We've hit "/." at the end of the parent path, which we can ignore, |
630 return null; | 630 // since the paths were equivalent up to this point. |
| 631 if (parentIndex == parent.length) break; |
| 632 parentCodeUnit = parentCodeUnits[parentIndex]; |
| 633 |
| 634 // We've hit "/./", which we can ignore. |
| 635 if (style.isSeparator(parentCodeUnit)) { |
| 636 parentIndex++; |
| 637 continue; |
| 638 } |
| 639 |
| 640 // We've hit "/..", which may be a directory traversal operator that |
| 641 // we can't handle on the fast track. |
| 642 if (parentCodeUnit == chars.PERIOD) { |
| 643 parentIndex++; |
| 644 if (parentIndex == parent.length || |
| 645 style.isSeparator(parentCodeUnits[parentIndex])) { |
| 646 return null; |
| 647 } |
| 648 } |
| 649 } |
| 650 |
| 651 // If this isn't a directory traversal, fall through so we hit the |
| 652 // normal handling for mismatched paths. |
| 653 } |
| 654 |
| 655 // This is the same logic as above, but for the child path instead of the |
| 656 // parent. |
| 657 if (childCodeUnit == chars.PERIOD) { |
| 658 if (style.isSeparator(lastCodeUnit)) { |
| 659 childIndex++; |
| 660 if (childIndex == child.length) break; |
| 661 childCodeUnit = childCodeUnits[childIndex]; |
| 662 |
| 663 if (style.isSeparator(childCodeUnit)) { |
| 664 childIndex++; |
| 665 continue; |
| 666 } |
| 667 |
| 668 if (childCodeUnit == chars.PERIOD) { |
| 669 childIndex++; |
| 670 if (childIndex == child.length || |
| 671 style.isSeparator(childCodeUnits[childIndex])) { |
| 672 return null; |
| 673 } |
| 674 } |
| 675 } |
631 } | 676 } |
632 | 677 |
633 // If we're here, we've hit two non-matching, non-significant characters. | 678 // If we're here, we've hit two non-matching, non-significant characters. |
634 // As long as the remainders of the two paths don't have any unresolved | 679 // As long as the remainders of the two paths don't have any unresolved |
635 // ".." components, we can be confident that [child] is not within | 680 // ".." components, we can be confident that [child] is not within |
636 // [parent]. | 681 // [parent]. |
637 var childDirection = _pathDirection(childCodeUnits, childIndex); | 682 var childDirection = _pathDirection(childCodeUnits, childIndex); |
638 if (childDirection != _PathDirection.belowRoot) return null; | 683 if (childDirection != _PathDirection.belowRoot) return null; |
639 var parentDirection = _pathDirection(parentCodeUnits, parentIndex); | 684 var parentDirection = _pathDirection(parentCodeUnits, parentIndex); |
640 if (parentDirection != _PathDirection.belowRoot) return null; | 685 if (parentDirection != _PathDirection.belowRoot) return null; |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 | 945 |
901 /// The path never reaches to or above its original root. | 946 /// The path never reaches to or above its original root. |
902 static const belowRoot = const _PathDirection("below root"); | 947 static const belowRoot = const _PathDirection("below root"); |
903 | 948 |
904 final String name; | 949 final String name; |
905 | 950 |
906 const _PathDirection(this.name); | 951 const _PathDirection(this.name); |
907 | 952 |
908 String toString() => name; | 953 String toString() => name; |
909 } | 954 } |
OLD | NEW |