/*
* melib - gpgme module
*
* Copyright 2020 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use crate::email::{
pgp::{DecryptionMetadata, Recipient},
Address,
};
use crate::error::{ErrorKind, IntoMeliError, MeliError, Result, ResultIntoMeliError};
use futures::FutureExt;
use smol::Async;
use std::borrow::Cow;
use std::collections::HashMap;
use std::ffi::{CStr, CString, OsStr};
use std::future::Future;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::Path;
use std::sync::{Arc, Mutex};
const GPGME_MIN_VERSION: &str = "1.12.0";
macro_rules! call {
($lib:expr, $func:ty) => {{
let func: libloading::Symbol<$func> =
$lib.get(stringify!($func).as_bytes()).expect(concat!(
"Could not use libgpgme: symbol ",
stringify!($func),
" not found!"
));
func
}};
}
macro_rules! c_string_literal {
($lit:literal) => {{
unsafe {
CStr::from_bytes_with_nul_unchecked(concat!($lit, "\0").as_bytes()).as_ptr()
as *const ::std::os::raw::c_char
}
}};
}
mod bindings;
use bindings::*;
mod io;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GpgmeFlag {
///"auto-key-retrieve"
AutoKeyRetrieve,
OfflineMode,
}
bitflags! {
pub struct LocateKey: u8 {
/// Locate a key using DNS CERT, as specified in RFC-4398.
const CERT = 0b1;
/// Locate a key using DNS PKA.
const PKA = 0b10;
/// Locate a key using DANE, as specified in draft-ietf-dane-openpgpkey-05.txt.
const DANE = 0b100;
/// Locate a key using the Web Key Directory protocol.
const WKD = 0b1000;
/// Using DNS Service Discovery, check the domain in question for any LDAP keyservers to use. If this fails, attempt to locate the key using the PGP Universal method of checking ‘ldap://keys.(thedomain)’.
const LDAP = 0b10000;
/// Locate a key using a keyserver.
const KEYSERVER = 0b100000;
/// In addition, a keyserver URL as used in the dirmngr configuration may be used here to query that particular keyserver.
const KEYSERVER_URL = 0b1000000;
/// Locate the key using the local keyrings. This mechanism allows the user to select the order a local key lookup is done. Thus using ‘--auto-key-locate local’ is identical to --no-auto-key-locate.
const LOCAL = 0b10000000;
/// This flag disables the standard local key lookup, done before any of the mechanisms defined by the --auto-key-locate are tried. The position of this mechanism in the list does not matter. It is not required if local is also used.
const NODEFAULT = 0;
}
}
struct IoState {
max_idx: usize,
ops: HashMap<usize, GpgmeFd>,
done: Arc<Mutex<Option<Result<()>>>>,
sender: smol::channel::Sender<()>,
receiver: smol::channel::Receiver<()>,
key_sender: smol::channel::Sender<KeyInner>,
key_receiver: smol::channel::Receiver<KeyInner>,
lib: Arc<libloading::Library>,
}
unsafe impl Send for IoState {}
unsafe impl Sync for IoState {}
pub struct ContextInner {
inner: core::ptr::NonNull<gpgme_context>,
lib: Arc<libloading::Library>,
}
unsafe impl Send for ContextInner {}
unsafe impl Sync for ContextInner {}
pub struct Context {
inner: Arc<ContextInner>,
io_state: Arc<Mutex<IoState>>,
}
unsafe impl Send for Context {}
unsafe impl Sync for Context {}
impl Drop for ContextInner {
#[inline]
fn drop(&mut self) {
unsafe { call!(self.lib, gpgme_release)(self.inner.as_mut()) }
}
}
impl Context {
pub fn new() -> Result<Self> {
let version = CString::new(GPGME_MIN_VERSION).unwrap();