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