2121from django .test import SimpleTestCase
2222from django .utils import six
2323from django .utils ._os import upath
24- from django .utils .encoding import force_text , smart_str
24+ from django .utils .encoding import force_str , force_text , smart_str
2525from django .utils .functional import lazy
2626
2727lazystr = lazy (force_text , six .text_type )
@@ -657,6 +657,8 @@ def test_decode(self):
657657 c2 = SimpleCookie ()
658658 c2 .load (c .output ()[12 :])
659659 self .assertEqual (c ['test' ].value , c2 ['test' ].value )
660+ c3 = parse_cookie (c .output ()[12 :])
661+ self .assertEqual (c ['test' ].value , c3 ['test' ])
660662
661663 def test_decode_2 (self ):
662664 """
@@ -667,6 +669,8 @@ def test_decode_2(self):
667669 c2 = SimpleCookie ()
668670 c2 .load (c .output ()[12 :])
669671 self .assertEqual (c ['test' ].value , c2 ['test' ].value )
672+ c3 = parse_cookie (c .output ()[12 :])
673+ self .assertEqual (c ['test' ].value , c3 ['test' ])
670674
671675 def test_nonstandard_keys (self ):
672676 """
@@ -680,6 +684,52 @@ def test_repeated_nonstandard_keys(self):
680684 """
681685 self .assertIn ('good_cookie' , parse_cookie ('a:=b; a:=c; good_cookie=yes' ).keys ())
682686
687+ def test_python_cookies (self ):
688+ """
689+ Test cases copied from Python's Lib/test/test_http_cookies.py
690+ """
691+ self .assertEqual (parse_cookie ('chips=ahoy; vienna=finger' ), {'chips' : 'ahoy' , 'vienna' : 'finger' })
692+ # Here parse_cookie() differs from Python's cookie parsing in that it
693+ # treats all semicolons as delimiters, even within quotes.
694+ self .assertEqual (
695+ parse_cookie ('keebler="E=mc2; L=\\ "Loves\\ "; fudge=\\ 012;"' ),
696+ {'keebler' : '"E=mc2' , 'L' : '\\ "Loves\\ "' , 'fudge' : '\\ 012' , '' : '"' }
697+ )
698+ # Illegal cookies that have an '=' char in an unquoted value.
699+ self .assertEqual (parse_cookie ('keebler=E=mc2' ), {'keebler' : 'E=mc2' })
700+ # Cookies with ':' character in their name.
701+ self .assertEqual (parse_cookie ('key:term=value:term' ), {'key:term' : 'value:term' })
702+ # Cookies with '[' and ']'.
703+ self .assertEqual (parse_cookie ('a=b; c=[; d=r; f=h' ), {'a' : 'b' , 'c' : '[' , 'd' : 'r' , 'f' : 'h' })
704+
705+ def test_cookie_edgecases (self ):
706+ # Cookies that RFC6265 allows.
707+ self .assertEqual (parse_cookie ('a=b; Domain=example.com' ), {'a' : 'b' , 'Domain' : 'example.com' })
708+ # parse_cookie() has historically kept only the last cookie with the
709+ # same name.
710+ self .assertEqual (parse_cookie ('a=b; h=i; a=c' ), {'a' : 'c' , 'h' : 'i' })
711+
712+ def test_invalid_cookies (self ):
713+ """
714+ Cookie strings that go against RFC6265 but browsers will send if set
715+ via document.cookie.
716+ """
717+ # Chunks without an equals sign appear as unnamed values per
718+ # https://bugzilla.mozilla.org/show_bug.cgi?id=169091
719+ self .assertIn ('django_language' , parse_cookie ('abc=def; unnamed; django_language=en' ).keys ())
720+ # Even a double quote may be an unamed value.
721+ self .assertEqual (parse_cookie ('a=b; "; c=d' ), {'a' : 'b' , '' : '"' , 'c' : 'd' })
722+ # Spaces in names and values, and an equals sign in values.
723+ self .assertEqual (parse_cookie ('a b c=d e = f; gh=i' ), {'a b c' : 'd e = f' , 'gh' : 'i' })
724+ # More characters the spec forbids.
725+ self .assertEqual (parse_cookie ('a b,c<>@:/[]?{}=d " =e,f g' ), {'a b,c<>@:/[]?{}' : 'd " =e,f g' })
726+ # Unicode characters. The spec only allows ASCII.
727+ self .assertEqual (parse_cookie ('saint=André Bessette' ), {'saint' : force_str ('André Bessette' )})
728+ # Browsers don't send extra whitespace or semicolons in Cookie headers,
729+ # but parse_cookie() should parse whitespace the same way
730+ # document.cookie parses whitespace.
731+ self .assertEqual (parse_cookie (' = b ; ; = ; c = ; ' ), {'' : 'b' , 'c' : '' })
732+
683733 def test_httponly_after_load (self ):
684734 """
685735 Test that we can use httponly attribute on cookies that we load
0 commit comments