| 558 | return |
| 559 | |
| 560 | def __parse_string(self, str, patt=_CookiePattern): |
| 561 | i = 0 # Our starting point |
| 562 | n = len(str) # Length of string |
| 563 | parsed_items = [] # Parsed (type, key, value) triples |
| 564 | morsel_seen = False # A key=value pair was previously encountered |
| 565 | |
| 566 | TYPE_ATTRIBUTE = 1 |
| 567 | TYPE_KEYVALUE = 2 |
| 568 | |
| 569 | # We first parse the whole cookie string and reject it if it's |
| 570 | # syntactically invalid (this helps avoid some classes of injection |
| 571 | # attacks). |
| 572 | while 0 <= i < n: |
| 573 | # Start looking for a cookie |
| 574 | match = patt.match(str, i) |
| 575 | if not match: |
| 576 | # No more cookies |
| 577 | break |
| 578 | |
| 579 | key, value = match.group("key"), match.group("val") |
| 580 | i = match.end(0) |
| 581 | |
| 582 | if key[0] == "$": |
| 583 | if not morsel_seen: |
| 584 | # We ignore attributes which pertain to the cookie |
| 585 | # mechanism as a whole, such as "$Version". |
| 586 | # See RFC 2965. (Does anyone care?) |
| 587 | continue |
| 588 | parsed_items.append((TYPE_ATTRIBUTE, key[1:], value)) |
| 589 | elif key.lower() in Morsel._reserved: |
| 590 | if not morsel_seen: |
| 591 | # Invalid cookie string |
| 592 | return |
| 593 | if value is None: |
| 594 | if key.lower() in Morsel._flags: |
| 595 | parsed_items.append((TYPE_ATTRIBUTE, key, True)) |
| 596 | else: |
| 597 | # Invalid cookie string |
| 598 | return |
| 599 | else: |
| 600 | parsed_items.append((TYPE_ATTRIBUTE, key, _unquote(value))) |
| 601 | elif value is not None: |
| 602 | parsed_items.append((TYPE_KEYVALUE, key, self.value_decode(value))) |
| 603 | morsel_seen = True |
| 604 | else: |
| 605 | # Invalid cookie string |
| 606 | return |
| 607 | |
| 608 | # The cookie string is valid, apply it. |
| 609 | M = None # current morsel |
| 610 | for tp, key, value in parsed_items: |
| 611 | if tp == TYPE_ATTRIBUTE: |
| 612 | assert M is not None |
| 613 | M[key] = value |
| 614 | else: |
| 615 | assert tp == TYPE_KEYVALUE |
| 616 | rval, cval = value |
| 617 | self.__set(key, rval, cval) |