sequoia_openpgp/
packet_pile.rs

1use std::convert::TryFrom;
2use std::fmt;
3use std::vec;
4use std::iter::FromIterator;
5use std::iter::IntoIterator;
6
7use buffered_reader::BufferedReader;
8
9use crate::Result;
10use crate::Error;
11use crate::Packet;
12use crate::cert::Cert;
13use crate::packet::{self, Container};
14use crate::parse::PacketParserResult;
15use crate::parse::PacketParserBuilder;
16use crate::parse::Parse;
17use crate::parse::Cookie;
18
19/// An unstructured [packet] sequence.
20///
21/// To parse an OpenPGP packet stream into a `PacketPile`, you can use
22/// [`PacketParser`], [`PacketPileParser`], or
23/// [`PacketPile::from_file`] (or related routines).
24///
25///   [packet]: https://www.rfc-editor.org/rfc/rfc9580.html#section-4
26///   [`PacketParser`]: crate::parse::PacketParser
27///   [`PacketPileParser`]: crate::parse::PacketPileParser
28///
29/// You can also convert a [`Cert`] into a `PacketPile` using
30/// `PacketPile::from`.  Unlike serializing a `Cert`, this does not
31/// drop any secret key material.
32///
33/// Normally, you'll want to convert the `PacketPile` to a `Cert` or a
34/// `Message`.
35///
36/// # Examples
37///
38/// This example shows how to modify packets in PacketPile using [`pathspec`]s.
39///
40///   [`pathspec`]: PacketPile::path_ref()
41///
42/// ```rust
43/// # use sequoia_openpgp as openpgp;
44/// use std::convert::TryFrom;
45/// use openpgp::{Packet, PacketPile};
46/// use openpgp::packet::signature::Signature4;
47/// use openpgp::packet::Signature;
48/// use openpgp::cert::prelude::*;
49/// use openpgp::parse::Parse;
50/// use openpgp::serialize::Serialize;
51/// use openpgp::policy::StandardPolicy;
52/// use openpgp::crypto::mpi;
53/// use openpgp::types::RevocationStatus;
54///
55/// # fn main() -> openpgp::Result<()> {
56/// let (cert, revocation) = CertBuilder::new().generate()?;
57///
58/// let mut buffer = Vec::new();
59/// cert.serialize(&mut buffer)?;
60/// let packet: Packet = revocation.into();
61/// packet.serialize(&mut buffer)?;
62///
63/// let policy = &StandardPolicy::new();
64///
65/// // Certificate is considered revoked because it is accompanied by its
66/// // revocation signature
67/// let pp: PacketPile = PacketPile::from_bytes(&buffer)?;
68/// let cert = Cert::try_from(pp)?;
69/// if let RevocationStatus::Revoked(_) = cert.revocation_status(policy, None) {
70///     // cert is considered revoked
71/// }
72/// # else {
73/// #     unreachable!();
74/// # }
75///
76/// // Breaking the revocation signature changes certificate's status
77/// let mut pp: PacketPile = PacketPile::from_bytes(&buffer)?;
78/// if let Some(Packet::Signature(ref mut sig)) = pp.path_ref_mut(&[2]) {
79///     *sig = Signature4::new(
80///         sig.typ(),
81///         sig.pk_algo(),
82///         sig.hash_algo(),
83///         sig.hashed_area().clone(),
84///         sig.unhashed_area().clone(),
85///         *sig.digest_prefix(),
86///         // MPI is replaced with a dummy one
87///         mpi::Signature::RSA {
88///             s: mpi::MPI::from(vec![1, 2, 3])
89///         }).into();
90/// }
91///
92/// let cert = Cert::try_from(pp)?;
93/// if let RevocationStatus::NotAsFarAsWeKnow = cert.revocation_status(policy, None) {
94///     // revocation signature is broken and the cert is not revoked
95///     assert_eq!(cert.bad_signatures().count(), 1);
96/// }
97/// # else {
98/// #   unreachable!();
99/// # }
100/// #     Ok(())
101/// # }
102/// ```
103#[derive(PartialEq, Clone, Default)]
104pub struct PacketPile {
105    /// At the top level, we have a sequence of packets, which may be
106    /// containers.
107    top_level: Container,
108}
109
110assert_send_and_sync!(PacketPile);
111
112impl fmt::Debug for PacketPile {
113    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114        f.debug_struct("PacketPile")
115            .field("packets", &self.top_level.children_ref())
116            .finish()
117    }
118}
119
120impl<'a> Parse<'a, PacketPile> for PacketPile {
121    /// Deserializes the OpenPGP message stored in the file named by
122    /// `path`.
123    ///
124    /// Although this method is easier to use to parse a sequence of
125    /// OpenPGP packets than a [`PacketParser`] or a
126    /// [`PacketPileParser`], this interface buffers the whole message
127    /// in memory.  Thus, the caller must be certain that the
128    /// *deserialized* message is not too large.
129    ///
130    /// Note: this interface *does* buffer the contents of packets.
131    ///
132    ///   [`PacketParser`]: crate::parse::PacketParser
133    ///   [`PacketPileParser`]: crate::parse::PacketPileParser
134    fn from_buffered_reader<R>(reader: R) -> Result<PacketPile>
135    where
136        R: BufferedReader<Cookie> + 'a,
137    {
138        PacketPile::from_cookie_reader(reader.into_boxed())
139    }
140}
141
142impl std::str::FromStr for PacketPile {
143    type Err = anyhow::Error;
144
145    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
146        Self::from_bytes(s.as_bytes())
147    }
148}
149
150impl From<Vec<Packet>> for PacketPile {
151    fn from(p: Vec<Packet>) -> Self {
152        PacketPile { top_level: Container::from(p) }
153    }
154}
155
156impl From<Packet> for PacketPile {
157    fn from(p: Packet) -> Self {
158        Self::from(vec![p])
159    }
160}
161
162impl FromIterator<Packet> for PacketPile {
163    fn from_iter<I: IntoIterator<Item=Packet>>(iter: I) -> Self {
164        Self::from(Vec::from_iter(iter))
165    }
166}
167
168impl From<PacketPile> for Vec<Packet> {
169    fn from(pp: PacketPile) -> Self {
170        pp.into_children().collect()
171    }
172}
173
174impl PacketPile {
175    /// Accessor for PacketPileParser.
176    pub(crate) fn top_level_mut(&mut self) -> &mut Container {
177        &mut self.top_level
178    }
179
180    /// Returns an error if operating on a non-container packet.
181    fn error() -> crate::Error {
182        crate::Error::InvalidOperation("Not a container packet".into())
183    }
184
185    /// Pretty prints the message to stderr.
186    ///
187    /// This function is primarily intended for debugging purposes.
188    #[cfg(test)]
189    pub fn pretty_print(&self) {
190        self.top_level.pretty_print(0);
191    }
192
193    /// Returns a reference to the packet at the location described by
194    /// `pathspec`.
195    ///
196    /// `pathspec` is a slice of the form `[0, 1, 2]`.  Each element
197    /// is the index of packet in a container.  Thus, the previous
198    /// path specification means: return the third child of the second
199    /// child of the first top-level packet.  In other words, the
200    /// starred packet in the following tree:
201    ///
202    /// ```text
203    ///         PacketPile
204    ///        /     |     \
205    ///       0      1      2  ...
206    ///     /   \
207    ///    /     \
208    ///  0         1  ...
209    ///        /   |   \  ...
210    ///       0    1    2
211    ///                 *
212    /// ```
213    ///
214    /// And, `[10]` means return the 11th top-level packet.
215    ///
216    /// Note: there is no packet at the root.  Thus, the path `[]`
217    /// returns None.
218    ///
219    /// # Examples
220    ///
221    /// ```rust
222    /// # use sequoia_openpgp as openpgp;
223    /// # use openpgp::{Result, types::{CompressionAlgorithm, DataFormat},
224    /// #     Packet, PacketPile, packet::Literal, packet::CompressedData};
225    /// # fn main() -> Result<()> {
226    /// # let mut lit = Literal::new(DataFormat::Unicode);
227    /// # lit.set_body(b"test".to_vec());
228    /// # let packets = vec![lit.into()];
229    /// let pile = PacketPile::from(packets);
230    ///
231    /// if let Some(packet) = pile.path_ref(&[0]) {
232    ///     // There is a packet at this path.
233    /// }
234    /// # else {
235    /// #     unreachable!();
236    /// # }
237    ///
238    /// if let None = pile.path_ref(&[0, 1, 2]) {
239    ///     // But none here.
240    /// }
241    /// # else {
242    /// #     unreachable!();
243    /// # }
244    /// # Ok(())
245    /// # }
246    /// ```
247    pub fn path_ref(&self, pathspec: &[usize]) -> Option<&Packet> {
248        let mut packet : Option<&Packet> = None;
249
250        let mut cont = Some(&self.top_level);
251        for i in pathspec {
252            if let Some(c) = cont.take() {
253                if let Some(children) = c.children_ref() {
254                    if *i < children.len() {
255                        let p = &children[*i];
256                        packet = Some(p);
257                        cont = p.container_ref();
258                        continue;
259                    }
260                }
261            }
262
263            return None;
264        }
265        packet
266    }
267
268    /// Returns a mutable reference to the packet at the location
269    /// described by `pathspec`.
270    ///
271    /// See the description of the `path_spec` for more details.
272    ///
273    /// # Examples
274    ///
275    /// ```rust
276    /// # use sequoia_openpgp as openpgp;
277    /// # use openpgp::{Result, types::{CompressionAlgorithm, DataFormat},
278    /// #     Packet, PacketPile, packet::Literal, packet::CompressedData};
279    /// # fn main() -> Result<()> {
280    /// # let mut lit = Literal::new(DataFormat::Unicode);
281    /// # lit.set_body(b"test".to_vec());
282    /// # let packets = vec![lit.into()];
283    /// let mut pile = PacketPile::from(packets);
284    ///
285    /// if let Some(ref packet) = pile.path_ref_mut(&[0]) {
286    ///     // There is a packet at this path.
287    /// }
288    /// # else {
289    /// #     unreachable!();
290    /// # }
291    ///
292    /// if let None = pile.path_ref_mut(&[0, 1, 2]) {
293    ///     // But none here.
294    /// }
295    /// # else {
296    /// #     unreachable!();
297    /// # }
298    /// # Ok(())
299    /// # }
300    /// ```
301    pub fn path_ref_mut(&mut self, pathspec: &[usize]) -> Option<&mut Packet> {
302        let mut container = &mut self.top_level;
303
304        for (level, &i) in pathspec.iter().enumerate() {
305            let tmp = container;
306
307            let p = tmp.children_mut().and_then(|c| c.get_mut(i))?;
308
309            if level == pathspec.len() - 1 {
310                return Some(p)
311            }
312
313            container = p.container_mut().unwrap();
314        }
315
316        None
317    }
318
319    /// Replaces the specified packets at the location described by
320    /// `pathspec` with `packets`.
321    ///
322    /// If a packet is a container, the subtree rooted at the
323    /// container is removed.
324    ///
325    /// Note: the number of packets to remove need not match the
326    /// number of packets to insert.
327    ///
328    /// The removed packets are returned.
329    ///
330    /// If the path was invalid, then `Error::IndexOutOfRange` is
331    /// returned instead.
332    ///
333    /// # Examples
334    ///
335    /// ```rust
336    /// # use sequoia_openpgp as openpgp;
337    /// # use openpgp::{Result, types::{CompressionAlgorithm, DataFormat},
338    /// #     Packet, PacketPile, packet::Literal, packet::CompressedData};
339    /// # fn main() -> Result<()> {
340    /// // A compressed data packet that contains a literal data packet.
341    /// let mut literal = Literal::new(DataFormat::Unicode);
342    /// literal.set_body(b"old".to_vec());
343    /// let mut compressed =
344    ///     CompressedData::new(CompressionAlgorithm::Uncompressed);
345    /// compressed.container_mut().children_mut().unwrap().push(literal.into());
346    /// let mut pile = PacketPile::from(Packet::from(compressed));
347    ///
348    /// // Replace the literal data packet.
349    /// let mut literal = Literal::new(DataFormat::Unicode);
350    /// literal.set_body(b"new".to_vec());
351    /// pile.replace(
352    ///     &[0, 0], 1,
353    ///     [literal.into()].to_vec())?;
354    /// # if let Some(Packet::Literal(lit)) = pile.path_ref(&[0, 0]) {
355    /// #     assert_eq!(lit.body(), &b"new"[..], "{:#?}", lit);
356    /// # } else {
357    /// #     panic!("Unexpected packet!");
358    /// # }
359    /// #     Ok(())
360    /// # }
361    /// ```
362    pub fn replace(&mut self, pathspec: &[usize], count: usize,
363                   mut packets: Vec<Packet>)
364        -> Result<Vec<Packet>>
365    {
366        let mut container = &mut self.top_level;
367
368        for (level, &i) in pathspec.iter().enumerate() {
369            let tmp = container;
370
371            if level == pathspec.len() - 1 {
372                if tmp.children_ref().map(|c| i + count > c.len())
373                    .unwrap_or(true)
374                {
375                    return Err(Error::IndexOutOfRange.into());
376                }
377
378                // Out with the old...
379                let old = tmp.children_mut()
380                    .expect("checked above")
381                    .drain(i..i + count)
382                    .collect::<Vec<Packet>>();
383                assert_eq!(old.len(), count);
384
385                // In with the new...
386
387                let mut tail = tmp.children_mut()
388                    .expect("checked above")
389                    .drain(i..)
390                    .collect::<Vec<Packet>>();
391
392                tmp.children_mut().expect("checked above").append(&mut packets);
393                tmp.children_mut().expect("checked above").append(&mut tail);
394
395                return Ok(old)
396            }
397
398            if tmp.children_ref().map(|c| i >= c.len()).unwrap_or(true) {
399                return Err(Error::IndexOutOfRange.into());
400            }
401
402            match tmp.children_ref().expect("checked above")[i] {
403                // The structured container types.
404                Packet::CompressedData(_)
405                    | Packet::SEIP(_)
406                    => (), // Ok.
407                _ => return Err(Error::IndexOutOfRange.into()),
408            }
409            container =
410                tmp.children_mut().expect("checked above")[i].container_mut()
411                .expect("The above packets are structured containers");
412        }
413
414        Err(Error::IndexOutOfRange.into())
415    }
416
417    /// Returns an iterator over all the packet's descendants, in
418    /// depth-first order.
419    ///
420    /// ```rust
421    /// # use sequoia_openpgp as openpgp;
422    /// # use openpgp::{Result, types::{CompressionAlgorithm, DataFormat},
423    /// #     Packet, PacketPile, packet::Literal, packet::Tag};
424    /// # use std::iter::Iterator;
425    /// # fn main() -> Result<()> {
426    /// let mut lit = Literal::new(DataFormat::Unicode);
427    /// lit.set_body(b"test".to_vec());
428    ///
429    /// let pile = PacketPile::from(vec![lit.into()]);
430    ///
431    /// for packet in pile.descendants() {
432    ///     assert_eq!(packet.tag(), Tag::Literal);
433    /// }
434    /// # Ok(())
435    /// # }
436    /// ```
437    pub fn descendants(&self) -> packet::Iter {
438        self.top_level.descendants().expect("toplevel is a container")
439    }
440
441    /// Returns an iterator over the top-level packets.
442    ///
443    /// ```rust
444    /// # use sequoia_openpgp as openpgp;
445    /// # use openpgp::{Result, types::{CompressionAlgorithm, DataFormat},
446    /// #     Packet, PacketPile, packet::Literal, packet::CompressedData};
447    /// # fn main() -> Result<()> {
448    /// let mut lit = Literal::new(DataFormat::Unicode);
449    /// lit.set_body(b"test".to_vec());
450    ///
451    /// let pile = PacketPile::from(vec![lit.into()]);
452    ///
453    /// assert_eq!(pile.children().len(), 1);
454    /// # Ok(())
455    /// # }
456    /// ```
457    pub fn children(&self)
458        -> impl Iterator<Item=&Packet> + ExactSizeIterator + Send + Sync
459    {
460        self.top_level.children().expect("toplevel is a container")
461    }
462
463    /// Returns an `IntoIter` over the top-level packets.
464    ///
465    /// ```rust
466    /// # use sequoia_openpgp as openpgp;
467    /// # use openpgp::{Result, types::{CompressionAlgorithm, DataFormat},
468    /// #     Packet, PacketPile, packet::Literal, packet::Tag};
469    /// # fn main() -> Result<()> {
470    /// let mut lit = Literal::new(DataFormat::Unicode);
471    /// lit.set_body(b"test".to_vec());
472    ///
473    /// let pile = PacketPile::from(vec![lit.into()]);
474    ///
475    /// for packet in pile.into_children() {
476    ///     assert_eq!(packet.tag(), Tag::Literal);
477    /// }
478    /// # Ok(())
479    /// # }
480    /// ```
481    pub fn into_children(self)
482        -> impl Iterator<Item=Packet> + ExactSizeIterator + Send + Sync
483    {
484        self.top_level.into_children().expect("toplevel is a container")
485    }
486
487
488    pub(crate) fn from_cookie_reader<'a>(bio: Box<dyn BufferedReader<Cookie> + 'a>)
489            -> Result<PacketPile> {
490        PacketParserBuilder::from_cookie_reader(bio)?
491            .buffer_unread_content()
492            .into_packet_pile()
493    }
494}
495
496impl From<Cert> for PacketPile {
497    /// Converts the `Cert` into a `PacketPile`.
498    ///
499    /// If any packets include secret key material, that secret key
500    /// material is included in the resulting `PacketPile`.  In
501    /// contrast, when serializing a `Cert`, or converting a cert to
502    /// packets with [`Cert::into_packets`], the secret key material
503    /// not included.
504    ///
505    /// Note: This will change in sequoia-openpgp version 2, which
506    /// will harmonize the behavior and not include secret key
507    /// material.
508    // XXXv2: Drop the note in the doc comment and mentioned it in the
509    // release notes.
510    fn from(cert: Cert) -> PacketPile {
511        #[allow(deprecated)]
512        PacketPile::from(cert.into_packets().collect::<Vec<Packet>>())
513    }
514}
515
516impl<'a> TryFrom<PacketParserResult<'a>> for PacketPile {
517    type Error = anyhow::Error;
518
519    /// Reads all the packets from a `PacketParser`, and turns them
520    /// into a message.
521    ///
522    /// Note: this assumes that `ppr` points to a top-level packet.
523    fn try_from(ppr: PacketParserResult<'a>)
524        -> Result<PacketPile>
525    {
526        // Things are not going to work out if we don't start with a
527        // top-level packet.  We should only pop until
528        // ppo.recursion_depth and leave the rest of the message, but
529        // it is hard to imagine that that is what the caller wants.
530        // Instead of hiding that error, fail fast.
531        if let PacketParserResult::Some(ref pp) = ppr {
532            if pp.recursion_depth() != 0 {
533                return Err(Error::InvalidOperation(
534                    format!("Expected top-level packet, \
535                             but the parser is at level {}",
536                            pp.recursion_depth())).into());
537            }
538        }
539
540        // Create a top-level container.
541        let mut top_level = Container::default();
542
543        let mut last_position = 0;
544
545        if ppr.is_eof() {
546            // Empty message.
547            return Ok(PacketPile::from(Vec::new()));
548        }
549        let mut pp = ppr.unwrap();
550
551        'outer: loop {
552            let recursion_depth = pp.recursion_depth();
553            let (mut packet, mut ppr) = pp.recurse()?;
554            let mut position = recursion_depth as isize;
555
556            let mut relative_position : isize = position - last_position;
557            assert!(relative_position <= 1);
558
559            // Find the right container for `packet`.
560            let mut container = &mut top_level;
561            // If we recurse, don't create the new container here.
562            for _ in 0..(position - if relative_position > 0 { 1 } else { 0 }) {
563                // Do a little dance to prevent container from
564                // being reborrowed and preventing us from
565                // assigning to it.
566                let tmp = container;
567                let packets_len =
568                    tmp.children_ref().ok_or_else(Self::error)?.len();
569                let p = &mut tmp.children_mut()
570                    .ok_or_else(Self::error)?
571                    [packets_len - 1];
572
573                container = p.container_mut().unwrap();
574            }
575
576            if relative_position < 0 {
577                relative_position = 0;
578            }
579
580            // If next packet will be inserted in the same container
581            // or the current container's child, we don't need to walk
582            // the tree from the root.
583            loop {
584                if relative_position == 1 {
585                    // Create a new container.
586                    let tmp = container;
587                    let i =
588                        tmp.children_ref().ok_or_else(Self::error)?.len() - 1;
589                    container = tmp.children_mut()
590                        .ok_or_else(Self::error)?
591                        [i].container_mut().unwrap();
592                }
593
594                container.children_mut().unwrap().push(packet);
595
596                if ppr.is_eof() {
597                    break 'outer;
598                }
599
600                pp = ppr.unwrap();
601
602                last_position = position;
603                position = pp.recursion_depth() as isize;
604                relative_position = position - last_position;
605                if position < last_position {
606                    // There was a pop, we need to restart from the
607                    // root.
608                    break;
609                }
610
611                let recursion_depth = pp.recursion_depth();
612                let (packet_, ppr_) = pp.recurse()?;
613                packet = packet_;
614                ppr = ppr_;
615                assert_eq!(position, recursion_depth as isize);
616            }
617        }
618
619        Ok(PacketPile { top_level })
620    }
621}
622
623impl<'a> PacketParserBuilder<'a> {
624    /// Finishes configuring the `PacketParser` and returns a fully
625    /// parsed message.
626    ///
627    /// Note: calling this function does not change the default
628    /// settings.  Thus, by default, the content of packets will *not*
629    /// be buffered.
630    ///
631    /// Note: to avoid denial-of-service attacks, the `PacketParser`
632    /// interface should be preferred unless the size of the message
633    /// is known to fit in memory.
634    ///
635    /// # Examples
636    ///
637    /// ```rust
638    /// # use sequoia_openpgp as openpgp;
639    /// # use openpgp::Result;
640    /// # use openpgp::PacketPile;
641    /// # use openpgp::parse::{Parse, PacketParser, PacketParserBuilder};
642    /// # f(include_bytes!("../tests/data/keys/public-key.pgp"));
643    /// #
644    /// # fn f(message_data: &[u8]) -> Result<PacketPile> {
645    /// let message = PacketParserBuilder::from_bytes(message_data)?
646    ///     .buffer_unread_content()
647    ///     .into_packet_pile()?;
648    /// # return Ok(message);
649    /// # }
650    /// ```
651    pub fn into_packet_pile(self) -> Result<PacketPile> {
652        PacketPile::try_from(self.build()?)
653    }
654}
655
656#[cfg(test)]
657mod test {
658    use super::*;
659
660    use crate::types::CompressionAlgorithm;
661    use crate::types::DataFormat::Unicode;
662    use crate::packet::Literal;
663    use crate::packet::CompressedData;
664    use crate::packet::seip::SEIP1;
665    use crate::packet::Tag;
666    use crate::parse::Parse;
667
668    #[test]
669    fn deserialize_test_1 () {
670        // XXX: This test should be more thorough.  Right now, we mostly
671        // just rely on the fact that an assertion is not thrown.
672
673        // A flat message.
674        let pile = PacketPile::from_bytes(crate::tests::key("public-key.pgp"))
675            .unwrap();
676        eprintln!("PacketPile has {} top-level packets.",
677                  pile.children().len());
678        eprintln!("PacketPile: {:?}", pile);
679
680        let mut count = 0;
681        for (i, p) in pile.descendants().enumerate() {
682            eprintln!("{}: {:?}", i, p);
683            count += 1;
684        }
685
686        assert_eq!(count, 61);
687    }
688
689    #[cfg(feature = "compression-deflate")]
690    #[test]
691    fn deserialize_test_2 () {
692        // A message containing a compressed packet that contains a
693        // literal packet.
694        let pile = PacketPile::from_bytes(
695            crate::tests::message("compressed-data-algo-1.pgp")).unwrap();
696        eprintln!("PacketPile has {} top-level packets.",
697                  pile.children().len());
698        eprintln!("PacketPile: {:?}", pile);
699
700        let mut count = 0;
701        for (i, p) in pile.descendants().enumerate() {
702            eprintln!("{}: {:?}", i, p);
703            count += 1;
704        }
705        assert_eq!(count, 2);
706    }
707
708    #[cfg(feature = "compression-deflate")]
709    #[test]
710    fn deserialize_test_3 () {
711        let pile =
712            PacketPile::from_bytes(crate::tests::message("signed.pgp")).unwrap();
713        eprintln!("PacketPile has {} top-level packets.",
714                  pile.children().len());
715        eprintln!("PacketPile: {:?}", pile);
716
717        let mut count = 0;
718        for (i, p) in pile.descendants().enumerate() {
719            count += 1;
720            eprintln!("{}: {:?}", i, p);
721        }
722        // We expect 6 packets.
723        assert_eq!(count, 6);
724    }
725
726    // dkg's key contains packets from different OpenPGP
727    // implementations.  And, it even includes some v3 signatures.
728    //
729    // lutz's key is a v3 key.
730    #[test]
731    fn torture() {
732        use std::convert::TryInto;
733        use crate::parse::PacketPileParser;
734
735        let data = crate::tests::key("dkg.pgp");
736        let mut ppp: PacketPileParser =
737            PacketParserBuilder::from_bytes(data).unwrap()
738            //.trace()
739            .buffer_unread_content()
740            .try_into().unwrap();
741
742        while ppp.packet().is_ok() {
743            ppp.recurse().unwrap();
744        }
745        let pile = ppp.finish();
746        //pile.pretty_print();
747        assert_eq!(pile.children().len(), 1450);
748
749        let data = crate::tests::key("lutz.pgp");
750        let mut ppp: PacketPileParser =
751            PacketParserBuilder::from_bytes(data).unwrap()
752            //.trace()
753            .buffer_unread_content()
754            .try_into().unwrap();
755
756        while let Ok(pp) = ppp.packet().as_ref() {
757            eprintln!("{:?}", pp);
758            ppp.recurse().unwrap();
759        }
760        let pile = ppp.finish();
761        pile.pretty_print();
762        assert_eq!(pile.children().len(), 77);
763    }
764
765    #[cfg(feature = "compression-deflate")]
766    #[test]
767    fn compression_quine_test_1 () {
768        // Use the PacketPile::from_file interface to parse an OpenPGP
769        // quine.
770        let max_recursion_depth = 128;
771        let pile = PacketParserBuilder::from_bytes(
772            crate::tests::message("compression-quine.pgp")).unwrap()
773            .max_recursion_depth(max_recursion_depth)
774            .into_packet_pile().unwrap();
775
776        let mut count = 0;
777        for (i, p) in pile.descendants().enumerate() {
778            count += 1;
779            if false {
780                eprintln!("{}: p: {:?}", i, p);
781            }
782        }
783
784        assert_eq!(count, 1 + max_recursion_depth);
785    }
786
787    #[cfg(feature = "compression-deflate")]
788    #[test]
789    fn compression_quine_test_2 () {
790        // Use the iterator interface to parse an OpenPGP quine.
791        let max_recursion_depth = 255;
792        let mut ppr : PacketParserResult
793            = PacketParserBuilder::from_bytes(
794                crate::tests::message("compression-quine.pgp")).unwrap()
795                .max_recursion_depth(max_recursion_depth)
796                .build().unwrap();
797
798        let mut count = 0;
799        loop {
800            if let PacketParserResult::Some(pp2) = ppr {
801                count += 1;
802
803                let packet_depth = pp2.recursion_depth();
804                let pp2 = pp2.recurse().unwrap().1;
805                assert_eq!(packet_depth, count - 1);
806                if pp2.is_some() {
807                    assert_eq!(pp2.as_ref().unwrap().recursion_depth(), count);
808                }
809                ppr = pp2;
810            } else {
811                break;
812            }
813        }
814        assert_eq!(count, 1 + max_recursion_depth as isize);
815    }
816
817    #[cfg(feature = "compression-deflate")]
818    #[test]
819    fn consume_content_1 () {
820        use std::io::Read;
821        use crate::parse::PacketParser;
822        // A message containing a compressed packet that contains a
823        // literal packet.  When we read some of the compressed
824        // packet, we expect recurse() to not recurse.
825
826        let ppr = PacketParserBuilder::from_bytes(
827                crate::tests::message("compressed-data-algo-1.pgp")).unwrap()
828            .buffer_unread_content()
829            .build().unwrap();
830
831        let mut pp = ppr.unwrap();
832        if let Packet::CompressedData(_) = pp.packet {
833        } else {
834            panic!("Expected a compressed packet!");
835        }
836
837        // Read some of the body of the compressed packet.
838        let mut data = [0u8; 1];
839        let amount = pp.read(&mut data).unwrap();
840        assert_eq!(amount, 1);
841
842        // recurse should now not recurse.  Since there is nothing
843        // following the compressed packet, ppr should be EOF.
844        let (packet, ppr) = pp.next().unwrap();
845        assert!(ppr.is_eof());
846
847        // Get the rest of the content and put the initial byte that
848        // we stole back.
849        let mut content = packet.processed_body().unwrap().to_vec();
850        content.insert(0, data[0]);
851
852        let ppr = PacketParser::from_bytes(&content).unwrap();
853        let pp = ppr.unwrap();
854        if let Packet::Literal(_) = pp.packet {
855        } else {
856            panic!("Expected a literal packet!");
857        }
858
859        // And we're done...
860        let ppr = pp.next().unwrap().1;
861        assert!(ppr.is_eof());
862    }
863
864    #[test]
865    fn path_ref() {
866        // 0: SEIP
867        //  0: CompressedData
868        //   0: Literal("one")
869        //   1: Literal("two")
870        //   2: Literal("three")
871        //   3: Literal("four")
872        let mut packets : Vec<Packet> = Vec::new();
873
874        let text = [ &b"one"[..], &b"two"[..],
875                      &b"three"[..], &b"four"[..] ].to_vec();
876
877        let mut cd = CompressedData::new(CompressionAlgorithm::Uncompressed);
878        for t in text.iter() {
879            let mut lit = Literal::new(Unicode);
880            lit.set_body(t.to_vec());
881            cd = cd.push(lit.into())
882        }
883
884        let mut seip = SEIP1::new();
885        seip.container_mut().children_mut().unwrap().push(cd.into());
886        packets.push(seip.into());
887
888        eprintln!("{:#?}", packets);
889
890        let mut pile = PacketPile::from(packets);
891
892        assert_eq!(pile.path_ref(&[ 0 ]).unwrap().tag(), Tag::SEIP);
893        assert_eq!(pile.path_ref_mut(&[ 0 ]).unwrap().tag(), Tag::SEIP);
894        assert_eq!(pile.path_ref(&[ 0, 0 ]).unwrap().tag(),
895                   Tag::CompressedData);
896        assert_eq!(pile.path_ref_mut(&[ 0, 0 ]).unwrap().tag(),
897                   Tag::CompressedData);
898
899        for (i, t) in text.into_iter().enumerate() {
900            assert_eq!(pile.path_ref(&[ 0, 0, i ]).unwrap().tag(),
901                       Tag::Literal);
902            assert_eq!(pile.path_ref_mut(&[ 0, 0, i ]).unwrap().tag(),
903                       Tag::Literal);
904
905            let packet = pile.path_ref(&[ 0, 0, i ]).unwrap();
906            if let Packet::Literal(l) = packet {
907                assert_eq!(l.body(), t);
908            } else {
909                panic!("Expected literal, got: {:?}", packet);
910            }
911            let packet = pile.path_ref_mut(&[ 0, 0, i ]).unwrap();
912            if let Packet::Literal(l) = packet {
913                assert_eq!(l.body(), t);
914            } else {
915                panic!("Expected literal, got: {:?}", packet);
916            }
917        }
918
919        // Try a few out of bounds accesses.
920        assert!(pile.path_ref(&[ 0, 0, 4 ]).is_none());
921        assert!(pile.path_ref_mut(&[ 0, 0, 4 ]).is_none());
922
923        assert!(pile.path_ref(&[ 0, 0, 5 ]).is_none());
924        assert!(pile.path_ref_mut(&[ 0, 0, 5 ]).is_none());
925
926        assert!(pile.path_ref(&[ 0, 1 ]).is_none());
927        assert!(pile.path_ref_mut(&[ 0, 1 ]).is_none());
928
929        assert!(pile.path_ref(&[ 0, 2 ]).is_none());
930        assert!(pile.path_ref_mut(&[ 0, 2 ]).is_none());
931
932        assert!(pile.path_ref(&[ 1 ]).is_none());
933        assert!(pile.path_ref_mut(&[ 1 ]).is_none());
934
935        assert!(pile.path_ref(&[ 2 ]).is_none());
936        assert!(pile.path_ref_mut(&[ 2 ]).is_none());
937
938        assert!(pile.path_ref(&[ 0, 1, 0 ]).is_none());
939        assert!(pile.path_ref_mut(&[ 0, 1, 0 ]).is_none());
940
941        assert!(pile.path_ref(&[ 0, 2, 0 ]).is_none());
942        assert!(pile.path_ref_mut(&[ 0, 2, 0 ]).is_none());
943    }
944
945    #[test]
946    fn replace() {
947        // 0: Literal("one")
948        // =>
949        // 0: Literal("two")
950        let mut one = Literal::new(Unicode);
951        one.set_body(b"one".to_vec());
952        let mut two = Literal::new(Unicode);
953        two.set_body(b"two".to_vec());
954        let mut packets : Vec<Packet> = Vec::new();
955        packets.push(one.into());
956
957        assert!(packets.iter().map(|p| p.tag()).collect::<Vec<Tag>>()
958                == [ Tag::Literal ]);
959
960        let mut pile = PacketPile::from(packets.clone());
961        pile.replace(
962            &[ 0 ], 1,
963            [ two.into()
964            ].to_vec()).unwrap();
965
966        let children = pile.into_children().collect::<Vec<Packet>>();
967        assert_eq!(children.len(), 1, "{:#?}", children);
968        if let Packet::Literal(ref literal) = children[0] {
969            assert_eq!(literal.body(), &b"two"[..], "{:#?}", literal);
970        } else {
971            panic!("WTF");
972        }
973
974        // We start with four packets, and replace some of them with
975        // up to 3 packets.
976        let initial
977            = [ &b"one"[..], &b"two"[..], &b"three"[..], &b"four"[..] ].to_vec();
978        let inserted
979            = [ &b"a"[..], &b"b"[..], &b"c"[..] ].to_vec();
980
981        let mut packets : Vec<Packet> = Vec::new();
982        for text in initial.iter() {
983            let mut lit = Literal::new(Unicode);
984            lit.set_body(text.to_vec());
985            packets.push(lit.into())
986        }
987
988        for start in 0..initial.len() + 1 {
989            for delete in 0..initial.len() - start + 1 {
990                for insert in 0..inserted.len() + 1 {
991                    let mut pile = PacketPile::from(packets.clone());
992
993                    let mut replacement : Vec<Packet> = Vec::new();
994                    for &text in inserted[0..insert].iter() {
995                        let mut lit = Literal::new(Unicode);
996                        lit.set_body(text.to_vec());
997                        replacement.push(lit.into());
998                    }
999
1000                    pile.replace(&[ start ], delete, replacement).unwrap();
1001
1002                    let values = pile
1003                        .children()
1004                        .map(|p| {
1005                            if let Packet::Literal(ref literal) = p {
1006                                literal.body()
1007                            } else {
1008                                panic!("Expected a literal packet, got: {:?}", p);
1009                            }
1010                        })
1011                        .collect::<Vec<&[u8]>>();
1012
1013                    assert_eq!(values.len(), initial.len() - delete + insert);
1014
1015                    assert_eq!(values[..start],
1016                               initial[..start]);
1017                    assert_eq!(values[start..start + insert],
1018                               inserted[..insert]);
1019                    assert_eq!(values[start + insert..],
1020                               initial[start + delete..]);
1021                }
1022            }
1023        }
1024
1025
1026        // Like above, but the packets to replace are not at the
1027        // top-level, but in a compressed data packet.
1028
1029        let initial
1030            = [ &b"one"[..], &b"two"[..], &b"three"[..], &b"four"[..] ].to_vec();
1031        let inserted
1032            = [ &b"a"[..], &b"b"[..], &b"c"[..] ].to_vec();
1033
1034        let mut cd = CompressedData::new(CompressionAlgorithm::Uncompressed);
1035        for l in initial.iter() {
1036            let mut lit = Literal::new(Unicode);
1037            lit.set_body(l.to_vec());
1038            cd = cd.push(lit.into());
1039        }
1040
1041        for start in 0..initial.len() + 1 {
1042            for delete in 0..initial.len() - start + 1 {
1043                for insert in 0..inserted.len() + 1 {
1044                    let mut pile = PacketPile::from(
1045                        vec![ cd.clone().into() ]);
1046
1047                    let mut replacement : Vec<Packet> = Vec::new();
1048                    for &text in inserted[0..insert].iter() {
1049                        let mut lit = Literal::new(Unicode);
1050                        lit.set_body(text.to_vec());
1051                        replacement.push(lit.into());
1052                    }
1053
1054                    pile.replace(&[ 0, start ], delete, replacement).unwrap();
1055
1056                    let top_level = pile.children().collect::<Vec<&Packet>>();
1057                    assert_eq!(top_level.len(), 1);
1058
1059                    let values = top_level[0]
1060                        .children().unwrap()
1061                        .map(|p| {
1062                            if let Packet::Literal(ref literal) = p {
1063                                literal.body()
1064                            } else {
1065                                panic!("Expected a literal packet, got: {:?}", p);
1066                            }
1067                        })
1068                        .collect::<Vec<&[u8]>>();
1069
1070                    assert_eq!(values.len(), initial.len() - delete + insert);
1071
1072                    assert_eq!(values[..start],
1073                               initial[..start]);
1074                    assert_eq!(values[start..start + insert],
1075                               inserted[..insert]);
1076                    assert_eq!(values[start + insert..],
1077                               initial[start + delete..]);
1078                }
1079            }
1080        }
1081
1082        // Make sure out-of-range accesses error out.
1083        let mut one = Literal::new(Unicode);
1084        one.set_body(b"one".to_vec());
1085        let mut packets : Vec<Packet> = Vec::new();
1086        packets.push(one.into());
1087        let mut pile = PacketPile::from(packets.clone());
1088
1089        assert!(pile.replace(&[ 1 ], 0, Vec::new()).is_ok());
1090        assert!(pile.replace(&[ 2 ], 0, Vec::new()).is_err());
1091        assert!(pile.replace(&[ 0 ], 2, Vec::new()).is_err());
1092        assert!(pile.replace(&[ 0, 0 ], 0, Vec::new()).is_err());
1093        assert!(pile.replace(&[ 0, 1 ], 0, Vec::new()).is_err());
1094
1095        // Try the same thing, but with a container.
1096        let mut packets : Vec<Packet> = Vec::new();
1097        packets.push(CompressedData::new(CompressionAlgorithm::Uncompressed)
1098                     .into());
1099        let mut pile = PacketPile::from(packets.clone());
1100
1101        assert!(pile.replace(&[ 1 ], 0, Vec::new()).is_ok());
1102        assert!(pile.replace(&[ 2 ], 0, Vec::new()).is_err());
1103        assert!(pile.replace(&[ 0 ], 2, Vec::new()).is_err());
1104        // Since this is a container, this should be okay.
1105        assert!(pile.replace(&[ 0, 0 ], 0, Vec::new()).is_ok());
1106        assert!(pile.replace(&[ 0, 1 ], 0, Vec::new()).is_err());
1107    }
1108}