wip
This commit is contained in:
parent
534833d616
commit
4913b2ac9d
13 changed files with 67 additions and 20 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll, Waker};
|
||||
|
@ -20,11 +20,11 @@ use tokio_rustls::{
|
|||
|
||||
use crate::command::Command;
|
||||
use crate::response::{Capability, Response, ResponseCode};
|
||||
use crate::types::Status;
|
||||
use crate::types::{Capability as Capability_, Status};
|
||||
|
||||
use super::ClientConfig;
|
||||
|
||||
pub type CapsLock = Arc<RwLock<Option<Vec<Capability>>>>;
|
||||
pub type CapsLock = Arc<RwLock<Option<HashSet<Capability>>>>;
|
||||
pub type ResultMap = Arc<RwLock<HashMap<usize, (Option<Response>, Option<Waker>)>>>;
|
||||
pub type GreetingState = Arc<RwLock<(bool, Option<Waker>)>>;
|
||||
pub const TAG_PREFIX: &str = "panorama";
|
||||
|
@ -130,6 +130,10 @@ where
|
|||
/// Attempts to upgrade this connection using STARTTLS
|
||||
pub async fn upgrade(mut self) -> Result<Client<TlsStream<C>>> {
|
||||
// TODO: make sure STARTTLS is in the capability list
|
||||
if !self.has_capability("STARTTLS").await? {
|
||||
bail!("server doesn't support this capability");
|
||||
}
|
||||
|
||||
// first, send the STARTTLS command
|
||||
let resp = self.execute(Command::Starttls).await?;
|
||||
debug!("server response to starttls: {:?}", resp);
|
||||
|
@ -154,6 +158,34 @@ where
|
|||
|
||||
Ok(Client::new(stream, self.config))
|
||||
}
|
||||
|
||||
/// Check if this client has a particular capability
|
||||
pub async fn has_capability(&self, cap: impl AsRef<str>) -> Result<bool> {
|
||||
let cap = cap.as_ref().to_owned();
|
||||
debug!("checking for the capability: {:?}", cap);
|
||||
|
||||
let cap_bytes = cap.as_bytes();
|
||||
debug!("cap_bytes {:?}", cap_bytes);
|
||||
let (_, cap) = match crate::oldparser::rfc3501::capability(cap_bytes) {
|
||||
Ok(v) => v,
|
||||
Err(err) => {
|
||||
error!("ERROR PARSING {:?} {} {:?}", cap, err, err);
|
||||
use std::error::Error;
|
||||
let bt = err.backtrace().unwrap();
|
||||
error!("{}", bt);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let cap = Capability::from(cap);
|
||||
|
||||
let caps = &*self.caps.read();
|
||||
// TODO: refresh caps
|
||||
|
||||
let caps = caps.as_ref().unwrap();
|
||||
let result = caps.contains(&cap);
|
||||
debug!("cap result: {:?}", result);
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GreetingWaiter(GreetingState);
|
||||
|
@ -226,7 +258,7 @@ where
|
|||
}
|
||||
|
||||
debug!("got a new line {:?}", next_line);
|
||||
let (_, resp) = match crate::parser::parse_response(next_line.as_bytes()) {
|
||||
let (_, resp) = match crate::oldparser::parse_response(next_line.as_bytes()) {
|
||||
Ok(v) => v,
|
||||
Err(err) => {
|
||||
debug!("shiet: {:?}", err);
|
||||
|
@ -246,6 +278,7 @@ where
|
|||
let resp = Response::from(resp);
|
||||
debug!("resp: {:?}", resp);
|
||||
match &resp {
|
||||
// capabilities list
|
||||
Response::Capabilities(new_caps)
|
||||
| Response::Data {
|
||||
status: Status::Ok,
|
||||
|
@ -253,10 +286,18 @@ where
|
|||
..
|
||||
} => {
|
||||
let caps = &mut *caps.write();
|
||||
*caps = Some(new_caps.clone());
|
||||
*caps = Some(new_caps.iter().cloned().collect());
|
||||
debug!("new caps: {:?}", caps);
|
||||
}
|
||||
|
||||
// bye
|
||||
Response::Data {
|
||||
status: Status::Bye,
|
||||
..
|
||||
} => {
|
||||
bail!("disconnected");
|
||||
}
|
||||
|
||||
Response::Done { tag, .. } => {
|
||||
let tag_str = &tag.0;
|
||||
if tag_str.starts_with(TAG_PREFIX) {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(backtrace)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate anyhow;
|
||||
#[macro_use]
|
||||
|
@ -10,9 +12,9 @@ extern crate log;
|
|||
pub mod builders;
|
||||
pub mod client;
|
||||
pub mod command;
|
||||
pub mod parser;
|
||||
pub mod oldparser;
|
||||
pub mod response;
|
||||
pub mod types;
|
||||
|
||||
pub use crate::parser::ParseResult;
|
||||
pub use crate::oldparser::ParseResult;
|
||||
pub use crate::types::*;
|
||||
|
|
|
@ -8,7 +8,7 @@ use nom::{
|
|||
IResult,
|
||||
};
|
||||
|
||||
use crate::{parser::core::*, types::*};
|
||||
use crate::{oldparser::core::*, types::*};
|
||||
|
||||
pub fn section_part(i: &[u8]) -> IResult<&[u8], Vec<u32>> {
|
||||
let (i, (part, mut rest)) = tuple((number, many0(preceded(char('.'), number))))(i)?;
|
||||
|
|
|
@ -9,7 +9,7 @@ use nom::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
parser::{core::*, rfc3501::envelope},
|
||||
oldparser::{core::*, rfc3501::envelope},
|
||||
types::*,
|
||||
};
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ use nom::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
parser::{
|
||||
oldparser::{
|
||||
core::*, rfc3501::body::*, rfc3501::body_structure::*, rfc4315, rfc4551, rfc5161, rfc5464,
|
||||
rfc7162,
|
||||
},
|
||||
|
@ -181,7 +181,7 @@ fn resp_text_code(i: &[u8]) -> IResult<&[u8], ResponseCode> {
|
|||
)(i)
|
||||
}
|
||||
|
||||
fn capability(i: &[u8]) -> IResult<&[u8], Capability> {
|
||||
pub fn capability(i: &[u8]) -> IResult<&[u8], Capability> {
|
||||
alt((
|
||||
map(tag_no_case(b"IMAP4rev1"), |_| Capability::Imap4rev1),
|
||||
map(preceded(tag_no_case(b"AUTH="), atom), Capability::Auth),
|
||||
|
|
|
@ -13,7 +13,7 @@ use nom::{
|
|||
IResult,
|
||||
};
|
||||
|
||||
use crate::parser::core::number;
|
||||
use crate::oldparser::core::number;
|
||||
use crate::types::*;
|
||||
|
||||
/// Extends resp-text-code as follows:
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
use nom::{bytes::streaming::tag_no_case, sequence::tuple, IResult};
|
||||
|
||||
use crate::{
|
||||
parser::core::{number_64, paren_delimited},
|
||||
oldparser::core::{number_64, paren_delimited},
|
||||
types::*,
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use nom::{
|
|||
IResult,
|
||||
};
|
||||
|
||||
use crate::parser::core::atom;
|
||||
use crate::oldparser::core::atom;
|
||||
use crate::types::*;
|
||||
|
||||
// The ENABLED response lists capabilities that were enabled in response
|
||||
|
@ -23,7 +23,7 @@ pub(crate) fn resp_enabled(i: &[u8]) -> IResult<&[u8], Response> {
|
|||
map(enabled_data, Response::Capabilities)(i)
|
||||
}
|
||||
|
||||
fn enabled_data(i: &[u8]) -> IResult<&[u8], Vec<Capability>> {
|
||||
pub fn enabled_data(i: &[u8]) -> IResult<&[u8], Vec<Capability>> {
|
||||
let (i, (_, capabilities)) = tuple((
|
||||
tag_no_case("ENABLED"),
|
||||
many0(preceded(char(' '), capability)),
|
||||
|
@ -31,6 +31,6 @@ fn enabled_data(i: &[u8]) -> IResult<&[u8], Vec<Capability>> {
|
|||
Ok((i, capabilities))
|
||||
}
|
||||
|
||||
fn capability(i: &[u8]) -> IResult<&[u8], Capability> {
|
||||
pub fn capability(i: &[u8]) -> IResult<&[u8], Capability> {
|
||||
map(atom, Capability::Atom)(i)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use nom::{
|
|||
IResult,
|
||||
};
|
||||
|
||||
use crate::{parser::core::*, types::*};
|
||||
use crate::{oldparser::core::*, types::*};
|
||||
|
||||
fn is_entry_component_char(c: u8) -> bool {
|
||||
c < 0x80 && c > 0x19 && c != b'*' && c != b'%' && c != b'/'
|
||||
|
|
|
@ -10,7 +10,7 @@ use nom::{
|
|||
IResult,
|
||||
};
|
||||
|
||||
use crate::parser::core::sequence_set;
|
||||
use crate::oldparser::core::sequence_set;
|
||||
use crate::types::*;
|
||||
|
||||
// The VANISHED response reports that the specified UIDs have been
|
||||
|
|
|
@ -70,7 +70,7 @@ impl<'a> From<Response_<'a>> for Response {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum Capability {
|
||||
Imap4rev1,
|
||||
Auth(String),
|
||||
|
|
|
@ -40,7 +40,7 @@ pub enum Response<'a> {
|
|||
|
||||
impl<'a> Response<'a> {
|
||||
pub fn from_bytes(buf: &'a [u8]) -> crate::ParseResult {
|
||||
crate::parser::parse_response(buf)
|
||||
crate::oldparser::parse_response(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@ pub struct Rect(u16, u16, u16, u16);
|
|||
|
||||
/// UI entrypoint.
|
||||
pub async fn run_ui(mut w: impl Write + Debug, exit: ExitSender) -> Result<()> {
|
||||
loop {
|
||||
tokio::time::sleep(Duration::from_secs(4000)).await;
|
||||
}
|
||||
|
||||
execute!(w, cursor::Hide, terminal::EnterAlternateScreen)?;
|
||||
terminal::enable_raw_mode()?;
|
||||
|
||||
|
|
Loading…
Reference in a new issue