mirror of
https://github.com/chatmail/core.git
synced 2026-07-04 14:35:08 +03:00
Compare commits
5 Commits
v1.148.3
...
link2xt/ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
189a093e02 | ||
|
|
fc2b111f5d | ||
|
|
913d2c45b3 | ||
|
|
e32d676a08 | ||
|
|
9812d5ba75 |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## [1.148.4] - 2024-10-24
|
||||
|
||||
### Features / Changes
|
||||
|
||||
- Jsonrpc: add `private_tag` to `Account::Configured` Object ([#6107](https://github.com/deltachat/deltachat-core-rust/pull/6107)).
|
||||
|
||||
### Fixes
|
||||
|
||||
- Normalize proxy URLs before saving into proxy_url.
|
||||
- Do not wait for connections in maybe_add_gossip_peers().
|
||||
|
||||
## [1.148.3] - 2024-10-24
|
||||
|
||||
### Fixes
|
||||
@@ -5127,3 +5138,4 @@ https://github.com/deltachat/deltachat-core-rust/pulls?q=is%3Apr+is%3Aclosed
|
||||
[1.148.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.148.0..v1.148.1
|
||||
[1.148.2]: https://github.com/deltachat/deltachat-core-rust/compare/v1.148.1..v1.148.2
|
||||
[1.148.3]: https://github.com/deltachat/deltachat-core-rust/compare/v1.148.2..v1.148.3
|
||||
[1.148.4]: https://github.com/deltachat/deltachat-core-rust/compare/v1.148.3..v1.148.4
|
||||
|
||||
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -1293,11 +1293,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-broadcast",
|
||||
"async-channel 2.3.1",
|
||||
"async-compression",
|
||||
"async-imap",
|
||||
"async-native-tls",
|
||||
"async-smtp",
|
||||
@@ -1393,7 +1394,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat-jsonrpc"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-channel 2.3.1",
|
||||
@@ -1418,7 +1419,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat-repl"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deltachat",
|
||||
@@ -1434,7 +1435,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat-rpc-server"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deltachat",
|
||||
@@ -1463,7 +1464,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat_ffi"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deltachat",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
rust-version = "1.77"
|
||||
@@ -42,6 +42,7 @@ anyhow = { workspace = true }
|
||||
async-broadcast = "0.7.1"
|
||||
async-channel = { workspace = true }
|
||||
async-imap = { version = "0.10.2", default-features = false, features = ["runtime-tokio", "compress"] }
|
||||
async-compression = { version = "0.4.15", default-features = false, features = ["tokio", "gzip"] }
|
||||
async-native-tls = { version = "0.5", default-features = false, features = ["runtime-tokio"] }
|
||||
async-smtp = { version = "0.9", default-features = false, features = ["runtime-tokio"] }
|
||||
async_zip = { version = "0.0.17", default-features = false, features = ["deflate", "tokio-fs"] }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat_ffi"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
description = "Deltachat FFI"
|
||||
edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat-jsonrpc"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
description = "DeltaChat JSON-RPC API"
|
||||
edition = "2021"
|
||||
default-run = "deltachat-jsonrpc-server"
|
||||
|
||||
@@ -17,6 +17,9 @@ pub enum Account {
|
||||
// size: u32,
|
||||
profile_image: Option<String>, // TODO: This needs to be converted to work with blob http server.
|
||||
color: String,
|
||||
/// Optional tag as "Work", "Family".
|
||||
/// Meant to help profile owner to differ between profiles with similar names.
|
||||
private_tag: Option<String>,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
Unconfigured { id: u32 },
|
||||
@@ -31,12 +34,14 @@ impl Account {
|
||||
let color = color_int_to_hex_string(
|
||||
Contact::get_by_id(ctx, ContactId::SELF).await?.get_color(),
|
||||
);
|
||||
let private_tag = ctx.get_config(Config::PrivateTag).await?;
|
||||
Ok(Account::Configured {
|
||||
id,
|
||||
display_name,
|
||||
addr,
|
||||
profile_image,
|
||||
color,
|
||||
private_tag,
|
||||
})
|
||||
} else {
|
||||
Ok(Account::Unconfigured { id })
|
||||
|
||||
@@ -58,5 +58,5 @@
|
||||
},
|
||||
"type": "module",
|
||||
"types": "dist/deltachat.d.ts",
|
||||
"version": "1.148.3"
|
||||
"version": "1.148.4"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat-repl"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
license = "MPL-2.0"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/deltachat/deltachat-core-rust"
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "deltachat-rpc-client"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
description = "Python client for Delta Chat core JSON-RPC interface"
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
|
||||
@@ -61,7 +61,7 @@ def test_qr_securejoin(acfactory, protect, tmp_path):
|
||||
# Setup second device for Alice
|
||||
# to test observing securejoin protocol.
|
||||
alice.export_backup(tmp_path)
|
||||
files = list(tmp_path.glob("*.tar"))
|
||||
files = list(tmp_path.glob("*.tar.gz"))
|
||||
alice2 = acfactory.get_unconfigured_account()
|
||||
alice2.import_backup(files[0])
|
||||
|
||||
|
||||
@@ -379,7 +379,7 @@ def test_import_export_backup(acfactory, tmp_path) -> None:
|
||||
alice = acfactory.new_configured_account()
|
||||
alice.export_backup(tmp_path)
|
||||
|
||||
files = list(tmp_path.glob("*.tar"))
|
||||
files = list(tmp_path.glob("*.tar.gz"))
|
||||
alice2 = acfactory.get_unconfigured_account()
|
||||
alice2.import_backup(files[0])
|
||||
|
||||
@@ -630,7 +630,7 @@ def test_markseen_contact_request(acfactory, tmp_path):
|
||||
|
||||
# Bob sets up a second device.
|
||||
bob.export_backup(tmp_path)
|
||||
files = list(tmp_path.glob("*.tar"))
|
||||
files = list(tmp_path.glob("*.tar.gz"))
|
||||
bob2 = acfactory.get_unconfigured_account()
|
||||
bob2.import_backup(files[0])
|
||||
bob2.start_io()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat-rpc-server"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
description = "DeltaChat JSON-RPC server"
|
||||
edition = "2021"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
},
|
||||
"type": "module",
|
||||
"types": "index.d.ts",
|
||||
"version": "1.148.3"
|
||||
"version": "1.148.4"
|
||||
}
|
||||
|
||||
@@ -55,5 +55,5 @@
|
||||
"test:mocha": "mocha node/test/test.mjs --growl --reporter=spec --bail --exit"
|
||||
},
|
||||
"types": "node/dist/index.d.ts",
|
||||
"version": "1.148.3"
|
||||
"version": "1.148.4"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "deltachat"
|
||||
version = "1.148.3"
|
||||
version = "1.148.4"
|
||||
description = "Python bindings for the Delta Chat Core library using CFFI against the Rust-implemented libdeltachat"
|
||||
readme = "README.rst"
|
||||
requires-python = ">=3.7"
|
||||
|
||||
@@ -4,12 +4,16 @@
|
||||
|
||||
use deltachat_derive::{FromSql, ToSql};
|
||||
use once_cell::sync::Lazy;
|
||||
use percent_encoding::{AsciiSet, NON_ALPHANUMERIC};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::chat::ChatId;
|
||||
|
||||
pub static DC_VERSION_STR: Lazy<String> = Lazy::new(|| env!("CARGO_PKG_VERSION").to_string());
|
||||
|
||||
/// Set of characters to percent-encode in email addresses and names.
|
||||
pub(crate) const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Default,
|
||||
|
||||
72
src/imex.rs
72
src/imex.rs
@@ -11,7 +11,7 @@ use futures_lite::FutureExt;
|
||||
use pin_project::pin_project;
|
||||
|
||||
use tokio::fs::{self, File};
|
||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, ReadBuf};
|
||||
use tokio_tar::Archive;
|
||||
|
||||
use crate::blob::BlobDirContents;
|
||||
@@ -123,7 +123,7 @@ pub async fn has_backup(_context: &Context, dir_name: &Path) -> Result<String> {
|
||||
let name = dirent.file_name();
|
||||
let name: String = name.to_string_lossy().into();
|
||||
if name.starts_with("delta-chat")
|
||||
&& name.ends_with(".tar")
|
||||
&& (name.ends_with(".tar") || name.ends_with(".tar.gz"))
|
||||
&& (newest_backup_name.is_empty() || name > newest_backup_name)
|
||||
{
|
||||
// We just use string comparison to determine which backup is newer.
|
||||
@@ -269,30 +269,24 @@ async fn import_backup(
|
||||
context.get_dbfile().display()
|
||||
);
|
||||
|
||||
import_backup_stream(context, backup_file, file_size, passphrase).await?;
|
||||
let backup_file = ProgressReader::new(backup_file, context.clone(), file_size);
|
||||
if backup_to_import.extension() == Some(OsStr::new("gz")) {
|
||||
let backup_file = tokio::io::BufReader::new(backup_file);
|
||||
let backup_file = async_compression::tokio::bufread::GzipDecoder::new(backup_file);
|
||||
import_backup_stream(context, backup_file, passphrase).await?;
|
||||
} else {
|
||||
import_backup_stream(context, backup_file, passphrase).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Imports backup by reading a tar file from a stream.
|
||||
///
|
||||
/// `file_size` is used to calculate the progress
|
||||
/// and emit progress events.
|
||||
/// Ideally it is the sum of the entry
|
||||
/// sizes without the header overhead,
|
||||
/// but can be estimated as tar file size
|
||||
/// in which case the progress is underestimated
|
||||
/// and may not reach 99.9% by the end of import.
|
||||
/// Underestimating is better than
|
||||
/// overestimating because the progress
|
||||
/// jumps to 100% instead of getting stuck at 99.9%
|
||||
/// for some time.
|
||||
pub(crate) async fn import_backup_stream<R: tokio::io::AsyncRead + Unpin>(
|
||||
context: &Context,
|
||||
backup_file: R,
|
||||
file_size: u64,
|
||||
passphrase: String,
|
||||
) -> Result<()> {
|
||||
import_backup_stream_inner(context, backup_file, file_size, passphrase)
|
||||
import_backup_stream_inner(context, backup_file, passphrase)
|
||||
.await
|
||||
.0
|
||||
}
|
||||
@@ -319,6 +313,19 @@ struct ProgressReader<R> {
|
||||
}
|
||||
|
||||
impl<R> ProgressReader<R> {
|
||||
/// Creates a new `ProgressReader`.
|
||||
///
|
||||
/// `file_size` is used to calculate the progress
|
||||
/// and emit progress events.
|
||||
/// Ideally it is the sum of the entry
|
||||
/// sizes without the header overhead,
|
||||
/// but can be estimated as tar file size
|
||||
/// in which case the progress is underestimated
|
||||
/// and may not reach 99.9% by the end of import.
|
||||
/// Underestimating is better than
|
||||
/// overestimating because the progress
|
||||
/// jumps to 100% instead of getting stuck at 99.9%
|
||||
/// for some time.
|
||||
fn new(r: R, context: Context, file_size: u64) -> Self {
|
||||
Self {
|
||||
inner: r,
|
||||
@@ -358,10 +365,8 @@ where
|
||||
async fn import_backup_stream_inner<R: tokio::io::AsyncRead + Unpin>(
|
||||
context: &Context,
|
||||
backup_file: R,
|
||||
file_size: u64,
|
||||
passphrase: String,
|
||||
) -> (Result<()>,) {
|
||||
let backup_file = ProgressReader::new(backup_file, context.clone(), file_size);
|
||||
let mut archive = Archive::new(backup_file);
|
||||
|
||||
let mut entries = match archive.entries() {
|
||||
@@ -461,10 +466,10 @@ fn get_next_backup_path(
|
||||
tempdbfile.push(format!("{stem}-{i:02}-{addr}.db"));
|
||||
|
||||
let mut tempfile = folder.clone();
|
||||
tempfile.push(format!("{stem}-{i:02}-{addr}.tar.part"));
|
||||
tempfile.push(format!("{stem}-{i:02}-{addr}.tar.gz.part"));
|
||||
|
||||
let mut destfile = folder.clone();
|
||||
destfile.push(format!("{stem}-{i:02}-{addr}.tar"));
|
||||
destfile.push(format!("{stem}-{i:02}-{addr}.tar.gz"));
|
||||
|
||||
if !tempdbfile.exists() && !tempfile.exists() && !destfile.exists() {
|
||||
return Ok((tempdbfile, tempfile, destfile));
|
||||
@@ -504,9 +509,13 @@ async fn export_backup(context: &Context, dir: &Path, passphrase: String) -> Res
|
||||
file_size += blob.to_abs_path().metadata()?.len()
|
||||
}
|
||||
|
||||
export_backup_stream(context, &temp_db_path, blobdir, file, file_size)
|
||||
.await
|
||||
.context("Exporting backup to file failed")?;
|
||||
let gzip_encoder = async_compression::tokio::write::GzipEncoder::new(file);
|
||||
let mut gzip_encoder =
|
||||
export_backup_stream(context, &temp_db_path, blobdir, gzip_encoder, file_size)
|
||||
.await
|
||||
.context("Exporting backup to file failed")?;
|
||||
gzip_encoder.shutdown().await?;
|
||||
|
||||
fs::rename(temp_path, &dest_path).await?;
|
||||
context.emit_event(EventType::ImexFileWritten(dest_path));
|
||||
Ok(())
|
||||
@@ -543,6 +552,10 @@ impl<W> ProgressWriter<W> {
|
||||
context,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_inner(self) -> W {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> AsyncWrite for ProgressWriter<W>
|
||||
@@ -590,12 +603,12 @@ pub(crate) async fn export_backup_stream<'a, W>(
|
||||
blobdir: BlobDirContents<'a>,
|
||||
writer: W,
|
||||
file_size: u64,
|
||||
) -> Result<()>
|
||||
) -> Result<W>
|
||||
where
|
||||
W: tokio::io::AsyncWrite + tokio::io::AsyncWriteExt + Unpin + Send + 'static,
|
||||
{
|
||||
let writer = ProgressWriter::new(writer, context.clone(), file_size);
|
||||
let mut builder = tokio_tar::Builder::new(writer);
|
||||
let progress_writer = ProgressWriter::new(writer, context.clone(), file_size);
|
||||
let mut builder = tokio_tar::Builder::new(progress_writer);
|
||||
|
||||
builder
|
||||
.append_path_with_name(temp_db_path, DBFILE_BACKUP_NAME)
|
||||
@@ -607,8 +620,9 @@ where
|
||||
builder.append_file(path_in_archive, &mut file).await?;
|
||||
}
|
||||
|
||||
builder.finish().await?;
|
||||
Ok(())
|
||||
// Convert tar builder back into the underlying stream.
|
||||
let progress_writer = builder.into_inner().await?;
|
||||
Ok(progress_writer.into_inner())
|
||||
}
|
||||
|
||||
/// Imports secret key from a file.
|
||||
|
||||
@@ -36,12 +36,13 @@ use futures_lite::FutureExt;
|
||||
use iroh_net::relay::RelayMode;
|
||||
use iroh_net::Endpoint;
|
||||
use tokio::fs;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::chat::add_device_msg;
|
||||
use crate::context::Context;
|
||||
use crate::imex::BlobDirContents;
|
||||
use crate::imex::{BlobDirContents, ProgressReader};
|
||||
use crate::message::{Message, Viewtype};
|
||||
use crate::qr::Qr;
|
||||
use crate::stock_str::backup_transfer_msg_body;
|
||||
@@ -190,9 +191,11 @@ impl BackupProvider {
|
||||
|
||||
send_stream.write_all(&file_size.to_be_bytes()).await?;
|
||||
|
||||
export_backup_stream(&context, &dbfile, blobdir, send_stream, file_size)
|
||||
.await
|
||||
.context("Failed to write backup into QUIC stream")?;
|
||||
let mut send_stream =
|
||||
export_backup_stream(&context, &dbfile, blobdir, send_stream, file_size)
|
||||
.await
|
||||
.context("Failed to write backup into QUIC stream")?;
|
||||
send_stream.shutdown().await?;
|
||||
info!(context, "Finished writing backup into QUIC stream.");
|
||||
let mut buf = [0u8; 1];
|
||||
info!(context, "Waiting for acknowledgment.");
|
||||
@@ -310,7 +313,8 @@ pub async fn get_backup2(
|
||||
let mut file_size_buf = [0u8; 8];
|
||||
recv_stream.read_exact(&mut file_size_buf).await?;
|
||||
let file_size = u64::from_be_bytes(file_size_buf);
|
||||
import_backup_stream(context, recv_stream, file_size, passphrase)
|
||||
let recv_stream = ProgressReader::new(recv_stream, context.clone(), file_size);
|
||||
import_backup_stream(context, recv_stream, passphrase)
|
||||
.await
|
||||
.context("Failed to import backup from QUIC stream")?;
|
||||
info!(context, "Finished importing backup from the stream.");
|
||||
|
||||
@@ -12,13 +12,14 @@ use fast_socks5::client::Socks5Stream;
|
||||
use fast_socks5::util::target_addr::ToTargetAddr;
|
||||
use fast_socks5::AuthenticationMethod;
|
||||
use fast_socks5::Socks5Command;
|
||||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||
use percent_encoding::{percent_encode, utf8_percent_encode, NON_ALPHANUMERIC};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_io_timeout::TimeoutStream;
|
||||
use url::Url;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::constants::NON_ALPHANUMERIC_WITHOUT_DOT;
|
||||
use crate::context::Context;
|
||||
use crate::net::connect_tcp;
|
||||
use crate::net::session::SessionStream;
|
||||
@@ -41,6 +42,12 @@ impl PartialEq for ShadowsocksConfig {
|
||||
|
||||
impl Eq for ShadowsocksConfig {}
|
||||
|
||||
impl ShadowsocksConfig {
|
||||
fn to_url(&self) -> String {
|
||||
self.server_config.to_url()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct HttpConfig {
|
||||
/// HTTP proxy host.
|
||||
@@ -84,6 +91,17 @@ impl HttpConfig {
|
||||
};
|
||||
Ok(http_config)
|
||||
}
|
||||
|
||||
fn to_url(&self, scheme: &str) -> String {
|
||||
let host = utf8_percent_encode(&self.host, NON_ALPHANUMERIC_WITHOUT_DOT);
|
||||
if let Some((user, password)) = &self.user_password {
|
||||
let user = utf8_percent_encode(user, NON_ALPHANUMERIC);
|
||||
let password = utf8_percent_encode(password, NON_ALPHANUMERIC);
|
||||
format!("{scheme}://{user}:{password}@{host}:{}", self.port)
|
||||
} else {
|
||||
format!("{scheme}://{host}:{}", self.port)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@@ -123,6 +141,17 @@ impl Socks5Config {
|
||||
|
||||
Ok(socks_stream)
|
||||
}
|
||||
|
||||
fn to_url(&self) -> String {
|
||||
let host = utf8_percent_encode(&self.host, NON_ALPHANUMERIC_WITHOUT_DOT);
|
||||
if let Some((user, password)) = &self.user_password {
|
||||
let user = utf8_percent_encode(user, NON_ALPHANUMERIC);
|
||||
let password = utf8_percent_encode(password, NON_ALPHANUMERIC);
|
||||
format!("socks5://{user}:{password}@{host}:{}", self.port)
|
||||
} else {
|
||||
format!("socks5://{host}:{}", self.port)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@@ -217,7 +246,7 @@ where
|
||||
|
||||
impl ProxyConfig {
|
||||
/// Creates a new proxy configuration by parsing given proxy URL.
|
||||
fn from_url(url: &str) -> Result<Self> {
|
||||
pub(crate) fn from_url(url: &str) -> Result<Self> {
|
||||
let url = Url::parse(url).context("Cannot parse proxy URL")?;
|
||||
match url.scheme() {
|
||||
"http" => {
|
||||
@@ -272,6 +301,19 @@ impl ProxyConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes proxy config into an URL.
|
||||
///
|
||||
/// This function can be used to normalize proxy URL
|
||||
/// by parsing it and serializing back.
|
||||
pub(crate) fn to_url(&self) -> String {
|
||||
match self {
|
||||
Self::Http(http_config) => http_config.to_url("http"),
|
||||
Self::Https(http_config) => http_config.to_url("https"),
|
||||
Self::Socks5(socks5_config) => socks5_config.to_url(),
|
||||
Self::Shadowsocks(shadowsocks_config) => shadowsocks_config.to_url(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Migrates legacy `socks5_host`, `socks5_port`, `socks5_user` and `socks5_password`
|
||||
/// config into `proxy_url` if `proxy_url` is unset or empty.
|
||||
///
|
||||
|
||||
@@ -143,9 +143,10 @@ impl Iroh {
|
||||
self.endpoint.add_node_addr(peer.clone())?;
|
||||
}
|
||||
|
||||
self.gossip
|
||||
.join(topic, peers.into_iter().map(|peer| peer.node_id).collect())
|
||||
.await?;
|
||||
self.gossip.join_with_opts(
|
||||
topic,
|
||||
JoinOptions::with_bootstrap(peers.into_iter().map(|peer| peer.node_id)),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
17
src/qr.rs
17
src/qr.rs
@@ -20,7 +20,7 @@ use crate::events::EventType;
|
||||
use crate::key::Fingerprint;
|
||||
use crate::message::Message;
|
||||
use crate::net::http::post_empty;
|
||||
use crate::net::proxy::DEFAULT_SOCKS_PORT;
|
||||
use crate::net::proxy::{ProxyConfig, DEFAULT_SOCKS_PORT};
|
||||
use crate::peerstate::Peerstate;
|
||||
use crate::token;
|
||||
use crate::tools::validate_id;
|
||||
@@ -723,6 +723,10 @@ pub async fn set_config_from_qr(context: &Context, qr: &str) -> Result<()> {
|
||||
.get_config(Config::ProxyUrl)
|
||||
.await?
|
||||
.unwrap_or_default();
|
||||
|
||||
// Normalize the URL.
|
||||
let url = ProxyConfig::from_url(&url)?.to_url();
|
||||
|
||||
let proxy_urls: Vec<&str> = std::iter::once(url.as_str())
|
||||
.chain(
|
||||
old_proxy_url_value
|
||||
@@ -1787,6 +1791,17 @@ mod tests {
|
||||
)
|
||||
);
|
||||
|
||||
// SOCKS5 config does not have port 1080 explicitly specified,
|
||||
// but should bring `socks5://1.2.3.4:1080` to the top instead of creating another entry.
|
||||
set_config_from_qr(&t, "socks5://1.2.3.4").await?;
|
||||
assert_eq!(
|
||||
t.get_config(Config::ProxyUrl).await?,
|
||||
Some(
|
||||
"socks5://1.2.3.4:1080\nss://YWVzLTEyOC1nY206dGVzdA@192.168.100.1:8888#Example1\nsocks5://foo:666\nsocks5://Da:x%26%25%24X@jau:1080"
|
||||
.to_string()
|
||||
)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
//! Implementation of [SecureJoin protocols](https://securejoin.delta.chat/).
|
||||
|
||||
use anyhow::{ensure, Context as _, Error, Result};
|
||||
use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC};
|
||||
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||
|
||||
use crate::aheader::EncryptPreference;
|
||||
use crate::chat::{self, get_chat_id_by_grpid, Chat, ChatId, ChatIdBlocked, ProtectionStatus};
|
||||
use crate::chatlist_events;
|
||||
use crate::config::Config;
|
||||
use crate::constants::{Blocked, Chattype};
|
||||
use crate::constants::{Blocked, Chattype, NON_ALPHANUMERIC_WITHOUT_DOT};
|
||||
use crate::contact::{Contact, ContactId, Origin};
|
||||
use crate::context::Context;
|
||||
use crate::e2ee::ensure_secret_key_exists;
|
||||
@@ -34,9 +34,6 @@ 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'.');
|
||||
|
||||
fn inviter_progress(context: &Context, contact_id: ContactId, progress: usize) {
|
||||
debug_assert!(
|
||||
progress <= 1000,
|
||||
|
||||
Reference in New Issue
Block a user