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 part of dart.io; | 5 part of dart.io; |
6 | 6 |
7 class _HttpHeaders implements HttpHeaders { | 7 class _HttpHeaders implements HttpHeaders { |
8 final Map<String, List<String>> _headers; | 8 final Map<String, List<String>> _headers; |
9 final String protocolVersion; | 9 final String protocolVersion; |
10 | 10 |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 Map<String, String> _unmodifiableParameters; | 623 Map<String, String> _unmodifiableParameters; |
624 | 624 |
625 _HeaderValue([String this._value = "", Map<String, String> parameters]) { | 625 _HeaderValue([String this._value = "", Map<String, String> parameters]) { |
626 if (parameters != null) { | 626 if (parameters != null) { |
627 _parameters = new HashMap<String, String>.from(parameters); | 627 _parameters = new HashMap<String, String>.from(parameters); |
628 } | 628 } |
629 } | 629 } |
630 | 630 |
631 static _HeaderValue parse(String value, | 631 static _HeaderValue parse(String value, |
632 {parameterSeparator: ";", | 632 {parameterSeparator: ";", |
| 633 valueSeparator: null, |
633 preserveBackslash: false}) { | 634 preserveBackslash: false}) { |
634 // Parse the string. | 635 // Parse the string. |
635 var result = new _HeaderValue(); | 636 var result = new _HeaderValue(); |
636 result._parse(value, parameterSeparator, preserveBackslash); | 637 result._parse(value, parameterSeparator, valueSeparator, preserveBackslash); |
637 return result; | 638 return result; |
638 } | 639 } |
639 | 640 |
640 String get value => _value; | 641 String get value => _value; |
641 | 642 |
642 void _ensureParameters() { | 643 void _ensureParameters() { |
643 if (_parameters == null) { | 644 if (_parameters == null) { |
644 _parameters = new HashMap<String, String>(); | 645 _parameters = new HashMap<String, String>(); |
645 } | 646 } |
646 } | 647 } |
(...skipping 10 matching lines...) Expand all Loading... |
657 StringBuffer sb = new StringBuffer(); | 658 StringBuffer sb = new StringBuffer(); |
658 sb.write(_value); | 659 sb.write(_value); |
659 if (parameters != null && parameters.length > 0) { | 660 if (parameters != null && parameters.length > 0) { |
660 _parameters.forEach((String name, String value) { | 661 _parameters.forEach((String name, String value) { |
661 sb..write("; ")..write(name)..write("=")..write(value); | 662 sb..write("; ")..write(name)..write("=")..write(value); |
662 }); | 663 }); |
663 } | 664 } |
664 return sb.toString(); | 665 return sb.toString(); |
665 } | 666 } |
666 | 667 |
667 void _parse(String s, String parameterSeparator, bool preserveBackslash) { | 668 void _parse(String s, |
| 669 String parameterSeparator, |
| 670 String valueSeparator, |
| 671 bool preserveBackslash) { |
668 int index = 0; | 672 int index = 0; |
669 | 673 |
670 bool done() => index == s.length; | 674 bool done() => index == s.length; |
671 | 675 |
672 void skipWS() { | 676 void skipWS() { |
673 while (!done()) { | 677 while (!done()) { |
674 if (s[index] != " " && s[index] != "\t") return; | 678 if (s[index] != " " && s[index] != "\t") return; |
675 index++; | 679 index++; |
676 } | 680 } |
677 } | 681 } |
678 | 682 |
679 String parseValue() { | 683 String parseValue() { |
680 int start = index; | 684 int start = index; |
681 while (!done()) { | 685 while (!done()) { |
682 if (s[index] == " " || | 686 if (s[index] == " " || |
683 s[index] == "\t" || | 687 s[index] == "\t" || |
| 688 s[index] == valueSeparator || |
684 s[index] == parameterSeparator) break; | 689 s[index] == parameterSeparator) break; |
685 index++; | 690 index++; |
686 } | 691 } |
687 return s.substring(start, index); | 692 return s.substring(start, index); |
688 } | 693 } |
689 | 694 |
690 void expect(String expected) { | 695 void expect(String expected) { |
691 if (done() || s[index] != expected) { | 696 if (done() || s[index] != expected) { |
692 throw new HttpException("Failed to parse header value"); | 697 throw new HttpException("Failed to parse header value"); |
693 } | 698 } |
694 index++; | 699 index++; |
695 } | 700 } |
696 | 701 |
697 void maybeExpect(String expected) { | 702 void maybeExpect(String expected) { |
698 if (s[index] == expected) index++; | 703 if (s[index] == expected) index++; |
699 } | 704 } |
700 | 705 |
701 void parseParameters() { | 706 void parseParameters() { |
702 var parameters = new HashMap<String, String>(); | 707 var parameters = new HashMap<String, String>(); |
703 _parameters = new UnmodifiableMapView(parameters); | 708 _parameters = new UnmodifiableMapView(parameters); |
704 | 709 |
705 String parseParameterName() { | 710 String parseParameterName() { |
706 int start = index; | 711 int start = index; |
707 while (!done()) { | 712 while (!done()) { |
708 if (s[index] == " " || s[index] == "\t" || s[index] == "=") break; | 713 if (s[index] == " " || |
| 714 s[index] == "\t" || |
| 715 s[index] == "=" || |
| 716 s[index] == valueSeparator) break; |
709 index++; | 717 index++; |
710 } | 718 } |
711 return s.substring(start, index).toLowerCase(); | 719 return s.substring(start, index).toLowerCase(); |
712 } | 720 } |
713 | 721 |
714 String parseParameterValue() { | 722 String parseParameterValue() { |
715 if (s[index] == "\"") { | 723 if (!done() && s[index] == "\"") { |
716 // Parse quoted value. | 724 // Parse quoted value. |
717 StringBuffer sb = new StringBuffer(); | 725 StringBuffer sb = new StringBuffer(); |
718 index++; | 726 index++; |
719 while (!done()) { | 727 while (!done()) { |
720 if (s[index] == "\\") { | 728 if (s[index] == "\\") { |
721 if (index + 1 == s.length) { | 729 if (index + 1 == s.length) { |
722 throw new HttpException("Failed to parse header value"); | 730 throw new HttpException("Failed to parse header value"); |
723 } | 731 } |
724 if (preserveBackslash && s[index + 1] != "\"") { | 732 if (preserveBackslash && s[index + 1] != "\"") { |
725 sb.write(s[index]); | 733 sb.write(s[index]); |
726 } | 734 } |
727 index++; | 735 index++; |
728 } else if (s[index] == "\"") { | 736 } else if (s[index] == "\"") { |
729 index++; | 737 index++; |
730 break; | 738 break; |
731 } | 739 } |
732 sb.write(s[index]); | 740 sb.write(s[index]); |
733 index++; | 741 index++; |
734 } | 742 } |
735 return sb.toString(); | 743 return sb.toString(); |
736 } else { | 744 } else { |
737 // Parse non-quoted value. | 745 // Parse non-quoted value. |
738 return parseValue(); | 746 var val = parseValue(); |
| 747 return val == "" ? null : val; |
739 } | 748 } |
740 } | 749 } |
741 | 750 |
742 while (!done()) { | 751 while (!done()) { |
743 skipWS(); | 752 skipWS(); |
744 if (done()) return; | 753 if (done()) return; |
745 String name = parseParameterName(); | 754 String name = parseParameterName(); |
746 skipWS(); | 755 skipWS(); |
747 expect("="); | 756 if (done()) { |
| 757 parameters[name] = null; |
| 758 return; |
| 759 } |
| 760 maybeExpect("="); |
748 skipWS(); | 761 skipWS(); |
| 762 if(done()) { |
| 763 parameters[name] = null; |
| 764 return; |
| 765 } |
749 String value = parseParameterValue(); | 766 String value = parseParameterValue(); |
750 if (name == 'charset' && this is _ContentType) { | 767 if (name == 'charset' && this is _ContentType) { |
751 // Charset parameter of ContentTypes are always lower-case. | 768 // Charset parameter of ContentTypes are always lower-case. |
752 value = value.toLowerCase(); | 769 value = value.toLowerCase(); |
753 } | 770 } |
754 parameters[name] = value; | 771 parameters[name] = value; |
755 skipWS(); | 772 skipWS(); |
756 if (done()) return; | 773 if (done()) return; |
| 774 // TODO: Implement support for multi-valued parameters. |
| 775 if(s[index] == valueSeparator) return; |
757 expect(parameterSeparator); | 776 expect(parameterSeparator); |
758 } | 777 } |
759 } | 778 } |
760 | 779 |
761 skipWS(); | 780 skipWS(); |
762 _value = parseValue(); | 781 _value = parseValue(); |
763 skipWS(); | 782 skipWS(); |
764 if (done()) return; | 783 if (done()) return; |
765 maybeExpect(parameterSeparator); | 784 maybeExpect(parameterSeparator); |
766 parseParameters(); | 785 parseParameters(); |
(...skipping 26 matching lines...) Expand all Loading... |
793 if (charset != null) { | 812 if (charset != null) { |
794 _ensureParameters(); | 813 _ensureParameters(); |
795 this._parameters["charset"] = charset.toLowerCase(); | 814 this._parameters["charset"] = charset.toLowerCase(); |
796 } | 815 } |
797 } | 816 } |
798 | 817 |
799 _ContentType._(); | 818 _ContentType._(); |
800 | 819 |
801 static _ContentType parse(String value) { | 820 static _ContentType parse(String value) { |
802 var result = new _ContentType._(); | 821 var result = new _ContentType._(); |
803 result._parse(value, ";", false); | 822 result._parse(value, ";", null, false); |
804 int index = result._value.indexOf("/"); | 823 int index = result._value.indexOf("/"); |
805 if (index == -1 || index == (result._value.length - 1)) { | 824 if (index == -1 || index == (result._value.length - 1)) { |
806 result._primaryType = result._value.trim().toLowerCase(); | 825 result._primaryType = result._value.trim().toLowerCase(); |
807 result._subType = ""; | 826 result._subType = ""; |
808 } else { | 827 } else { |
809 result._primaryType = | 828 result._primaryType = |
810 result._value.substring(0, index).trim().toLowerCase(); | 829 result._value.substring(0, index).trim().toLowerCase(); |
811 result._subType = result._value.substring(index + 1).trim().toLowerCase(); | 830 result._subType = result._value.substring(index + 1).trim().toLowerCase(); |
812 } | 831 } |
813 return result; | 832 return result; |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
970 (codeUnit >= 0x23 && codeUnit <= 0x2B) || | 989 (codeUnit >= 0x23 && codeUnit <= 0x2B) || |
971 (codeUnit >= 0x2D && codeUnit <= 0x3A) || | 990 (codeUnit >= 0x2D && codeUnit <= 0x3A) || |
972 (codeUnit >= 0x3C && codeUnit <= 0x5B) || | 991 (codeUnit >= 0x3C && codeUnit <= 0x5B) || |
973 (codeUnit >= 0x5D && codeUnit <= 0x7E))) { | 992 (codeUnit >= 0x5D && codeUnit <= 0x7E))) { |
974 throw new FormatException( | 993 throw new FormatException( |
975 "Invalid character in cookie value, code unit: '$codeUnit'"); | 994 "Invalid character in cookie value, code unit: '$codeUnit'"); |
976 } | 995 } |
977 } | 996 } |
978 } | 997 } |
979 } | 998 } |
OLD | NEW |