2121from django .test import TestCase
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 )
@@ -643,6 +643,8 @@ def test_decode(self):
643643 c2 = SimpleCookie ()
644644 c2 .load (c .output ()[12 :])
645645 self .assertEqual (c ['test' ].value , c2 ['test' ].value )
646+ c3 = parse_cookie (c .output ()[12 :])
647+ self .assertEqual (c ['test' ].value , c3 ['test' ])
646648
647649 def test_decode_2 (self ):
648650 """
@@ -653,6 +655,8 @@ def test_decode_2(self):
653655 c2 = SimpleCookie ()
654656 c2 .load (c .output ()[12 :])
655657 self .assertEqual (c ['test' ].value , c2 ['test' ].value )
658+ c3 = parse_cookie (c .output ()[12 :])
659+ self .assertEqual (c ['test' ].value , c3 ['test' ])
656660
657661 def test_nonstandard_keys (self ):
658662 """
@@ -666,6 +670,52 @@ def test_repeated_nonstandard_keys(self):
666670 """
667671 self .assertIn ('good_cookie' , parse_cookie ('a:=b; a:=c; good_cookie=yes' ).keys ())
668672
673+ def test_python_cookies (self ):
674+ """
675+ Test cases copied from Python's Lib/test/test_http_cookies.py
676+ """
677+ self .assertEqual (parse_cookie ('chips=ahoy; vienna=finger' ), {'chips' : 'ahoy' , 'vienna' : 'finger' })
678+ # Here parse_cookie() differs from Python's cookie parsing in that it
679+ # treats all semicolons as delimiters, even within quotes.
680+ self .assertEqual (
681+ parse_cookie ('keebler="E=mc2; L=\\ "Loves\\ "; fudge=\\ 012;"' ),
682+ {'keebler' : '"E=mc2' , 'L' : '\\ "Loves\\ "' , 'fudge' : '\\ 012' , '' : '"' }
683+ )
684+ # Illegal cookies that have an '=' char in an unquoted value.
685+ self .assertEqual (parse_cookie ('keebler=E=mc2' ), {'keebler' : 'E=mc2' })
686+ # Cookies with ':' character in their name.
687+ self .assertEqual (parse_cookie ('key:term=value:term' ), {'key:term' : 'value:term' })
688+ # Cookies with '[' and ']'.
689+ self .assertEqual (parse_cookie ('a=b; c=[; d=r; f=h' ), {'a' : 'b' , 'c' : '[' , 'd' : 'r' , 'f' : 'h' })
690+
691+ def test_cookie_edgecases (self ):
692+ # Cookies that RFC6265 allows.
693+ self .assertEqual (parse_cookie ('a=b; Domain=example.com' ), {'a' : 'b' , 'Domain' : 'example.com' })
694+ # parse_cookie() has historically kept only the last cookie with the
695+ # same name.
696+ self .assertEqual (parse_cookie ('a=b; h=i; a=c' ), {'a' : 'c' , 'h' : 'i' })
697+
698+ def test_invalid_cookies (self ):
699+ """
700+ Cookie strings that go against RFC6265 but browsers will send if set
701+ via document.cookie.
702+ """
703+ # Chunks without an equals sign appear as unnamed values per
704+ # https://bugzilla.mozilla.org/show_bug.cgi?id=169091
705+ self .assertIn ('django_language' , parse_cookie ('abc=def; unnamed; django_language=en' ).keys ())
706+ # Even a double quote may be an unamed value.
707+ self .assertEqual (parse_cookie ('a=b; "; c=d' ), {'a' : 'b' , '' : '"' , 'c' : 'd' })
708+ # Spaces in names and values, and an equals sign in values.
709+ self .assertEqual (parse_cookie ('a b c=d e = f; gh=i' ), {'a b c' : 'd e = f' , 'gh' : 'i' })
710+ # More characters the spec forbids.
711+ self .assertEqual (parse_cookie ('a b,c<>@:/[]?{}=d " =e,f g' ), {'a b,c<>@:/[]?{}' : 'd " =e,f g' })
712+ # Unicode characters. The spec only allows ASCII.
713+ self .assertEqual (parse_cookie ('saint=André Bessette' ), {'saint' : force_str ('André Bessette' )})
714+ # Browsers don't send extra whitespace or semicolons in Cookie headers,
715+ # but parse_cookie() should parse whitespace the same way
716+ # document.cookie parses whitespace.
717+ self .assertEqual (parse_cookie (' = b ; ; = ; c = ; ' ), {'' : 'b' , 'c' : '' })
718+
669719 def test_httponly_after_load (self ):
670720 """
671721 Test that we can use httponly attribute on cookies that we load
0 commit comments