| 2596 | return decmsg |
| 2597 | |
| 2598 | def parse(self, data): |
| 2599 | unarmored = self.ascii_unarmor(data) |
| 2600 | data = unarmored['body'] |
| 2601 | |
| 2602 | if unarmored['magic'] is not None and 'KEY' not in unarmored['magic']: |
| 2603 | raise ValueError('Expected: KEY. Got: {}'.format(str(unarmored['magic']))) |
| 2604 | |
| 2605 | if unarmored['headers'] is not None: |
| 2606 | self.ascii_headers = unarmored['headers'] |
| 2607 | |
| 2608 | # parse packets |
| 2609 | # keys will hold other keys parsed here |
| 2610 | keys = collections.OrderedDict() |
| 2611 | # orphaned will hold all non-opaque orphaned packets |
| 2612 | orphaned = [] |
| 2613 | # last holds the last non-signature thing processed |
| 2614 | |
| 2615 | ##TODO: see issue #141 and fix this better |
| 2616 | def _getpkt(d): |
| 2617 | return Packet(d) if d else None |
| 2618 | # some packets are filtered out |
| 2619 | getpkt = filter(lambda p: p.header.tag != PacketTag.Trust, iter(functools.partial(_getpkt, data), None)) |
| 2620 | |
| 2621 | def pktgrouper(): |
| 2622 | class PktGrouper(object): |
| 2623 | def __init__(self): |
| 2624 | self.last = None |
| 2625 | |
| 2626 | def __call__(self, pkt): |
| 2627 | if pkt.header.tag != PacketTag.Signature: |
| 2628 | self.last = '{:02X}_{:s}'.format(id(pkt), pkt.__class__.__name__) |
| 2629 | return self.last |
| 2630 | return PktGrouper() |
| 2631 | |
| 2632 | while True: |
| 2633 | for group in iter(group for _, group in itertools.groupby(getpkt, key=pktgrouper()) if not _.endswith('Opaque')): |
| 2634 | pkt = next(group) |
| 2635 | |
| 2636 | # deal with pkt first |
| 2637 | if isinstance(pkt, Key): |
| 2638 | pgpobj = (self if self._key is None else PGPKey()) | pkt |
| 2639 | |
| 2640 | elif isinstance(pkt, (UserID, UserAttribute)): |
| 2641 | pgpobj = PGPUID() | pkt |
| 2642 | |
| 2643 | else: # pragma: no cover |
| 2644 | break |
| 2645 | |
| 2646 | # add signatures to whatever we got |
| 2647 | [ operator.ior(pgpobj, PGPSignature() | sig) for sig in group if not isinstance(sig, Opaque) ] |
| 2648 | |
| 2649 | # and file away pgpobj |
| 2650 | if isinstance(pgpobj, PGPKey): |
| 2651 | if pgpobj.is_primary: |
| 2652 | keys[(pgpobj.fingerprint.keyid, pgpobj.is_public)] = pgpobj |
| 2653 | |
| 2654 | else: |
| 2655 | keys[next(reversed(keys))] |= pgpobj |