Documentation improvements

This commit is contained in:
link2xt
2023-02-10 17:22:33 +00:00
parent bb702a9342
commit 2a5fa9a0d3
12 changed files with 206 additions and 26 deletions

View File

@@ -1,7 +1,5 @@
//! # Chat module.
#![allow(missing_docs)]
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::fmt;
@@ -60,6 +58,7 @@ pub enum ChatItem {
},
}
/// Chat protection status.
#[derive(
Debug,
Display,
@@ -77,7 +76,12 @@ pub enum ChatItem {
)]
#[repr(u32)]
pub enum ProtectionStatus {
/// Chat is not protected.
Unprotected = 0,
/// Chat is protected.
///
/// All members of the chat must be verified.
Protected = 1,
}
@@ -295,7 +299,7 @@ impl ChatId {
Ok(chat_id)
}
pub async fn set_selfavatar_timestamp(self, context: &Context, timestamp: i64) -> Result<()> {
async fn set_selfavatar_timestamp(self, context: &Context, timestamp: i64) -> Result<()> {
context
.sql
.execute(
@@ -680,6 +684,7 @@ impl ChatId {
Ok(())
}
/// Returns ID of the draft message, if there is one.
async fn get_draft_msg_id(self, context: &Context) -> Result<Option<MsgId>> {
let msg_id: Option<MsgId> = context
.sql
@@ -691,6 +696,7 @@ impl ChatId {
Ok(msg_id)
}
/// Returns draft message, if there is one.
pub async fn get_draft(self, context: &Context) -> Result<Option<Message>> {
if self.is_special() {
return Ok(None);
@@ -704,7 +710,7 @@ impl ChatId {
}
}
/// Delete draft message in specified chat, if there is one.
/// Deletes draft message, if there is one.
///
/// Returns `true`, if message was deleted, `false` otherwise.
async fn maybe_delete_draft(self, context: &Context) -> Result<bool> {
@@ -826,6 +832,7 @@ impl ChatId {
Ok(count)
}
/// Returns the number of fresh messages in the chat.
pub async fn get_fresh_msg_cnt(self, context: &Context) -> Result<usize> {
// this function is typically used to show a badge counter beside _each_ chatlist item.
// to make this as fast as possible, esp. on older devices, we added an combined index over the rows used for querying.
@@ -892,7 +899,7 @@ impl ChatId {
Ok(promoted)
}
// Returns true if chat is a saved messages chat.
/// Returns true if chat is a saved messages chat.
pub async fn is_self_talk(self, context: &Context) -> Result<bool> {
Ok(self.get_param(context).await?.exists(Param::Selftalk))
}
@@ -1130,15 +1137,29 @@ pub struct Chat {
/// Chat type, e.g. 1:1 chat, group chat, mailing list.
pub typ: Chattype,
/// Chat name.
pub name: String,
/// Whether the chat is archived or pinned.
pub visibility: ChatVisibility,
/// Group ID.
pub grpid: String,
/// Whether the chat is blocked, unblocked or a contact request.
pub(crate) blocked: Blocked,
/// Additional chat parameters stored in the database.
pub param: Params,
/// If location streaming is enabled in the chat.
is_sending_locations: bool,
/// Duration of the chat being muted.
pub mute_duration: MuteDuration,
/// If the chat is protected (verified).
protected: ProtectionStatus,
}
@@ -1258,7 +1279,7 @@ impl Chat {
}
}
pub async fn update_param(&mut self, context: &Context) -> Result<()> {
pub(crate) async fn update_param(&mut self, context: &Context) -> Result<()> {
context
.sql
.execute(
@@ -1314,6 +1335,10 @@ impl Chat {
Ok(None)
}
/// Returns chat avatar color.
///
/// For 1:1 chats, the color is calculated from the contact's address.
/// For group chats the color is calculated from the chat name.
pub async fn get_color(&self, context: &Context) -> Result<u32> {
let mut color = 0;
@@ -1360,6 +1385,7 @@ impl Chat {
})
}
/// Returns chat visibilitiy, e.g. whether it is archived or pinned.
pub fn get_visibility(&self) -> ChatVisibility {
self.visibility
}
@@ -1372,10 +1398,12 @@ impl Chat {
self.blocked == Blocked::Request
}
/// Returns true if the chat is not promoted.
pub fn is_unpromoted(&self) -> bool {
self.param.get_bool(Param::Unpromoted).unwrap_or_default()
}
/// Returns true if the chat is promoted.
pub fn is_promoted(&self) -> bool {
!self.is_unpromoted()
}
@@ -1390,6 +1418,7 @@ impl Chat {
self.is_sending_locations
}
/// Returns true if the chat is currently muted.
pub fn is_muted(&self) -> bool {
match self.mute_duration {
MuteDuration::NotMuted => false,
@@ -1974,6 +2003,7 @@ impl ChatIdBlocked {
}
}
/// Prepares a message for sending.
pub async fn prepare_msg(context: &Context, chat_id: ChatId, msg: &mut Message) -> Result<MsgId> {
ensure!(
!chat_id.is_special(),
@@ -2331,6 +2361,9 @@ async fn create_send_msg_job(context: &Context, msg_id: MsgId) -> Result<Option<
Ok(Some(row_id))
}
/// Sends a text message to the given chat.
///
/// Returns database ID of the sent message.
pub async fn send_text_msg(
context: &Context,
chat_id: ChatId,
@@ -2663,6 +2696,12 @@ pub(crate) async fn mark_old_messages_as_noticed(
Ok(())
}
/// Returns all database message IDs of the given types.
///
/// If `chat_id` is None, return messages from any chat.
///
/// `Viewtype::Unknown` can be used for `msg_type2` and `msg_type3`
/// if less than 3 viewtypes are requested.
pub async fn get_chat_media(
context: &Context,
chat_id: Option<ChatId>,
@@ -2706,10 +2745,14 @@ pub async fn get_chat_media(
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(i32)]
pub enum Direction {
/// Search forward.
Forward = 1,
/// Search backward.
Backward = -1,
}
/// Searches next/previous message based on the given message and list of types.
pub async fn get_next_media(
context: &Context,
curr_msg_id: MsgId,
@@ -3400,6 +3443,9 @@ pub async fn forward_msgs(context: &Context, msg_ids: &[MsgId], chat_id: ChatId)
Ok(())
}
/// Resends given messages with the same Message-ID.
///
/// This is primarily intended to make existing webxdcs available to new chat members.
pub async fn resend_msgs(context: &Context, msg_ids: &[MsgId]) -> Result<()> {
let mut chat_id = None;
let mut msgs: Vec<Message> = Vec::new();
@@ -3598,6 +3644,7 @@ pub async fn add_device_msg(
add_device_msg_with_importance(context, label, msg, false).await
}
/// Returns true if device message with a given label was ever added to the device chat.
pub async fn was_device_msg_ever_added(context: &Context, label: &str) -> Result<bool> {
ensure!(!label.is_empty(), "empty label");
let exists = context

View File

@@ -103,18 +103,26 @@ pub enum Config {
/// Own avatar filename.
Selfavatar,
/// Send BCC copy to self.
///
/// Should be enabled for multidevice setups.
#[strum(props(default = "1"))]
BccSelf,
/// True if encryption is preferred according to Autocrypt standard.
#[strum(props(default = "1"))]
E2eeEnabled,
/// True if Message Delivery Notifications (read receipts) should
/// be sent and requested.
#[strum(props(default = "1"))]
MdnsEnabled,
/// True if "Sent" folder should be watched for changes.
#[strum(props(default = "0"))]
SentboxWatch,
/// True if chat messages should be moved to a separate folder.
#[strum(props(default = "1"))]
MvboxMove,
@@ -125,9 +133,11 @@ pub enum Config {
#[strum(props(default = "0"))]
OnlyFetchMvbox,
/// Whether to show classic emails or only chat messages.
#[strum(props(default = "0"))] // also change ShowEmails.default() on changes
ShowEmails,
/// Quality of the media files to send.
#[strum(props(default = "0"))] // also change MediaQuality.default() on changes
MediaQuality,
@@ -142,6 +152,7 @@ pub enum Config {
#[strum(props(default = "1"))]
FetchedExistingMsgs,
/// Type of the OpenPGP key to generate.
#[strum(props(default = "0"))]
KeyGenType,
@@ -164,7 +175,9 @@ pub enum Config {
#[strum(props(default = "0"))]
DeleteDeviceAfter,
/// Save raw MIME messages with headers in the database if true.
SaveMimeHeaders,
/// The primary email address. Also see `SecondaryAddrs`.
ConfiguredAddr,
@@ -196,6 +209,8 @@ pub enum Config {
/// Configured SMTP server port.
ConfiguredSendPort,
ConfiguredSmtpCertificateChecks,
/// Whether OAuth 2 is used with configured provider.
ConfiguredServerFlags,
ConfiguredSendSecurity,
ConfiguredE2EEEnabled,
@@ -203,7 +218,11 @@ pub enum Config {
ConfiguredMvboxFolder,
ConfiguredSentboxFolder,
ConfiguredTimestamp,
/// ID of the configured provider from the provider database.
ConfiguredProvider,
/// True if account is configured.
Configured,
/// All secondary self addresses separated by spaces
@@ -219,6 +238,7 @@ pub enum Config {
#[strum(serialize = "sys.config_keys")]
SysConfigKeys,
/// True if it is a bot account.
Bot,
/// Whether we send a warning if the password is wrong (set to false when we send a warning
@@ -293,28 +313,33 @@ impl Context {
}
}
/// Returns 32-bit signed integer configuration value for the given key.
pub async fn get_config_int(&self, key: Config) -> Result<i32> {
self.get_config(key)
.await
.map(|s: Option<String>| s.and_then(|s| s.parse().ok()).unwrap_or_default())
}
/// Returns 64-bit signed integer configuration value for the given key.
pub async fn get_config_i64(&self, key: Config) -> Result<i64> {
self.get_config(key)
.await
.map(|s: Option<String>| s.and_then(|s| s.parse().ok()).unwrap_or_default())
}
/// Returns 64-bit unsigned integer configuration value for the given key.
pub async fn get_config_u64(&self, key: Config) -> Result<u64> {
self.get_config(key)
.await
.map(|s: Option<String>| s.and_then(|s| s.parse().ok()).unwrap_or_default())
}
/// Returns boolean configuration value for the given key.
pub async fn get_config_bool(&self, key: Config) -> Result<bool> {
Ok(self.get_config_int(key).await? != 0)
}
/// Returns true if movebox ("DeltaChat" folder) should be watched.
pub(crate) async fn should_watch_mvbox(&self) -> Result<bool> {
Ok(self.get_config_bool(Config::MvboxMove).await?
|| self.get_config_bool(Config::OnlyFetchMvbox).await?)

View File

@@ -1,7 +1,5 @@
//! Context module.
#![allow(missing_docs)]
use std::collections::{BTreeMap, HashMap};
use std::ffi::OsString;
use std::ops::Deref;

View File

@@ -240,7 +240,7 @@ fn mimepart_to_data_url(mail: &mailparse::ParsedMail<'_>) -> Result<String> {
}
impl MsgId {
/// Get HTML from a message-id.
/// Get HTML by database message id.
/// This requires `mime_headers` field to be set for the message;
/// this is the case at least when `Message.has_html()` returns true
/// (we do not save raw mime unconditionally in the database to save space).

View File

@@ -1,7 +1,5 @@
//! # Import/export module.
#![allow(missing_docs)]
use std::any::Any;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
@@ -38,6 +36,7 @@ use crate::{e2ee, tools};
const DBFILE_BACKUP_NAME: &str = "dc_database_backup.sqlite";
const BLOBS_BACKUP_NAME: &str = "blobs_backup";
/// Import/export command.
#[derive(Debug, Display, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
#[repr(u32)]
pub enum ImexMode {
@@ -220,6 +219,7 @@ pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result<St
))
}
/// Creates a new setup code for Autocrypt Setup Message.
pub fn create_setup_code(_context: &Context) -> String {
let mut random_val: u16;
let mut rng = thread_rng();
@@ -258,6 +258,10 @@ async fn maybe_add_bcc_self_device_msg(context: &Context) -> Result<()> {
Ok(())
}
/// Continue key transfer via Autocrypt Setup Message.
///
/// `msg_id` is the ID of the received Autocrypt Setup Message.
/// `setup_code` is the code entered by the user.
pub async fn continue_key_transfer(
context: &Context,
msg_id: MsgId,

View File

@@ -244,12 +244,18 @@ pub struct Message {
/// ID of the first contact in the `To:` header.
pub(crate) to_id: ContactId,
/// ID of the chat message belongs to.
pub(crate) chat_id: ChatId,
/// Type of the message.
pub(crate) viewtype: Viewtype,
/// State of the message.
pub(crate) state: MessageState,
pub(crate) download_state: DownloadState,
/// Whether the message is hidden.
pub(crate) hidden: bool,
pub(crate) timestamp_sort: i64,
pub(crate) timestamp_sent: i64,
@@ -257,8 +263,14 @@ pub struct Message {
pub(crate) ephemeral_timer: EphemeralTimer,
pub(crate) ephemeral_timestamp: i64,
pub(crate) text: Option<String>,
/// Message subject.
pub(crate) subject: String,
/// `Message-ID` header value.
pub(crate) rfc724_mid: String,
/// `In-Reply-To` header value.
pub(crate) in_reply_to: Option<String>,
pub(crate) is_dc_message: MessengerMessage,
pub(crate) mime_modified: bool,

View File

@@ -49,12 +49,18 @@ use crate::{location, tools};
/// using the [MimeMessage::from_bytes] constructor.
#[derive(Debug)]
pub struct MimeMessage {
/// Parsed MIME parts.
pub parts: Vec<Part>,
/// Message headers.
header: HashMap<String, String>,
/// Addresses are normalized and lowercased:
pub recipients: Vec<SingleInfo>,
/// `From:` address.
pub from: SingleInfo,
/// Whether the From address was repeated in the signed part
/// (and we know that the signer intended to send from this address)
pub from_is_signed: bool,
@@ -72,6 +78,8 @@ pub struct MimeMessage {
/// The set of mail recipient addresses for which gossip headers were applied, regardless of
/// whether they modified any peerstates.
pub gossiped_addr: HashSet<String>,
/// True if the message is a forwarded message.
pub is_forwarded: bool,
pub is_system_message: SystemMessage,
pub location_kml: Option<location::Kml>,
@@ -128,10 +136,20 @@ pub(crate) enum MailinglistType {
#[repr(u32)]
pub enum SystemMessage {
Unknown = 0,
/// Group name changed.
GroupNameChanged = 2,
/// Group avatar changed.
GroupImageChanged = 3,
/// Member was added to the group.
MemberAddedToGroup = 4,
/// Member was removed from the group.
MemberRemovedFromGroup = 5,
/// Autocrypt Setup Message.
AutocryptSetupMessage = 6,
SecurejoinMessage = 7,
LocationStreamingEnabled = 8,
@@ -140,20 +158,22 @@ pub enum SystemMessage {
/// Chat ephemeral message timer is changed.
EphemeralTimerChanged = 10,
// Chat protection state changed
/// Chat protection is enabled.
ChatProtectionEnabled = 11,
/// Chat protection is disabled.
ChatProtectionDisabled = 12,
/// Self-sent-message that contains only json used for multi-device-sync;
/// if possible, we attach that to other messages as for locations.
MultiDeviceSync = 20,
// Sync message that contains a json payload
// sent to the other webxdc instances
// These messages are not shown in the chat.
/// Sync message that contains a json payload
/// sent to the other webxdc instances
/// These messages are not shown in the chat.
WebxdcStatusUpdate = 30,
// Webxdc info added with `info` set in `send_webxdc_status_update()`.
/// Webxdc info added with `info` set in `send_webxdc_status_update()`.
WebxdcInfoMessage = 32,
}
@@ -1764,16 +1784,32 @@ fn is_known(key: &str) -> bool {
)
}
/// Parsed MIME part.
#[derive(Debug, Default, Clone)]
pub struct Part {
/// Type of the MIME part determining how it should be displayed.
pub typ: Viewtype,
/// MIME type.
pub mimetype: Option<Mime>,
/// Message text to be displayed in the chat.
pub msg: String,
/// Message text to be displayed in message info.
pub msg_raw: Option<String>,
/// Size of the MIME part in bytes.
pub bytes: usize,
pub param: Params,
/// Attachment filename.
pub(crate) org_filename: Option<String>,
/// An error detected during parsing.
pub error: Option<String>,
/// True if conversion from HTML to plaintext failed.
pub(crate) dehtml_failed: bool,
/// the part is a child or a descendant of multipart/related.

View File

@@ -1,13 +1,13 @@
//! Handle plain text together with some attributes.
#![allow(missing_docs)]
use once_cell::sync::Lazy;
use crate::simplify::split_lines;
/// Plaintext message body together with format=flowed attributes.
#[derive(Debug)]
pub struct PlainText {
/// The text itself.
pub text: String,
/// Text may "flowed" as defined in [RFC 2646](https://tools.ietf.org/html/rfc2646).

View File

@@ -1,7 +1,5 @@
//! [Provider database](https://providers.delta.chat/) module.
#![allow(missing_docs)]
mod data;
use anyhow::Result;
@@ -12,27 +10,46 @@ use crate::config::Config;
use crate::context::Context;
use crate::provider::data::{PROVIDER_DATA, PROVIDER_IDS, PROVIDER_UPDATED};
/// Provider status according to manual testing.
#[derive(Debug, Display, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
#[repr(u8)]
pub enum Status {
/// Provider is known to be working with Delta Chat.
Ok = 1,
/// Provider works with Delta Chat, but requires some preparation,
/// such as changing the settings in the web interface.
Preparation = 2,
/// Provider is known not to work with Delta Chat.
Broken = 3,
}
/// Server protocol.
#[derive(Debug, Display, PartialEq, Eq, Copy, Clone, FromPrimitive, ToPrimitive)]
#[repr(u8)]
pub enum Protocol {
/// SMTP protocol.
Smtp = 1,
/// IMAP protocol.
Imap = 2,
}
/// Socket security.
#[derive(Debug, Display, PartialEq, Eq, Copy, Clone, FromPrimitive, ToPrimitive)]
#[repr(u8)]
pub enum Socket {
/// Unspecified socket security, select automatically.
Automatic = 0,
/// TLS connection.
Ssl = 1,
/// STARTTLS connection.
Starttls = 2,
/// No TLS, plaintext connection.
Plain = 3,
}
@@ -42,47 +59,89 @@ impl Default for Socket {
}
}
/// Pattern used to construct login usernames from email addresses.
#[derive(Debug, PartialEq, Eq, Clone)]
#[repr(u8)]
pub enum UsernamePattern {
/// Whole email is used as username.
Email = 1,
/// Part of address before `@` is used as username.
Emaillocalpart = 2,
}
/// Type of OAuth 2 authorization.
#[derive(Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum Oauth2Authorizer {
/// Yandex.
Yandex = 1,
/// Gmail.
Gmail = 2,
}
/// Email server endpoint.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Server {
/// Server protocol, e.g. SMTP or IMAP.
pub protocol: Protocol,
/// Port security, e.g. TLS or STARTTLS.
pub socket: Socket,
/// Server host.
pub hostname: &'static str,
/// Server port.
pub port: u16,
/// Pattern used to construct login usernames from email addresses.
pub username_pattern: UsernamePattern,
}
/// Pair of key and value for default configuration.
#[derive(Debug, PartialEq, Eq)]
pub struct ConfigDefault {
/// Configuration variable name.
pub key: Config,
/// Configuration variable value.
pub value: &'static str,
}
/// Provider database entry.
#[derive(Debug, PartialEq, Eq)]
pub struct Provider {
/// Unique ID, corresponding to provider database filename.
pub id: &'static str,
/// Provider status according to manual testing.
pub status: Status,
/// Hint to be shown to the user on the login screen.
pub before_login_hint: &'static str,
/// Hint to be added to the device chat after provider configuration.
pub after_login_hint: &'static str,
/// URL of the page with provider overview.
pub overview_page: &'static str,
/// List of provider servers.
pub server: Vec<Server>,
/// Default configuration values to set when provider is configured.
pub config_defaults: Option<Vec<ConfigDefault>>,
/// True if provider is known to use use proper,
/// not self-signed certificates.
pub strict_tls: bool,
/// Maximum number of recipients the provider allows to send a single email to.
pub max_smtp_rcpt_to: Option<u16>,
/// Type of OAuth 2 authorization if provider supports it.
pub oauth2_authorizer: Option<Oauth2Authorizer>,
}
@@ -175,6 +234,7 @@ pub async fn get_provider_by_mx(context: &Context, domain: &str) -> Option<&'sta
None
}
/// Returns a provider with the given ID from the database.
pub fn get_provider_by_id(id: &str) -> Option<&'static Provider> {
if let Some(provider) = PROVIDER_IDS.get(id) {
Some(provider)
@@ -183,7 +243,7 @@ pub fn get_provider_by_id(id: &str) -> Option<&'static Provider> {
}
}
// returns update timestamp in seconds, UTC, compatible for comparison with time() and database times
/// Returns update timestamp as a unix timestamp compatible for comparison with time() and database times.
pub fn get_provider_update_timestamp() -> i64 {
NaiveDateTime::new(*PROVIDER_UPDATED, NaiveTime::from_hms_opt(0, 0, 0).unwrap())
.timestamp_millis()

View File

@@ -1,5 +1,3 @@
#![allow(missing_docs)]
use core::fmt;
use std::{ops::Deref, sync::Arc};
@@ -538,6 +536,7 @@ impl Context {
Ok(ret)
}
/// Returns true if all background work is done.
pub async fn all_work_done(&self) -> bool {
let lock = self.scheduler.read().await;
let stores: Vec<_> = match &*lock {

View File

@@ -1,7 +1,5 @@
//! Verified contact protocol implementation as [specified by countermitm project](https://countermitm.readthedocs.io/en/stable/new.html#setup-contact-protocol).
#![allow(missing_docs)]
use std::convert::TryFrom;
use anyhow::{bail, Context as _, Error, Result};
@@ -35,6 +33,7 @@ use qrinvite::QrInvite;
use crate::token::Namespace;
/// Set of characters to percent-encode in email addresses and names.
pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
macro_rules! inviter_progress {