summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi/include/sequoia/openpgp.h14
-rw-r--r--ffi/src/openpgp.rs34
-rw-r--r--net/src/async.rs2
-rw-r--r--net/tests/hkp.rs6
-rw-r--r--openpgp/src/armor.rs120
-rw-r--r--openpgp/src/autocrypt.rs5
-rw-r--r--openpgp/src/parse/parse.rs3
-rw-r--r--openpgp/src/reader.rs2
-rw-r--r--openpgp/src/tpk/mod.rs3
-rw-r--r--tool/src/sq.rs2
10 files changed, 100 insertions, 91 deletions
diff --git a/ffi/include/sequoia/openpgp.h b/ffi/include/sequoia/openpgp.h
index d4027ed0..dd19dae5 100644
--- a/ffi/include/sequoia/openpgp.h
+++ b/ffi/include/sequoia/openpgp.h
@@ -121,6 +121,11 @@ int sq_fingerprint_equal (const sq_fingerprint_t a, const sq_fingerprint_t b);
/*/
typedef enum sq_armor_kind {
/*/
+ /// When reading an Armored file, accept any type.
+ /*/
+ SQ_ARMOR_KIND_ANY,
+
+ /*/
/// A generic OpenPGP message.
/*/
SQ_ARMOR_KIND_MESSAGE,
@@ -145,11 +150,6 @@ typedef enum sq_armor_kind {
/*/
SQ_ARMOR_KIND_FILE,
- /*/
- /// When reading an Armored file, accept any type.
- /*/
- SQ_ARMOR_KIND_ANY,
-
/* Dummy value to make sure the enumeration has a defined size. Do
not use this value. */
SQ_ARMOR_KIND_FORCE_WIDTH = INT_MAX,
@@ -188,7 +188,9 @@ sq_reader_t sq_armor_reader_from_bytes (const uint8_t *b, size_t len,
/*/
/// Returns the kind of data this reader is for.
///
-/// Useful in combination with `Kind::Any`.
+/// Useful if the kind of data is not known in advance. If the header
+/// has not been encountered yet (try reading some data first!), this
+/// function returns SQ_ARMOR_KIND_ANY.
/*/
sq_armor_kind_t sq_armor_reader_kind (sq_reader_t reader);
diff --git a/ffi/src/openpgp.rs b/ffi/src/openpgp.rs
index a4866b16..5b6f773f 100644
--- a/ffi/src/openpgp.rs
+++ b/ffi/src/openpgp.rs
@@ -214,26 +214,26 @@ pub struct ArmorHeader {
value: *const c_char,
}
-fn int_to_kind(kind: c_int) -> armor::Kind {
+fn int_to_kind(kind: c_int) -> Option<armor::Kind> {
match kind {
- 0 => armor::Kind::Message,
- 1 => armor::Kind::PublicKey,
- 2 => armor::Kind::SecretKey,
- 3 => armor::Kind::Signature,
- 4 => armor::Kind::File,
- 5 => armor::Kind::Any,
+ 0 => None,
+ 1 => Some(armor::Kind::Message),
+ 2 => Some(armor::Kind::PublicKey),
+ 3 => Some(armor::Kind::SecretKey),
+ 4 => Some(armor::Kind::Signature),
+ 5 => Some(armor::Kind::File),
_ => panic!("Bad kind: {}", kind),
}
}
-fn kind_to_int(kind: armor::Kind) -> c_int {
+fn kind_to_int(kind: Option<armor::Kind>) -> c_int {
match kind {
- armor::Kind::Message => 0,
- armor::Kind::PublicKey => 1,
- armor::Kind::SecretKey => 2,
- armor::Kind::Signature => 3,
- armor::Kind::File => 4,
- armor::Kind::Any => 5,
+ None => 0,
+ Some(armor::Kind::Message) => 1,
+ Some(armor::Kind::PublicKey) => 2,
+ Some(armor::Kind::SecretKey) => 3,
+ Some(armor::Kind::Signature) => 4,
+ Some(armor::Kind::File) => 5,
}
}
@@ -364,7 +364,9 @@ pub extern "system" fn sq_armor_reader_from_bytes(b: *const uint8_t, len: size_t
/// Returns the kind of data this reader is for.
///
-/// Useful in combination with `Kind::Any`.
+/// Useful if the kind of data is not known in advance. If the header
+/// has not been encountered yet (try reading some data first!), this
+/// function returns SQ_ARMOR_KIND_ANY.
///
/// # Example
///
@@ -549,7 +551,7 @@ pub extern "system" fn sq_armor_writer_new
{
let ctx = ctx.expect("Context is NULL");
let inner = inner.expect("Inner is NULL");
- let kind = int_to_kind(kind);
+ let kind = int_to_kind(kind).expect("KIND must not be SQ_ARMOR_KIND_ANY");
let mut header_ = Vec::new();
if header_len > 0 {
diff --git a/net/src/async.rs b/net/src/async.rs
index 7af6f2ae..77ec00bc 100644
--- a/net/src/async.rs
+++ b/net/src/async.rs
@@ -130,7 +130,7 @@ impl KeyServer {
StatusCode::OK => {
let c = Cursor::new(body.as_ref());
let r = armor::Reader::new(
- c, armor::Kind::PublicKey);
+ c, Some(armor::Kind::PublicKey));
future::done(TPK::from_reader(r))
},
StatusCode::NOT_FOUND =>
diff --git a/net/tests/hkp.rs b/net/tests/hkp.rs
index 4acbf56d..cbb86532 100644
--- a/net/tests/hkp.rs
+++ b/net/tests/hkp.rs
@@ -22,7 +22,7 @@ extern crate openpgp;
extern crate sequoia_core;
extern crate sequoia_net;
-use openpgp::armor::{Reader, Kind};
+use openpgp::armor::Reader;
use openpgp::TPK;
use openpgp::{Fingerprint, KeyID};
use sequoia_core::{Context, NetworkPolicy};
@@ -92,7 +92,7 @@ fn service(req: Request<Body>)
"keytext" => {
let key = TPK::from_reader(
Reader::new(Cursor::new(value.into_owned()),
- Kind::Any)).unwrap();
+ None)).unwrap();
assert_eq!(
key.fingerprint(),
Fingerprint::from_hex(FP)
@@ -171,6 +171,6 @@ fn send() {
let mut keyserver =
KeyServer::new(&ctx, &format!("hkp://{}", addr)).unwrap();
let key = TPK::from_reader(Reader::new(Cursor::new(RESPONSE),
- Kind::Any)).unwrap();
+ None)).unwrap();
keyserver.send(&key).unwrap();
}
diff --git a/openpgp/src/armor.rs b/openpgp/src/armor.rs
index 7cfb599e..166391aa 100644
--- a/openpgp/src/armor.rs
+++ b/openpgp/src/armor.rs
@@ -21,7 +21,7 @@
//! use openpgp::armor::{Reader, Kind};
//!
//! let mut file = File::open("somefile.asc").unwrap();
-//! let mut r = Reader::new(&mut file, Kind::File);
+//! let mut r = Reader::new(&mut file, Some(Kind::File));
//! ```
extern crate base64;
@@ -61,8 +61,6 @@ pub enum Kind {
Signature,
/// A generic file. This is a GnuPG extension.
File,
- /// When reading an Armored file, accept any type.
- Any,
}
impl Arbitrary for Kind {
@@ -111,7 +109,6 @@ impl Kind {
&Kind::SecretKey => "PRIVATE KEY BLOCK",
&Kind::Signature => "SIGNATURE",
&Kind::File => "ARMORED FILE",
- &Kind::Any => unreachable!(),
}
}
@@ -176,7 +173,6 @@ impl<W: Write> Writer<W> {
/// # }
/// ```
pub fn new(inner: W, kind: Kind, headers: &[(&str, &str)]) -> Result<Self> {
- assert!(kind != Kind::Any);
let mut w = Writer {
sink: inner,
kind: kind,
@@ -326,7 +322,7 @@ impl<W: Write> Drop for Writer<W> {
/// as the line the header is in is only prefixed by whitespace.
pub struct Reader<'a> {
source: Box<'a + BufferedReader<()>>,
- kind: Kind,
+ kind: Option<Kind>,
buffer: Vec<u8>,
crc: CRC,
expect_crc: Option<u32>,
@@ -355,16 +351,16 @@ impl<'a> Reader<'a> {
/// -----END PGP ARMORED FILE-----";
///
/// let mut cursor = io::Cursor::new(&data);
- /// let mut reader = Reader::new(&mut cursor, Kind::Any);
+ /// let mut reader = Reader::new(&mut cursor, None);
///
/// let mut content = String::new();
/// reader.read_to_string(&mut content)?;
/// assert_eq!(content, "Hello world!");
- /// assert_eq!(reader.kind(), Kind::File);
+ /// assert_eq!(reader.kind(), Some(Kind::File));
/// # Ok(())
/// # }
/// ```
- pub fn new<R>(inner: R, kind: Kind) -> Self
+ pub fn new<R>(inner: R, kind: Option<Kind>) -> Self
where R: 'a + Read
{
Self::from_buffered_reader(
@@ -373,7 +369,7 @@ impl<'a> Reader<'a> {
}
/// Creates a `Reader` from an `io::Read`er.
- pub fn from_reader<R>(reader: R, kind: Kind) -> Self
+ pub fn from_reader<R>(reader: R, kind: Option<Kind>) -> Self
where R: 'a + Read
{
Self::from_buffered_reader(
@@ -382,7 +378,7 @@ impl<'a> Reader<'a> {
}
/// Creates a `Reader` from a file.
- pub fn from_file<P>(path: P, kind: Kind) -> Result<Self>
+ pub fn from_file<P>(path: P, kind: Option<Kind>) -> Result<Self>
where P: AsRef<Path>
{
Ok(Self::from_buffered_reader(
@@ -391,14 +387,14 @@ impl<'a> Reader<'a> {
}
/// Creates a `Reader` from a buffer.
- pub fn from_bytes(bytes: &'a [u8], kind: Kind) -> Self {
+ pub fn from_bytes(bytes: &'a [u8], kind: Option<Kind>) -> Self {
Self::from_buffered_reader(
Box::new(BufferedReaderMemory::new(bytes)),
kind)
}
pub(crate) fn from_buffered_reader(inner: Box<'a + BufferedReader<()>>,
- kind: Kind) -> Self {
+ kind: Option<Kind>) -> Self {
Reader {
source: Box::new(BufferedReaderGeneric::new(inner, None)),
kind: kind,
@@ -413,8 +409,10 @@ impl<'a> Reader<'a> {
/// Returns the kind of data this reader is for.
///
- /// Useful in combination with `Kind::Any`.
- pub fn kind(&self) -> Kind {
+ /// Useful if the kind of data is not known in advance. If the
+ /// header has not been encountered yet (try reading some data
+ /// first!), this function returns None.
+ pub fn kind(&self) -> Option<Kind> {
self.kind
}
@@ -444,13 +442,13 @@ impl<'a> Reader<'a> {
for i in 0..(line.len() - 27 + 1) {
if let Some(kind) = Kind::detect(&line[i..]) {
- if self.kind == Kind::Any {
+ if self.kind == None {
// Found any!
- self.kind = kind;
+ self.kind = Some(kind);
break 'search;
}
- if self.kind == kind {
+ if self.kind == Some(kind) {
// Found it!
break 'search;
}
@@ -515,7 +513,7 @@ impl<'a> Reader<'a> {
}
/// Parses the footer.
- fn finalize(footer: &[u8], kind: Kind) -> Result<Option<u32>> {
+ fn finalize(footer: &[u8], kind: Option<Kind>) -> Result<Option<u32>> {
let mut off = 0;
/* Look for CRC. The CRC is optional. */
@@ -545,8 +543,10 @@ impl<'a> Reader<'a> {
None
};
- if ! footer[off..].starts_with(&kind.end().into_bytes()) {
- return Err(Error::new(ErrorKind::InvalidInput, "Invalid ASCII Armor footer."));
+ if let Some(kind) = kind {
+ if ! footer[off..].starts_with(&kind.end().into_bytes()) {
+ return Err(Error::new(ErrorKind::InvalidInput, "Invalid ASCII Armor footer."));
+ }
}
Ok(crc)
@@ -654,7 +654,7 @@ impl<'a> Read for Reader<'a> {
// Later, we may have to get some more until we have a
// multiple of four non-whitespace ASCII characters.
let mut want = (buf.len() - read + 2) / 3 * 4
- + self.kind.footer_max_len();
+ + self.kind.map(|k| k.footer_max_len()).unwrap_or(46);
// Keep track of how much we got last time to detect
// hitting EOF.
@@ -670,28 +670,31 @@ impl<'a> Read for Reader<'a> {
}
// Check if we see the footer. If so, we're almost done.
- if let Some((n, end)) = find_footer(&raw, self.kind) {
- self.expect_crc = Reader::finalize(&raw[n..], self.kind)?;
- self.finalized = true;
- match base64::decode_config(&raw[..n], base64::MIME) {
- Ok(d) => break (end, d),
- Err(e) =>
- return Err(Error::new(ErrorKind::InvalidInput, e)),
- }
- } else {
- let n = &raw.iter().filter(
- |c| ! (**c).is_ascii_whitespace()).count();
- if n % 4 == 0 {
- // Success, try to decode it.
- match base64::decode_config(&raw, base64::MIME) {
- Ok(d) => break (raw.len(), d),
- Err(e) => return Err(Error::new(ErrorKind::InvalidInput, e)),
+ if let Some(kind) = self.kind {
+ if let Some((n, end)) = find_footer(&raw, kind) {
+ self.expect_crc = Reader::finalize(&raw[n..], self.kind)?;
+ self.finalized = true;
+ match base64::decode_config(&raw[..n], base64::MIME) {
+ Ok(d) => break (end, d),
+ Err(e) =>
+ return Err(Error::new(ErrorKind::InvalidInput, e)),
}
}
+ }
- // Get some more bytes.
- want = got + 4 - n % 4;
+ // See how many non-whitespace characters we got.
+ let n = &raw.iter().filter(
+ |c| ! (**c).is_ascii_whitespace()).count();
+ if n % 4 == 0 {
+ // Enough! Try to decode them.
+ match base64::decode_config(&raw, base64::MIME) {
+ Ok(d) => break (raw.len(), d),
+ Err(e) => return Err(Error::new(ErrorKind::InvalidInput, e)),
+ }
}
+
+ // Otherwise, get some more bytes.
+ want = got + 4 - n % 4;
}
};
self.source.consume(consumed);
@@ -754,8 +757,7 @@ impl<'a> Read for Reader<'a> {
macro_rules! armored {
($data:expr) => {{
use ::std::io::Cursor;
- $crate::armor::Reader::new(Cursor::new(&$data),
- $crate::armor::Kind::Any)
+ $crate::armor::Reader::new(Cursor::new(&$data), None)
}};
}
@@ -875,7 +877,7 @@ mod test {
fn dearmor_binary() {
for len in TEST_VECTORS.iter() {
let mut file = File::open(format!("tests/data/armor/test-{}.bin", len)).unwrap();
- let mut r = Reader::new(&mut file, Kind::Message);
+ let mut r = Reader::new(&mut file, Some(Kind::Message));
let mut buf = [0; 5];
let e = r.read(&mut buf);
assert!(e.is_err());
@@ -885,7 +887,7 @@ mod test {
#[test]
fn dearmor_wrong_kind() {
let mut file = File::open("tests/data/armor/test-0.asc").unwrap();
- let mut r = Reader::new(&mut file, Kind::Message);
+ let mut r = Reader::new(&mut file, Some(Kind::Message));
let mut buf = [0; 5];
let e = r.read(&mut buf);
assert!(e.is_err());
@@ -894,7 +896,7 @@ mod test {
#[test]
fn dearmor_wrong_crc() {
let mut file = File::open("tests/data/armor/test-0.bad-crc.asc").unwrap();
- let mut r = Reader::new(&mut file, Kind::File);
+ let mut r = Reader::new(&mut file, Some(Kind::File));
let mut buf = [0; 5];
let e = r.read(&mut buf);
assert!(e.is_err());
@@ -903,7 +905,7 @@ mod test {
#[test]
fn dearmor_wrong_footer() {
let mut file = File::open("tests/data/armor/test-2.bad-footer.asc").unwrap();
- let mut r = Reader::new(&mut file, Kind::File);
+ let mut r = Reader::new(&mut file, Some(Kind::File));
let mut buf = [0; 5];
let e = r.read(&mut buf);
assert!(e.is_err());
@@ -912,7 +914,7 @@ mod test {
#[test]
fn dearmor_no_crc() {
let mut file = File::open("tests/data/armor/test-1.no-crc.asc").unwrap();
- let mut r = Reader::new(&mut file, Kind::File);
+ let mut r = Reader::new(&mut file, Some(Kind::File));
let mut buf = [0; 5];
let e = r.read(&mut buf);
assert!(e.unwrap() == 1 && buf[0] == 0xde);
@@ -921,7 +923,7 @@ mod test {
#[test]
fn dearmor_with_header() {
let mut file = File::open("tests/data/armor/test-3.with-headers.asc").unwrap();
- let mut r = Reader::new(&mut file, Kind::File);
+ let mut r = Reader::new(&mut file, Some(Kind::File));
assert_eq!(r.headers().unwrap(),
&[("Comment".into(), "Some Header".into()),
("Comment".into(), "Another one".into())]);
@@ -933,10 +935,10 @@ mod test {
#[test]
fn dearmor_any() {
let mut file = File::open("tests/data/armor/test-3.with-headers.asc").unwrap();
- let mut r = Reader::new(&mut file, Kind::Any);
+ let mut r = Reader::new(&mut file, None);
let mut buf = [0; 5];
let e = r.read(&mut buf);
- assert!(r.kind() == Kind::File);
+ assert!(r.kind() == Some(Kind::File));
assert!(e.is_ok());
}
@@ -956,10 +958,10 @@ mod test {
write!(&mut garbage, "Some\ngarbage\nlines\n\t\r ").unwrap();
garbage.extend_from_slice(&armored);
- let mut r = Reader::new(Cursor::new(&garbage), Kind::Any);
+ let mut r = Reader::new(Cursor::new(&garbage), None);
let mut buf = [0; 5];
let e = r.read(&mut buf);
- assert!(r.kind() == Kind::File);
+ assert!(r.kind() == Some(Kind::File));
assert!(e.is_ok());
// Again, but this time add a non-whitespace character in the
@@ -968,7 +970,7 @@ mod test {
write!(&mut garbage, "Some\ngarbage\nlines\n\t.\r ").unwrap();
garbage.extend_from_slice(&armored);
- let mut r = Reader::new(Cursor::new(&garbage), Kind::Any);
+ let mut r = Reader::new(Cursor::new(&garbage), None);
let mut buf = [0; 5];
let e = r.read(&mut buf);
assert!(e.is_err());
@@ -982,7 +984,7 @@ mod test {
file.read_to_end(&mut bin).unwrap();
let mut file = File::open(format!("tests/data/armor/test-{}.asc", len)).unwrap();
- let mut r = Reader::new(&mut file, Kind::File);
+ let mut r = Reader::new(&mut file, Some(Kind::File));
let mut dearmored = Vec::<u8>::new();
r.read_to_end(&mut dearmored).unwrap();
@@ -998,7 +1000,7 @@ mod test {
file.read_to_end(&mut bin).unwrap();
let mut file = File::open(format!("tests/data/armor/test-{}.asc", len)).unwrap();
- let r = Reader::new(&mut file, Kind::File);
+ let r = Reader::new(&mut file, Some(Kind::File));
let mut dearmored = Vec::<u8>::new();
for c in r.bytes() {
dearmored.push(c.unwrap());
@@ -1013,14 +1015,14 @@ mod test {
let mut file =
File::open("tests/data/keys/yuge-key-so-yuge-the-yugest.asc")
.unwrap();
- let mut r = Reader::new(&mut file, Kind::Any);
+ let mut r = Reader::new(&mut file, None);
let mut dearmored = Vec::<u8>::new();
r.read_to_end(&mut dearmored).unwrap();
let mut file =
File::open("tests/data/keys/yuge-key-so-yuge-the-yugest.asc")
.unwrap();
- let r = Reader::new(&mut file, Kind::Any);
+ let r = Reader::new(&mut file, None);
let mut dearmored = Vec::<u8>::new();
for c in r.bytes() {
dearmored.push(c.unwrap());
@@ -1037,12 +1039,12 @@ mod test {
.unwrap();
let mut recovered = Vec::new();
- Reader::new(Cursor::new(&encoded), kind)
+ Reader::new(Cursor::new(&encoded), Some(kind))
.read_to_end(&mut recovered)
.unwrap();
let mut recovered_any = Vec::new();
- Reader::new(Cursor::new(&encoded), Kind::Any)
+ Reader::new(Cursor::new(&encoded), None)
.read_to_end(&mut recovered_any)
.unwrap();
diff --git a/openpgp/src/autocrypt.rs b/openpgp/src/autocrypt.rs
index 5cfdf9ad..73d982bb 100644
--- a/openpgp/src/autocrypt.rs
+++ b/openpgp/src/autocrypt.rs
@@ -422,7 +422,7 @@ impl AutocryptSetupMessage {
-> Result<AutocryptSetupMessageParser<'a>> {
// The outer message uses ASCII-armor. It includes a password
// hint. Hence, we need to parse it aggressively.
- let mut r = armor::Reader::new(r, armor::Kind::Message);
+ let mut r = armor::Reader::new(r, Some(armor::Kind::Message));
// Note, it is essential that we call r.headers here so that
// we can return any error now and not in
@@ -604,7 +604,8 @@ impl<'a> AutocryptSetupMessageParser<'a> {
// The inner message consists of an ASCII-armored encoded
// TSK.
let (prefer_encrypt, tsk) = {
- let mut r = armor::Reader::new(&mut pp, armor::Kind::SecretKey);
+ let mut r = armor::Reader::new(&mut pp,
+ Some(armor::Kind::SecretKey));
let prefer_encrypt = {
let headers = r.headers()?;
diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs
index 95f706d7..0f4240dc 100644
--- a/openpgp/src/parse/parse.rs
+++ b/openpgp/src/parse/parse.rs
@@ -3154,7 +3154,8 @@ mod test {
// The following TPK is corrupted about a third the way
// through. Make sure we can recover.
let mut ppr = PacketParser::from_reader(
- Reader::from_bytes(bytes!("../keys/corrupted.pgp"), Kind::PublicKey))
+ Reader::from_bytes(bytes!("../keys/corrupted.pgp"),
+ Some(Kind::PublicKey)))
.unwrap();
let mut sigs = 0;
diff --git a/openpgp/src/reader.rs b/openpgp/src/reader.rs
index 0406e6c3..dd84132d 100644
--- a/openpgp/src/reader.rs
+++ b/openpgp/src/reader.rs
@@ -22,7 +22,7 @@ impl<'a> Reader<'a> {
Ok(Reader(br))
} else {
Ok(Reader(Box::new(BufferedReaderGeneric::new(
- armor::Reader::from_buffered_reader(br, armor::Kind::Any),
+ armor::Reader::from_buffered_reader(br, None),
None))))
}
}
diff --git a/openpgp/src/tpk/mod.rs b/openpgp/src/tpk/mod.rs
index c9c92fad..497ffc2b 100644
--- a/openpgp/src/tpk/mod.rs
+++ b/openpgp/src/tpk/mod.rs
@@ -2035,7 +2035,8 @@ mod test {
cur.set_position(0);
- let r = armor::Reader::from_reader(&mut cur, armor::Kind::SecretKey);
+ let r = armor::Reader::from_reader(&mut cur,
+ Some(armor::Kind::SecretKey));
let t2 = TPK::from_reader(r).unwrap();
assert_eq!(t1.tpk().fingerprint(), t2.fingerprint());
diff --git a/tool/src/sq.rs b/tool/src/sq.rs
index 353a6574..2d0b3411 100644
--- a/tool/src/sq.rs
+++ b/tool/src/sq.rs
@@ -101,7 +101,7 @@ fn real_main() -> Result<(), failure::Error> {
("dearmor", Some(m)) => {
let mut input = open_or_stdin(m.value_of("input"))?;
let mut output = create_or_stdout(m.value_of("output"))?;
- let mut filter = armor::Reader::new(&mut input, armor::Kind::Any);
+ let mut filter = armor::Reader::new(&mut input, None);
io::copy(&mut filter, &mut output)?;
},
("autocrypt", Some(m)) => {