mirror of
https://github.com/chatmail/core.git
synced 2026-06-15 20:26:30 +03:00
Compare commits
19 Commits
iequidoo/d
...
link2xt/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81df15859c | ||
|
|
fbc21f3bc6 | ||
|
|
34aebe217e | ||
|
|
801909e0fe | ||
|
|
3d704a7025 | ||
|
|
3fdd01a487 | ||
|
|
b79124db11 | ||
|
|
0b6c9db11b | ||
|
|
a4dbbb0da1 | ||
|
|
393b6b8e08 | ||
|
|
7bb956a608 | ||
|
|
414630fa61 | ||
|
|
210b9d86f8 | ||
|
|
c2cd303a28 | ||
|
|
609b0cd828 | ||
|
|
f1861be0ba | ||
|
|
c5061aabfc | ||
|
|
eb171d6a08 | ||
|
|
1e3d4381e0 |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -62,7 +62,7 @@ jobs:
|
||||
with:
|
||||
show-progress: false
|
||||
persist-credentials: false
|
||||
- uses: EmbarkStudios/cargo-deny-action@a531616d8ce3b9177443e48a1159bc945a099823
|
||||
- uses: EmbarkStudios/cargo-deny-action@6c8f9facfa5047ec02d8485b6bf52b587b7777d1
|
||||
with:
|
||||
arguments: --workspace --all-features --locked
|
||||
command: check
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
cache-bin: false
|
||||
|
||||
- name: Install nextest
|
||||
uses: taiki-e/install-action@60ae4ce63c7aeb6e96d7f572c1ec7fafbb17ca80
|
||||
uses: taiki-e/install-action@213ccc1a076163c093f914550b94feb90fab916d
|
||||
with:
|
||||
tool: nextest
|
||||
|
||||
|
||||
12
.github/workflows/nix.yml
vendored
12
.github/workflows/nix.yml
vendored
@@ -73,10 +73,9 @@ jobs:
|
||||
- libdeltachat
|
||||
- python-docs
|
||||
|
||||
# Fails to build
|
||||
#- deltachat-repl-x86_64-android
|
||||
- deltachat-repl-x86_64-android
|
||||
- deltachat-rpc-server-x86_64-android
|
||||
#- deltachat-repl-x86-android
|
||||
#- deltachat-rpc-server-x86_64-android
|
||||
#- deltachat-rpc-server-x86-android
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -84,6 +83,7 @@ jobs:
|
||||
show-progress: false
|
||||
persist-credentials: false
|
||||
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13
|
||||
- run: nix build .#${{ matrix.installable }}
|
||||
|
||||
build-macos:
|
||||
@@ -95,14 +95,12 @@ jobs:
|
||||
installable:
|
||||
- deltachat-rpc-server
|
||||
- deltachat-rpc-server-x86_64-darwin
|
||||
|
||||
# Fails to build
|
||||
# because of <https://github.com/NixOS/nixpkgs/issues/413910>.
|
||||
# - deltachat-rpc-server-aarch64-darwin
|
||||
- deltachat-rpc-server-aarch64-darwin
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
show-progress: false
|
||||
persist-credentials: false
|
||||
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13
|
||||
- run: nix build .#${{ matrix.installable }}
|
||||
|
||||
40
CHANGELOG.md
40
CHANGELOG.md
@@ -1,44 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## [2.51.0] - 2026-05-29
|
||||
|
||||
### Features / Changes
|
||||
|
||||
- Follow certificate check parameter in autoconfig.
|
||||
- Immediately remove all encrypted messages from the server in single-device mode.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix syntax error in `only_fetch_mvbox` migration 150 resulting in failure to upgrade for `only_fetch_mvbox` users.
|
||||
- Do not try to resolve proxy IPv6 addresses in square brackets.
|
||||
- Do not fail to receive post-message with status updates for deleted webxdc.
|
||||
- Don't make message `OutDelivered` after successful resending to new broadcast member.
|
||||
|
||||
### Build system
|
||||
|
||||
- nix: fix downloads from crates.io in nix builds.
|
||||
|
||||
### Documentation
|
||||
|
||||
- Fix reference in `delete_expired_imap_messages` comment.
|
||||
|
||||
### Refactor
|
||||
|
||||
- Remove `pre_encrypt_mime_hook`.
|
||||
- Make `should_delete_all_downloaded_messages` non-async.
|
||||
|
||||
### Tests
|
||||
|
||||
- Test IPv6 addresses in HTTP(S) proxies.
|
||||
- Test `bcc_self` in `test_delete_expired_imap_messages`.
|
||||
- Test encrypted messages in `test_delete_expired_imap_messages`.
|
||||
|
||||
### Miscellaneous Tasks
|
||||
|
||||
- Bump version to 2.51.0-dev.
|
||||
- deps: bump zizmorcore/zizmor-action from 0.5.3 to 0.5.6.
|
||||
- deps: bump taiki-e/install-action from 2.78.1 to 2.79.2.
|
||||
|
||||
## [2.50.0] - 2026-05-22
|
||||
|
||||
### API-Changes
|
||||
@@ -8296,4 +8257,3 @@ https://github.com/chatmail/core/pulls?q=is%3Apr+is%3Aclosed
|
||||
[2.48.0]: https://github.com/chatmail/core/compare/v2.47.0..v2.48.0
|
||||
[2.49.0]: https://github.com/chatmail/core/compare/v2.48.0..v2.49.0
|
||||
[2.50.0]: https://github.com/chatmail/core/compare/v2.49.0..v2.50.0
|
||||
[2.51.0]: https://github.com/chatmail/core/compare/v2.50.0..v2.51.0
|
||||
|
||||
102
Cargo.lock
generated
102
Cargo.lock
generated
@@ -391,28 +391,6 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00"
|
||||
dependencies = [
|
||||
"aws-lc-sys",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
"dunce",
|
||||
"fs_extra",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backon"
|
||||
version = "1.5.0"
|
||||
@@ -785,13 +763,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.63"
|
||||
version = "1.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
|
||||
checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
@@ -945,15 +920,6 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cobs"
|
||||
version = "0.2.3"
|
||||
@@ -1710,7 +1676,7 @@ dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1760,12 +1726,6 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.18"
|
||||
@@ -2091,12 +2051,6 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.5.7"
|
||||
@@ -2154,12 +2108,6 @@ dependencies = [
|
||||
name = "format-flowed"
|
||||
version = "1.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "fs_extra"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
@@ -2733,7 +2681,7 @@ dependencies = [
|
||||
"hyper",
|
||||
"libc",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.9",
|
||||
"socket2 0.6.3",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@@ -3286,16 +3234,6 @@ version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
@@ -3436,9 +3374,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.31"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
@@ -3880,7 +3818,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4365,18 +4303,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.13"
|
||||
version = "1.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924"
|
||||
checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.1.13"
|
||||
version = "1.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b"
|
||||
checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -5281,7 +5219,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.12.1",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5290,7 +5228,6 @@ version = "0.23.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
@@ -5336,7 +5273,6 @@ version = "0.103.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
@@ -5581,9 +5517,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.150"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -5759,9 +5695,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "2.0.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
@@ -6147,7 +6083,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.1.4",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6295,9 +6231,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.52.3"
|
||||
version = "1.52.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
|
||||
checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
|
||||
@@ -101,7 +101,7 @@ tagger = "4.3.4"
|
||||
textwrap = "0.16.2"
|
||||
thiserror = { workspace = true }
|
||||
tokio-io-timeout = "1.2.1"
|
||||
tokio-rustls = { version = "0.26.2", default-features = false, features = ["aws-lc-rs", "tls12"] }
|
||||
tokio-rustls = { version = "0.26.2", default-features = false }
|
||||
tokio-stream = { version = "0.1.17", features = ["fs"] }
|
||||
astral-tokio-tar = { version = "0.6.2", default-features = false }
|
||||
tokio-util = { workspace = true }
|
||||
|
||||
@@ -1106,6 +1106,9 @@ impl CommandApi {
|
||||
/// because the word "channel" already appears a lot in the code,
|
||||
/// which would make it hard to grep for it.
|
||||
///
|
||||
/// After creation, the chat contains no recipients and is in _unpromoted_ state;
|
||||
/// see [`CommandApi::create_group_chat`] for more information on the unpromoted state.
|
||||
///
|
||||
/// Returns the created chat's id.
|
||||
async fn create_broadcast(&self, account_id: u32, chat_name: String) -> Result<u32> {
|
||||
let ctx = self.get_context(account_id).await?;
|
||||
|
||||
@@ -340,6 +340,9 @@ class Account:
|
||||
because the word "channel" already appears a lot in the code,
|
||||
which would make it hard to grep for it.
|
||||
|
||||
After creation, the chat contains no recipients and is in _unpromoted_ state;
|
||||
see `create_group()` for more information on the unpromoted state.
|
||||
|
||||
Returns the created chat.
|
||||
"""
|
||||
return Chat(self, self._rpc.create_broadcast(self.id, name))
|
||||
|
||||
484
flake.nix
484
flake.nix
@@ -29,11 +29,7 @@
|
||||
rustc = fenixToolchain;
|
||||
};
|
||||
manifest = (pkgs.lib.importTOML ./Cargo.toml).package;
|
||||
androidSdk = android.sdk.${system} (sdkPkgs:
|
||||
builtins.attrValues {
|
||||
inherit (sdkPkgs) ndk-27-2-12479018 cmdline-tools-latest;
|
||||
});
|
||||
androidNdkRoot = "${androidSdk}/share/android-sdk/ndk/27.2.12479018";
|
||||
version = manifest.version;
|
||||
|
||||
rustSrc = nix-filter.lib {
|
||||
root = ./.;
|
||||
@@ -66,37 +62,15 @@
|
||||
];
|
||||
};
|
||||
|
||||
# Map from architecture name to rust targets and nixpkgs targets.
|
||||
# Map from architecture name to nixpkgs targets.
|
||||
arch2targets = {
|
||||
"x86_64-linux" = {
|
||||
rustTarget = "x86_64-unknown-linux-musl";
|
||||
crossTarget = "x86_64-unknown-linux-musl";
|
||||
};
|
||||
"armv7l-linux" = {
|
||||
rustTarget = "armv7-unknown-linux-musleabihf";
|
||||
crossTarget = "armv7l-unknown-linux-musleabihf";
|
||||
};
|
||||
"armv6l-linux" = {
|
||||
rustTarget = "arm-unknown-linux-musleabihf";
|
||||
crossTarget = "armv6l-unknown-linux-musleabihf";
|
||||
};
|
||||
"aarch64-linux" = {
|
||||
rustTarget = "aarch64-unknown-linux-musl";
|
||||
crossTarget = "aarch64-unknown-linux-musl";
|
||||
};
|
||||
"i686-linux" = {
|
||||
rustTarget = "i686-unknown-linux-musl";
|
||||
crossTarget = "i686-unknown-linux-musl";
|
||||
};
|
||||
|
||||
"x86_64-darwin" = {
|
||||
rustTarget = "x86_64-apple-darwin";
|
||||
crossTarget = "x86_64-darwin";
|
||||
};
|
||||
"aarch64-darwin" = {
|
||||
rustTarget = "aarch64-apple-darwin";
|
||||
crossTarget = "aarch64-darwin";
|
||||
};
|
||||
"x86_64-linux" = "x86_64-unknown-linux-musl";
|
||||
"armv7l-linux" = "armv7l-unknown-linux-musleabihf";
|
||||
"armv6l-linux" = "armv6l-unknown-linux-musleabihf";
|
||||
"aarch64-linux" = "aarch64-unknown-linux-musl";
|
||||
"i686-linux" = "i686-unknown-linux-musl";
|
||||
"x86_64-darwin" = "x86_64-darwin";
|
||||
"aarch64-darwin" = "aarch64-darwin";
|
||||
};
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
@@ -105,7 +79,7 @@
|
||||
naersk'.buildPackage {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
version = manifest.version;
|
||||
inherit version;
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
@@ -113,222 +87,21 @@
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
};
|
||||
pkgsWin64 = pkgs.pkgsCross.mingwW64;
|
||||
mkWin64RustPackage = packageName:
|
||||
let
|
||||
rustTarget = "x86_64-pc-windows-gnu";
|
||||
toolchainWin = fenixPkgs.combine [
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
fenixPkgs.targets.${rustTarget}.stable.rust-std
|
||||
];
|
||||
naerskWin = pkgs.callPackage naersk {
|
||||
cargo = toolchainWin;
|
||||
rustc = toolchainWin;
|
||||
};
|
||||
in
|
||||
naerskWin.buildPackage rec {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
version = manifest.version;
|
||||
strictDeps = true;
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
];
|
||||
depsBuildBuild = [
|
||||
pkgsWin64.stdenv.cc
|
||||
];
|
||||
buildInputs = [
|
||||
pkgsWin64.windows.pthreads
|
||||
];
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
|
||||
CARGO_BUILD_TARGET = rustTarget;
|
||||
TARGET_CC = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc";
|
||||
CARGO_BUILD_RUSTFLAGS = [
|
||||
"-C"
|
||||
"linker=${TARGET_CC}"
|
||||
"-L"
|
||||
"native=${pkgsWin64.windows.pthreads}/lib"
|
||||
];
|
||||
|
||||
CC = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc";
|
||||
LD = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc";
|
||||
};
|
||||
|
||||
pkgsWin32 = pkgs.pkgsCross.mingw32;
|
||||
mkWin32RustPackage = packageName:
|
||||
let
|
||||
rustTarget = "i686-pc-windows-gnu";
|
||||
in
|
||||
let
|
||||
toolchainWin = fenixPkgs.combine [
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
fenixPkgs.targets.${rustTarget}.stable.rust-std
|
||||
];
|
||||
naerskWin = pkgs.callPackage naersk {
|
||||
cargo = toolchainWin;
|
||||
rustc = toolchainWin;
|
||||
};
|
||||
|
||||
# Get rid of MCF Gthread library.
|
||||
# See <https://github.com/NixOS/nixpkgs/issues/156343>
|
||||
# and <https://discourse.nixos.org/t/statically-linked-mingw-binaries/38395>
|
||||
# for details.
|
||||
#
|
||||
# Use DWARF-2 instead of SJLJ for exception handling.
|
||||
winCC = pkgsWin32.buildPackages.wrapCC (
|
||||
(pkgsWin32.buildPackages.gcc-unwrapped.override
|
||||
({
|
||||
threadsCross = {
|
||||
model = "win32";
|
||||
package = null;
|
||||
};
|
||||
})).overrideAttrs (oldAttr: {
|
||||
configureFlags = oldAttr.configureFlags ++ [
|
||||
"--disable-sjlj-exceptions"
|
||||
"--with-dwarf2"
|
||||
];
|
||||
})
|
||||
);
|
||||
in
|
||||
naerskWin.buildPackage rec {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
version = manifest.version;
|
||||
strictDeps = true;
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
];
|
||||
depsBuildBuild = [
|
||||
winCC
|
||||
];
|
||||
buildInputs = [
|
||||
pkgsWin32.windows.pthreads
|
||||
];
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
|
||||
CARGO_BUILD_TARGET = rustTarget;
|
||||
TARGET_CC = "${winCC}/bin/${winCC.targetPrefix}cc";
|
||||
CARGO_BUILD_RUSTFLAGS = [
|
||||
"-C"
|
||||
"linker=${TARGET_CC}"
|
||||
"-L"
|
||||
"native=${pkgsWin32.windows.pthreads}/lib"
|
||||
];
|
||||
|
||||
CC = "${winCC}/bin/${winCC.targetPrefix}cc";
|
||||
LD = "${winCC}/bin/${winCC.targetPrefix}cc";
|
||||
};
|
||||
|
||||
mkCrossRustPackage = arch: packageName:
|
||||
let
|
||||
rustTarget = arch2targets."${arch}".rustTarget;
|
||||
crossTarget = arch2targets."${arch}".crossTarget;
|
||||
pkgsCross = import nixpkgs {
|
||||
system = system;
|
||||
crossSystem.config = crossTarget;
|
||||
};
|
||||
in
|
||||
let
|
||||
toolchain = fenixPkgs.combine [
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
fenixPkgs.targets.${rustTarget}.stable.rust-std
|
||||
];
|
||||
naersk-lib = pkgs.callPackage naersk {
|
||||
cargo = toolchain;
|
||||
rustc = toolchain;
|
||||
};
|
||||
in
|
||||
naersk-lib.buildPackage rec {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
version = manifest.version;
|
||||
strictDeps = true;
|
||||
src = rustSrc;
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
];
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
|
||||
CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS = "-Clink-args=-L${pkgsCross.libiconv}/lib";
|
||||
CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS = "-Clink-args=-L${pkgsCross.libiconv}/lib";
|
||||
|
||||
CARGO_BUILD_TARGET = rustTarget;
|
||||
TARGET_CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc";
|
||||
CARGO_BUILD_RUSTFLAGS = [
|
||||
"-C"
|
||||
"linker=${TARGET_CC}"
|
||||
];
|
||||
|
||||
CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc";
|
||||
LD = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc";
|
||||
};
|
||||
|
||||
androidAttrs = {
|
||||
armeabi-v7a = {
|
||||
cc = "armv7a-linux-androideabi21-clang";
|
||||
rustTarget = "armv7-linux-androideabi";
|
||||
};
|
||||
arm64-v8a = {
|
||||
cc = "aarch64-linux-android21-clang";
|
||||
rustTarget = "aarch64-linux-android";
|
||||
};
|
||||
x86 = {
|
||||
cc = "i686-linux-android21-clang";
|
||||
rustTarget = "i686-linux-android";
|
||||
};
|
||||
x86_64 = {
|
||||
cc = "x86_64-linux-android21-clang";
|
||||
rustTarget = "x86_64-linux-android";
|
||||
};
|
||||
mkWin64RustPackage = pkgs.callPackage ./nix/win64-package.nix {
|
||||
inherit naersk system fenixPkgs version;
|
||||
};
|
||||
|
||||
mkAndroidRustPackage = arch: packageName:
|
||||
let
|
||||
rustTarget = androidAttrs.${arch}.rustTarget;
|
||||
toolchain = fenixPkgs.combine [
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
fenixPkgs.targets.${rustTarget}.stable.rust-std
|
||||
];
|
||||
naersk-lib = pkgs.callPackage naersk {
|
||||
cargo = toolchain;
|
||||
rustc = toolchain;
|
||||
};
|
||||
targetToolchain = "${androidNdkRoot}/toolchains/llvm/prebuilt/linux-x86_64";
|
||||
targetCcName = androidAttrs.${arch}.cc;
|
||||
targetCc = "${targetToolchain}/bin/${targetCcName}";
|
||||
in
|
||||
naersk-lib.buildPackage rec {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
version = manifest.version;
|
||||
strictDeps = true;
|
||||
src = rustSrc;
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
];
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
mkWin32RustPackage = pkgs.callPackage ./nix/win32-package.nix {
|
||||
inherit naersk system fenixPkgs version;
|
||||
};
|
||||
|
||||
CARGO_BUILD_TARGET = rustTarget;
|
||||
TARGET_CC = "${targetCc}";
|
||||
CARGO_BUILD_RUSTFLAGS = [
|
||||
"-C"
|
||||
"linker=${TARGET_CC}"
|
||||
];
|
||||
mkCrossRustPackage = pkgs.callPackage ./nix/cross-rust-package.nix {
|
||||
inherit nixpkgs arch2targets naersk fenixPkgs system rustSrc version;
|
||||
};
|
||||
|
||||
CC = "${targetCc}";
|
||||
LD = "${targetCc}";
|
||||
};
|
||||
mkAndroidRustPackage = pkgs.callPackage ./nix/android-package.nix {
|
||||
inherit naersk fenixPkgs system rustSrc android version;
|
||||
};
|
||||
|
||||
mkAndroidPackages = arch:
|
||||
let
|
||||
@@ -338,32 +111,7 @@
|
||||
"deltachat-rpc-server-${arch}-android" = rpc-server;
|
||||
"deltachat-repl-${arch}-android" = mkAndroidRustPackage arch "deltachat-repl";
|
||||
"deltachat-rpc-server-${arch}-android-wheel" =
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "deltachat-rpc-server-${arch}-android-wheel";
|
||||
version = manifest.version;
|
||||
src = nix-filter.lib {
|
||||
root = ./.;
|
||||
include = [
|
||||
"scripts/wheel-rpc-server.py"
|
||||
"deltachat-rpc-server/README.md"
|
||||
"LICENSE"
|
||||
"Cargo.toml"
|
||||
];
|
||||
};
|
||||
nativeBuildInputs = [
|
||||
pkgs.python3
|
||||
pkgs.python3Packages.wheel
|
||||
];
|
||||
buildInputs = [
|
||||
rpc-server
|
||||
];
|
||||
buildPhase = ''
|
||||
mkdir tmp
|
||||
cp ${rpc-server}/bin/deltachat-rpc-server tmp/deltachat-rpc-server
|
||||
python3 scripts/wheel-rpc-server.py ${arch}-android tmp/deltachat-rpc-server
|
||||
'';
|
||||
installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out'';
|
||||
};
|
||||
mkWheel { inherit rpc-server; arch = "${arch}-android"; };
|
||||
};
|
||||
|
||||
mkRustPackages = arch:
|
||||
@@ -373,34 +121,10 @@
|
||||
{
|
||||
"deltachat-repl-${arch}" = mkCrossRustPackage arch "deltachat-repl";
|
||||
"deltachat-rpc-server-${arch}" = rpc-server;
|
||||
"deltachat-rpc-server-${arch}-wheel" =
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "deltachat-rpc-server-${arch}-wheel";
|
||||
version = manifest.version;
|
||||
src = nix-filter.lib {
|
||||
root = ./.;
|
||||
include = [
|
||||
"scripts/wheel-rpc-server.py"
|
||||
"deltachat-rpc-server/README.md"
|
||||
"LICENSE"
|
||||
"Cargo.toml"
|
||||
];
|
||||
};
|
||||
nativeBuildInputs = [
|
||||
pkgs.python3
|
||||
pkgs.python3Packages.wheel
|
||||
];
|
||||
buildInputs = [
|
||||
rpc-server
|
||||
];
|
||||
buildPhase = ''
|
||||
mkdir tmp
|
||||
cp ${rpc-server}/bin/deltachat-rpc-server tmp/deltachat-rpc-server
|
||||
python3 scripts/wheel-rpc-server.py ${arch} tmp/deltachat-rpc-server
|
||||
'';
|
||||
installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out'';
|
||||
};
|
||||
"deltachat-rpc-server-${arch}-wheel" = mkWheel { inherit rpc-server; arch = "${arch}"; };
|
||||
};
|
||||
|
||||
mkWheel = pkgs.callPackage ./nix/wheel.nix { inherit nix-filter version; root = ./.; };
|
||||
in
|
||||
{
|
||||
formatter = pkgs.nixpkgs-fmt;
|
||||
@@ -424,116 +148,29 @@
|
||||
deltachat-repl-win64 = mkWin64RustPackage "deltachat-repl";
|
||||
deltachat-rpc-server-win64 = mkWin64RustPackage "deltachat-rpc-server";
|
||||
deltachat-rpc-server-win64-wheel =
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "deltachat-rpc-server-win64-wheel";
|
||||
version = manifest.version;
|
||||
src = nix-filter.lib {
|
||||
root = ./.;
|
||||
include = [
|
||||
"scripts/wheel-rpc-server.py"
|
||||
"deltachat-rpc-server/README.md"
|
||||
"LICENSE"
|
||||
"Cargo.toml"
|
||||
];
|
||||
};
|
||||
nativeBuildInputs = [
|
||||
pkgs.python3
|
||||
pkgs.python3Packages.wheel
|
||||
];
|
||||
buildInputs = [
|
||||
deltachat-rpc-server-win64
|
||||
];
|
||||
buildPhase = ''
|
||||
mkdir tmp
|
||||
cp ${deltachat-rpc-server-win64}/bin/deltachat-rpc-server.exe tmp/deltachat-rpc-server.exe
|
||||
python3 scripts/wheel-rpc-server.py win64 tmp/deltachat-rpc-server.exe
|
||||
'';
|
||||
installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out'';
|
||||
};
|
||||
mkWheel { rpc-server = deltachat-rpc-server-win64; arch = "win64"; binaryName = "deltachat-rpc-server.exe"; };
|
||||
|
||||
deltachat-repl-win32 = mkWin32RustPackage "deltachat-repl";
|
||||
deltachat-rpc-server-win32 = mkWin32RustPackage "deltachat-rpc-server";
|
||||
deltachat-rpc-server-win32-wheel =
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "deltachat-rpc-server-win32-wheel";
|
||||
version = manifest.version;
|
||||
src = nix-filter.lib {
|
||||
root = ./.;
|
||||
include = [
|
||||
"scripts/wheel-rpc-server.py"
|
||||
"deltachat-rpc-server/README.md"
|
||||
"LICENSE"
|
||||
"Cargo.toml"
|
||||
];
|
||||
};
|
||||
nativeBuildInputs = [
|
||||
pkgs.python3
|
||||
pkgs.python3Packages.wheel
|
||||
];
|
||||
buildInputs = [
|
||||
deltachat-rpc-server-win32
|
||||
];
|
||||
buildPhase = ''
|
||||
mkdir tmp
|
||||
cp ${deltachat-rpc-server-win32}/bin/deltachat-rpc-server.exe tmp/deltachat-rpc-server.exe
|
||||
python3 scripts/wheel-rpc-server.py win32 tmp/deltachat-rpc-server.exe
|
||||
'';
|
||||
installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out'';
|
||||
};
|
||||
mkWheel
|
||||
{ rpc-server = deltachat-rpc-server-win32; arch = "win32"; binaryName = "deltachat-rpc-server.exe"; };
|
||||
|
||||
# Run `nix build .#docs` to get C docs generated in `./result/`.
|
||||
docs =
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "docs";
|
||||
version = manifest.version;
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
nativeBuildInputs = [ pkgs.doxygen ];
|
||||
buildPhase = ''scripts/run-doxygen.sh'';
|
||||
installPhase = ''mkdir -p $out; cp -av deltachat-ffi/html deltachat-ffi/xml $out'';
|
||||
};
|
||||
docs = pkgs.callPackage ./nix/c-docs.nix { inherit version; };
|
||||
|
||||
libdeltachat =
|
||||
let
|
||||
rustPlatform = (pkgs.makeRustPlatform {
|
||||
cargo = fenixToolchain;
|
||||
rustc = fenixToolchain;
|
||||
});
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "libdeltachat";
|
||||
version = manifest.version;
|
||||
src = rustSrc;
|
||||
cargoDeps = pkgs.rustPlatform.importCargoLock cargoLock;
|
||||
libdeltachat = pkgs.callPackage ./nix/libdeltachat.nix {
|
||||
inherit fenixToolchain rustSrc cargoLock fenixPkgs version;
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
pkgs.cmake
|
||||
rustPlatform.cargoSetupHook
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
substituteInPlace $out/include/deltachat.h \
|
||||
--replace __FILE__ '"${placeholder "out"}/include/deltachat.h"'
|
||||
'';
|
||||
};
|
||||
|
||||
deltachat-rpc-client =
|
||||
pkgs.python3Packages.buildPythonPackage {
|
||||
pname = "deltachat-rpc-client";
|
||||
version = manifest.version;
|
||||
src = pkgs.lib.cleanSource ./deltachat-rpc-client;
|
||||
format = "pyproject";
|
||||
propagatedBuildInputs = [
|
||||
pkgs.python3Packages.setuptools
|
||||
pkgs.python3Packages.imap-tools
|
||||
];
|
||||
};
|
||||
deltachat-rpc-client = pkgs.callPackage ./nix/deltachat-rpc-client.nix {
|
||||
inherit version;
|
||||
};
|
||||
|
||||
deltachat-python =
|
||||
pkgs.python3Packages.buildPythonPackage {
|
||||
pname = "deltachat-python";
|
||||
version = manifest.version;
|
||||
inherit version;
|
||||
src = pkgs.lib.cleanSource ./python;
|
||||
format = "pyproject";
|
||||
buildInputs = [
|
||||
@@ -551,51 +188,12 @@
|
||||
pkgs.python3Packages.requests
|
||||
];
|
||||
};
|
||||
python-docs =
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "docs";
|
||||
version = manifest.version;
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
buildInputs = [
|
||||
deltachat-python
|
||||
deltachat-rpc-client
|
||||
pkgs.python3Packages.breathe
|
||||
pkgs.python3Packages.sphinx-rtd-theme
|
||||
];
|
||||
nativeBuildInputs = [ pkgs.sphinx ];
|
||||
buildPhase = ''sphinx-build -b html -a python/doc/ dist/html'';
|
||||
installPhase = ''mkdir -p $out; cp -av dist/html $out'';
|
||||
};
|
||||
};
|
||||
|
||||
devShells.default =
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = system;
|
||||
overlays = [ fenix.overlays.default ];
|
||||
python-docs = pkgs.callPackage ./nix/python-docs.nix {
|
||||
inherit deltachat-python deltachat-rpc-client version;
|
||||
};
|
||||
in
|
||||
pkgs.mkShell {
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
(fenix.packages.${system}.complete.withComponents [
|
||||
"cargo"
|
||||
"clippy"
|
||||
"rust-src"
|
||||
"rustc"
|
||||
"rustfmt"
|
||||
])
|
||||
cargo-deny
|
||||
rust-analyzer-nightly
|
||||
cargo-nextest
|
||||
perl # needed to build vendored OpenSSL
|
||||
git-cliff
|
||||
(python3.withPackages (pypkgs: with pypkgs; [
|
||||
tox
|
||||
]))
|
||||
nodejs
|
||||
];
|
||||
};
|
||||
|
||||
devShells.default = import ./nix/devshell.nix { inherit nixpkgs fenix system; };
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
63
nix/android-package.nix
Normal file
63
nix/android-package.nix
Normal file
@@ -0,0 +1,63 @@
|
||||
{ pkgs, naersk, fenixPkgs, system, version, rustSrc, android }:
|
||||
arch: packageName:
|
||||
let
|
||||
androidSdk = android.sdk.${system} (sdkPkgs:
|
||||
builtins.attrValues {
|
||||
inherit (sdkPkgs) ndk-27-2-12479018 cmdline-tools-latest;
|
||||
});
|
||||
androidNdkRoot = "${androidSdk}/share/android-sdk/ndk/27.2.12479018";
|
||||
androidAttrs = {
|
||||
armeabi-v7a = {
|
||||
cc = "armv7a-linux-androideabi21-clang";
|
||||
rustTarget = "armv7-linux-androideabi";
|
||||
};
|
||||
arm64-v8a = {
|
||||
cc = "aarch64-linux-android21-clang";
|
||||
rustTarget = "aarch64-linux-android";
|
||||
};
|
||||
x86 = {
|
||||
cc = "i686-linux-android21-clang";
|
||||
rustTarget = "i686-linux-android";
|
||||
};
|
||||
x86_64 = {
|
||||
cc = "x86_64-linux-android21-clang";
|
||||
rustTarget = "x86_64-linux-android";
|
||||
};
|
||||
};
|
||||
|
||||
rustTarget = androidAttrs.${arch}.rustTarget;
|
||||
toolchain = fenixPkgs.combine [
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
fenixPkgs.targets.${rustTarget}.stable.rust-std
|
||||
];
|
||||
naersk-lib = pkgs.callPackage naersk {
|
||||
cargo = toolchain;
|
||||
rustc = toolchain;
|
||||
};
|
||||
targetToolchain = "${androidNdkRoot}/toolchains/llvm/prebuilt/linux-x86_64";
|
||||
targetCcName = androidAttrs.${arch}.cc;
|
||||
targetCc = "${targetToolchain}/bin/${targetCcName}";
|
||||
in
|
||||
naersk-lib.buildPackage rec {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
inherit version;
|
||||
strictDeps = true;
|
||||
src = rustSrc;
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
];
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
|
||||
CARGO_BUILD_TARGET = rustTarget;
|
||||
TARGET_CC = "${targetCc}";
|
||||
CARGO_BUILD_RUSTFLAGS = [
|
||||
"-C"
|
||||
"linker=${TARGET_CC}"
|
||||
];
|
||||
|
||||
CC = "${targetCc}";
|
||||
LD = "${targetCc}";
|
||||
}
|
||||
9
nix/c-docs.nix
Normal file
9
nix/c-docs.nix
Normal file
@@ -0,0 +1,9 @@
|
||||
{ pkgs, version }:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "docs";
|
||||
inherit version;
|
||||
src = pkgs.lib.cleanSource ../.;
|
||||
nativeBuildInputs = [ pkgs.doxygen ];
|
||||
buildPhase = ''scripts/run-doxygen.sh'';
|
||||
installPhase = ''mkdir -p $out; cp -av deltachat-ffi/html deltachat-ffi/xml $out'';
|
||||
}
|
||||
50
nix/cross-rust-package.nix
Normal file
50
nix/cross-rust-package.nix
Normal file
@@ -0,0 +1,50 @@
|
||||
{ pkgs, nixpkgs, arch2targets, naersk, fenixPkgs, system, rustSrc, version }:
|
||||
arch: packageName:
|
||||
let
|
||||
crossTarget = arch2targets."${arch}";
|
||||
pkgsCross =
|
||||
if crossTarget == system then
|
||||
import nixpkgs { inherit system; }
|
||||
else
|
||||
import nixpkgs {
|
||||
system = system;
|
||||
crossSystem.config = crossTarget;
|
||||
};
|
||||
rustTarget = pkgsCross.stdenv.hostPlatform.rust.rustcTarget;
|
||||
toolchain = fenixPkgs.combine [
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
fenixPkgs.targets.${rustTarget}.stable.rust-std
|
||||
];
|
||||
naersk-lib = (pkgs.callPackage naersk {
|
||||
cargo = toolchain;
|
||||
rustc = toolchain;
|
||||
}).override {
|
||||
pkgs = pkgsCross;
|
||||
};
|
||||
in
|
||||
naersk-lib.buildPackage rec {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
inherit version;
|
||||
strictDeps = true;
|
||||
src = rustSrc;
|
||||
nativeBuildInputs = [
|
||||
pkgsCross.buildPackages.perl # Needed to build vendored OpenSSL.
|
||||
];
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
|
||||
CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS = "-Clink-args=-L${pkgsCross.libiconv}/lib";
|
||||
CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS = "-Clink-args=-L${pkgsCross.libiconv}/lib";
|
||||
|
||||
CARGO_BUILD_TARGET = rustTarget;
|
||||
TARGET_CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc";
|
||||
CARGO_BUILD_RUSTFLAGS = [
|
||||
"-C"
|
||||
"linker=${TARGET_CC}"
|
||||
];
|
||||
|
||||
CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc";
|
||||
LD = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc";
|
||||
}
|
||||
11
nix/deltachat-rpc-client.nix
Normal file
11
nix/deltachat-rpc-client.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs, version }:
|
||||
pkgs.python3Packages.buildPythonPackage {
|
||||
pname = "deltachat-rpc-client";
|
||||
inherit version;
|
||||
src = pkgs.lib.cleanSource ../deltachat-rpc-client;
|
||||
format = "pyproject";
|
||||
propagatedBuildInputs = [
|
||||
pkgs.python3Packages.setuptools
|
||||
pkgs.python3Packages.imap-tools
|
||||
];
|
||||
}
|
||||
27
nix/devshell.nix
Normal file
27
nix/devshell.nix
Normal file
@@ -0,0 +1,27 @@
|
||||
{ nixpkgs, fenix, system }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ fenix.overlays.default ];
|
||||
};
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
(fenix.packages.${system}.complete.withComponents [
|
||||
"cargo"
|
||||
"clippy"
|
||||
"rust-src"
|
||||
"rustc"
|
||||
"rustfmt"
|
||||
])
|
||||
cargo-deny
|
||||
rust-analyzer-nightly
|
||||
cargo-nextest
|
||||
perl # needed to build vendored OpenSSL
|
||||
git-cliff
|
||||
(python3.withPackages (pypkgs: with pypkgs; [
|
||||
tox
|
||||
]))
|
||||
nodejs
|
||||
];
|
||||
}
|
||||
26
nix/libdeltachat.nix
Normal file
26
nix/libdeltachat.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ pkgs, fenixToolchain, rustSrc, cargoLock, fenixPkgs, version }:
|
||||
let
|
||||
rustPlatform = (pkgs.makeRustPlatform {
|
||||
cargo = fenixToolchain;
|
||||
rustc = fenixToolchain;
|
||||
});
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "libdeltachat";
|
||||
inherit version;
|
||||
src = rustSrc;
|
||||
cargoDeps = pkgs.rustPlatform.importCargoLock cargoLock;
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
pkgs.cmake
|
||||
rustPlatform.cargoSetupHook
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
substituteInPlace $out/include/deltachat.h \
|
||||
--replace __FILE__ '"${placeholder "out"}/include/deltachat.h"'
|
||||
'';
|
||||
}
|
||||
15
nix/python-docs.nix
Normal file
15
nix/python-docs.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{ pkgs, version, deltachat-python, deltachat-rpc-client }:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "docs";
|
||||
inherit version;
|
||||
src = pkgs.lib.cleanSource ../.;
|
||||
buildInputs = [
|
||||
deltachat-python
|
||||
deltachat-rpc-client
|
||||
pkgs.python3Packages.breathe
|
||||
pkgs.python3Packages.sphinx-rtd-theme
|
||||
];
|
||||
nativeBuildInputs = [ pkgs.sphinx ];
|
||||
buildPhase = ''sphinx-build -b html -a python/doc/ dist/html'';
|
||||
installPhase = ''mkdir -p $out; cp -av dist/html $out'';
|
||||
}
|
||||
28
nix/wheel.nix
Normal file
28
nix/wheel.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
{ pkgs, nix-filter, version, root }:
|
||||
{ rpc-server, arch, binaryName ? "deltachat-rpc-server" }:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "deltachat-rpc-server-${arch}-wheel";
|
||||
inherit version;
|
||||
src = nix-filter.lib {
|
||||
inherit root;
|
||||
include = [
|
||||
"scripts/wheel-rpc-server.py"
|
||||
"deltachat-rpc-server/README.md"
|
||||
"LICENSE"
|
||||
"Cargo.toml"
|
||||
];
|
||||
};
|
||||
nativeBuildInputs = [
|
||||
pkgs.python3
|
||||
pkgs.python3Packages.wheel
|
||||
];
|
||||
buildInputs = [
|
||||
rpc-server
|
||||
];
|
||||
buildPhase = ''
|
||||
mkdir tmp
|
||||
cp ${rpc-server}/bin/${binaryName} tmp/${binaryName}
|
||||
python3 scripts/wheel-rpc-server.py ${arch} tmp/${binaryName}
|
||||
'';
|
||||
installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out'';
|
||||
}
|
||||
66
nix/win32-package.nix
Normal file
66
nix/win32-package.nix
Normal file
@@ -0,0 +1,66 @@
|
||||
{ pkgs, naersk, fenixPkgs, system, version }:
|
||||
packageName:
|
||||
let
|
||||
pkgsWin32 = pkgs.pkgsCross.mingw32;
|
||||
rustTarget = pkgsWin32.stdenv.hostPlatform.rust.rustcTarget;
|
||||
toolchainWin = fenixPkgs.combine [
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
fenixPkgs.targets.${rustTarget}.stable.rust-std
|
||||
];
|
||||
naerskWin = pkgs.callPackage naersk {
|
||||
cargo = toolchainWin;
|
||||
rustc = toolchainWin;
|
||||
};
|
||||
|
||||
# Get rid of MCF Gthread library.
|
||||
# See <https://github.com/NixOS/nixpkgs/issues/156343>
|
||||
# and <https://discourse.nixos.org/t/statically-linked-mingw-binaries/38395>
|
||||
# for details.
|
||||
#
|
||||
# Use DWARF-2 instead of SJLJ for exception handling.
|
||||
winCC = pkgsWin32.buildPackages.wrapCC (
|
||||
(pkgsWin32.buildPackages.gcc-unwrapped.override
|
||||
({
|
||||
threadsCross = {
|
||||
model = "win32";
|
||||
package = null;
|
||||
};
|
||||
})).overrideAttrs (oldAttr: {
|
||||
configureFlags = oldAttr.configureFlags ++ [
|
||||
"--disable-sjlj-exceptions"
|
||||
"--with-dwarf2"
|
||||
];
|
||||
})
|
||||
);
|
||||
in
|
||||
naerskWin.buildPackage rec {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
inherit version;
|
||||
strictDeps = true;
|
||||
src = pkgs.lib.cleanSource ../.;
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
];
|
||||
depsBuildBuild = [
|
||||
winCC
|
||||
];
|
||||
buildInputs = [
|
||||
pkgsWin32.windows.pthreads
|
||||
];
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
|
||||
CARGO_BUILD_TARGET = rustTarget;
|
||||
TARGET_CC = "${winCC}/bin/${winCC.targetPrefix}cc";
|
||||
CARGO_BUILD_RUSTFLAGS = [
|
||||
"-C"
|
||||
"linker=${TARGET_CC}"
|
||||
"-L"
|
||||
"native=${pkgsWin32.windows.pthreads}/lib"
|
||||
];
|
||||
|
||||
CC = "${winCC}/bin/${winCC.targetPrefix}cc";
|
||||
LD = "${winCC}/bin/${winCC.targetPrefix}cc";
|
||||
}
|
||||
45
nix/win64-package.nix
Normal file
45
nix/win64-package.nix
Normal file
@@ -0,0 +1,45 @@
|
||||
{ pkgs, naersk, fenixPkgs, system, version }:
|
||||
packageName:
|
||||
let
|
||||
pkgsWin64 = pkgs.pkgsCross.mingwW64;
|
||||
rustTarget = pkgsWin64.stdenv.hostPlatform.rust.rustcTarget;
|
||||
toolchainWin = fenixPkgs.combine [
|
||||
fenixPkgs.stable.rustc
|
||||
fenixPkgs.stable.cargo
|
||||
fenixPkgs.targets.${rustTarget}.stable.rust-std
|
||||
];
|
||||
naerskWin = pkgs.callPackage naersk {
|
||||
cargo = toolchainWin;
|
||||
rustc = toolchainWin;
|
||||
};
|
||||
in
|
||||
naerskWin.buildPackage rec {
|
||||
pname = packageName;
|
||||
cargoBuildOptions = x: x ++ [ "--package" packageName ];
|
||||
inherit version;
|
||||
strictDeps = true;
|
||||
src = pkgs.lib.cleanSource ../.;
|
||||
nativeBuildInputs = [
|
||||
pkgs.perl # Needed to build vendored OpenSSL.
|
||||
];
|
||||
depsBuildBuild = [
|
||||
pkgsWin64.stdenv.cc
|
||||
];
|
||||
buildInputs = [
|
||||
pkgsWin64.windows.pthreads
|
||||
];
|
||||
auditable = false; # Avoid cargo-auditable failures.
|
||||
doCheck = false; # Disable test as it requires network access.
|
||||
|
||||
CARGO_BUILD_TARGET = rustTarget;
|
||||
TARGET_CC = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc";
|
||||
CARGO_BUILD_RUSTFLAGS = [
|
||||
"-C"
|
||||
"linker=${TARGET_CC}"
|
||||
"-L"
|
||||
"native=${pkgsWin64.windows.pthreads}/lib"
|
||||
];
|
||||
|
||||
CC = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc";
|
||||
LD = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc";
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
2026-05-29
|
||||
2026-05-22
|
||||
87
src/chat.rs
87
src/chat.rs
@@ -32,7 +32,6 @@ use crate::debug_logging::maybe_set_logging_xdc;
|
||||
use crate::download::{
|
||||
DownloadState, PRE_MSG_ATTACHMENT_SIZE_THRESHOLD, PRE_MSG_SIZE_WARNING_THRESHOLD,
|
||||
};
|
||||
use crate::ensure_and_debug_assert_eq;
|
||||
use crate::ephemeral::{Timer as EphemeralTimer, start_chat_ephemeral_timers};
|
||||
use crate::events::EventType;
|
||||
use crate::key::{Fingerprint, self_fingerprint};
|
||||
@@ -1783,8 +1782,9 @@ impl Chat {
|
||||
);
|
||||
bail!("Cannot set message, contact for {} not found.", self.id);
|
||||
}
|
||||
} else if self.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 {
|
||||
ensure_and_debug_assert_eq!(self.typ, Chattype::Group,);
|
||||
} else if matches!(self.typ, Chattype::Group | Chattype::OutBroadcast)
|
||||
&& self.param.get_int(Param::Unpromoted).unwrap_or_default() == 1
|
||||
{
|
||||
msg.param.set_int(Param::AttachChatAvatarAndDescription, 1);
|
||||
self.param
|
||||
.remove(Param::Unpromoted)
|
||||
@@ -3626,6 +3626,9 @@ pub(crate) async fn create_group_ex(
|
||||
/// because the word "channel" already appears a lot in the code,
|
||||
/// which would make it hard to grep for it.
|
||||
///
|
||||
/// After creation, the chat contains no recipients and is in _unpromoted_ state;
|
||||
/// see [`create_group`] for more information on the unpromoted state.
|
||||
///
|
||||
/// Returns the created chat's id.
|
||||
pub async fn create_broadcast(context: &Context, chat_name: String) -> Result<ChatId> {
|
||||
let grpid = create_id();
|
||||
@@ -3657,20 +3660,17 @@ pub(crate) async fn create_out_broadcast_ex(
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
ensure!(cnt == 0, "{cnt} chats exist with grpid {grpid}");
|
||||
let mut params: Params = Params::new();
|
||||
params.update_timestamp(Param::GroupNameTimestamp, time())?;
|
||||
|
||||
t.execute(
|
||||
"INSERT INTO chats
|
||||
(type, name, name_normalized, grpid, created_timestamp, param)
|
||||
VALUES(?, ?, ?, ?, ?, ?)",
|
||||
(type, name, name_normalized, grpid, created_timestamp)
|
||||
VALUES(?, ?, ?, ?, ?)",
|
||||
(
|
||||
Chattype::OutBroadcast,
|
||||
&chat_name,
|
||||
normalize_text(&chat_name),
|
||||
&grpid,
|
||||
timestamp,
|
||||
params.to_string(),
|
||||
),
|
||||
)?;
|
||||
let chat_id = ChatId::new(t.last_insert_rowid().try_into()?);
|
||||
@@ -3738,19 +3738,17 @@ pub(crate) async fn update_chat_contacts_table(
|
||||
id: ChatId,
|
||||
contacts: &BTreeSet<ContactId>,
|
||||
) -> Result<()> {
|
||||
// See add_to_chat_contacts_table() for reasoning.
|
||||
let limit = cmp::max(time().saturating_add(TIMESTAMP_SENT_TOLERANCE), timestamp);
|
||||
context
|
||||
.sql
|
||||
.transaction(move |transaction| {
|
||||
// Bump `remove_timestamp` even for members from `contacts`.
|
||||
// Bump `remove_timestamp` to at least `now`
|
||||
// even for members from `contacts`.
|
||||
// We add members from `contacts` back below.
|
||||
transaction.execute(
|
||||
"UPDATE chats_contacts SET
|
||||
add_timestamp=MIN(add_timestamp, ?1),
|
||||
remove_timestamp=MAX(MIN(remove_timestamp,?1), MIN(add_timestamp,?1)+1, ?)
|
||||
"UPDATE chats_contacts
|
||||
SET remove_timestamp=MAX(add_timestamp+1, ?)
|
||||
WHERE chat_id=?",
|
||||
(limit, timestamp, id),
|
||||
(timestamp, id),
|
||||
)?;
|
||||
|
||||
if !contacts.is_empty() {
|
||||
@@ -3762,8 +3760,9 @@ pub(crate) async fn update_chat_contacts_table(
|
||||
)?;
|
||||
|
||||
for contact_id in contacts {
|
||||
// We bumped `remove_timestamp` for existing rows above,
|
||||
// so on conflict it is enough to set `add_timestamp = remove_timestamp`.
|
||||
// We bumped `add_timestamp` for existing rows above,
|
||||
// so on conflict it is enough to set `add_timestamp = remove_timestamp`
|
||||
// and this guarantees that `add_timestamp` is no less than `timestamp`.
|
||||
statement.execute((id, contact_id, timestamp))?;
|
||||
}
|
||||
}
|
||||
@@ -3780,24 +3779,17 @@ pub(crate) async fn add_to_chat_contacts_table(
|
||||
chat_id: ChatId,
|
||||
contact_ids: &[ContactId],
|
||||
) -> Result<()> {
|
||||
// Our clock may be slow, so limit stored timestamps with `timestamp` if it's bigger. This way
|
||||
// we only cap remote timestamps if, in addition, remote changes arrive reordered or we do local
|
||||
// changes. Also allow some tolerance, moreover, previous removals might lend time from the
|
||||
// future.
|
||||
let limit = cmp::max(time().saturating_add(TIMESTAMP_SENT_TOLERANCE), timestamp);
|
||||
context
|
||||
.sql
|
||||
.transaction(move |transaction| {
|
||||
let mut add_statement = transaction.prepare(
|
||||
"INSERT INTO chats_contacts (chat_id, contact_id, add_timestamp) VALUES(?1, ?2, ?3)
|
||||
ON CONFLICT (chat_id, contact_id)
|
||||
DO UPDATE SET
|
||||
remove_timestamp=MIN(remove_timestamp, ?4),
|
||||
add_timestamp=MIN(MAX(add_timestamp,remove_timestamp,?3), ?4)",
|
||||
DO UPDATE SET add_timestamp=MAX(remove_timestamp, ?3)",
|
||||
)?;
|
||||
|
||||
for contact_id in contact_ids {
|
||||
add_statement.execute((chat_id, contact_id, timestamp, limit))?;
|
||||
add_statement.execute((chat_id, contact_id, timestamp))?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
@@ -3808,34 +3800,26 @@ pub(crate) async fn add_to_chat_contacts_table(
|
||||
|
||||
/// Removes a contact from the chat
|
||||
/// by updating the `remove_timestamp`.
|
||||
/// Returns whether the contact has been a chat member recently. If so, a removal message should be
|
||||
/// sent.
|
||||
pub(crate) async fn remove_from_chat_contacts_table(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: ContactId,
|
||||
) -> Result<bool> {
|
||||
) -> Result<()> {
|
||||
let now = time();
|
||||
// See add_to_chat_contacts_table() for reasoning.
|
||||
let limit = now.saturating_add(TIMESTAMP_SENT_TOLERANCE);
|
||||
let is_past_member = context
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"UPDATE chats_contacts SET
|
||||
add_timestamp=MIN(add_timestamp, ?1),
|
||||
remove_timestamp=MAX(MIN(remove_timestamp,?1), MIN(add_timestamp,?1)+1, ?)
|
||||
"UPDATE chats_contacts
|
||||
SET remove_timestamp=MAX(add_timestamp+1, ?)
|
||||
WHERE chat_id=? AND contact_id=?",
|
||||
(limit, now, chat_id, contact_id),
|
||||
(now, chat_id, contact_id),
|
||||
)
|
||||
.await?
|
||||
> 0;
|
||||
Ok(is_past_member)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes a contact from the chat
|
||||
/// without leaving a trace in the db.
|
||||
/// Returns whether the contact was removed, even if it was a past contact. If so, a removal message
|
||||
/// should be sent if the removal is issued by this device.
|
||||
/// without leaving a trace.
|
||||
///
|
||||
/// Note that if we call this function,
|
||||
/// and then receive a message from another device
|
||||
@@ -3845,17 +3829,17 @@ pub(crate) async fn remove_from_chat_contacts_table_without_trace(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: ContactId,
|
||||
) -> Result<bool> {
|
||||
let removed = context
|
||||
) -> Result<()> {
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"DELETE FROM chats_contacts
|
||||
WHERE chat_id=? AND contact_id=?",
|
||||
(chat_id, contact_id),
|
||||
)
|
||||
.await?
|
||||
> 0;
|
||||
Ok(removed)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds a contact to the chat.
|
||||
@@ -4175,13 +4159,10 @@ pub async fn remove_contact_from_chat(
|
||||
|
||||
let mut sync = Nosync;
|
||||
|
||||
let removed = if chat.is_promoted() && chat.typ != Chattype::OutBroadcast {
|
||||
remove_from_chat_contacts_table(context, chat_id, contact_id).await?
|
||||
if chat.is_promoted() && chat.typ != Chattype::OutBroadcast {
|
||||
remove_from_chat_contacts_table(context, chat_id, contact_id).await?;
|
||||
} else {
|
||||
remove_from_chat_contacts_table_without_trace(context, chat_id, contact_id).await?
|
||||
};
|
||||
if !removed {
|
||||
return Ok(());
|
||||
remove_from_chat_contacts_table_without_trace(context, chat_id, contact_id).await?;
|
||||
}
|
||||
|
||||
// We do not return an error if the contact does not exist in the database.
|
||||
|
||||
@@ -9,7 +9,6 @@ use crate::headerdef::HeaderDef;
|
||||
use crate::imex::{ImexMode, has_backup, imex};
|
||||
use crate::message::{Message, MessengerMessage, delete_msgs};
|
||||
use crate::mimeparser::{self, MimeMessage};
|
||||
use crate::qr::{Qr, check_qr};
|
||||
use crate::receive_imf::receive_imf;
|
||||
use crate::securejoin::{get_securejoin_qr, join_securejoin};
|
||||
use crate::test_utils;
|
||||
@@ -2800,30 +2799,6 @@ async fn test_can_send_group() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_cant_remove_nonmember() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let bob = &tcm.bob().await;
|
||||
let charlie = &tcm.charlie().await;
|
||||
|
||||
let alice_broadcast_id = create_broadcast(alice, "Channel".to_string()).await?;
|
||||
let qr = get_securejoin_qr(alice, Some(alice_broadcast_id))
|
||||
.await
|
||||
.unwrap();
|
||||
tcm.exec_securejoin_qr(bob, alice, &qr).await;
|
||||
|
||||
let alice_charlie_id = alice.add_or_lookup_contact_id(charlie).await;
|
||||
remove_contact_from_chat(alice, alice_broadcast_id, alice_charlie_id).await?;
|
||||
assert!(alice.pop_sent_msg_opt(Duration::ZERO).await.is_none());
|
||||
assert!(!remove_from_chat_contacts_table(alice, alice_broadcast_id, alice_charlie_id).await?);
|
||||
assert!(
|
||||
!remove_from_chat_contacts_table_without_trace(alice, alice_broadcast_id, alice_charlie_id)
|
||||
.await?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that in a broadcast channel,
|
||||
/// the recipients can't see the identity of their fellow recipients.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
@@ -2947,24 +2922,10 @@ async fn test_broadcast_change_name() -> Result<()> {
|
||||
let fiona = &tcm.fiona().await;
|
||||
|
||||
let broadcast_id = create_broadcast(alice, "Channel".to_string()).await?;
|
||||
let mut qr = get_securejoin_qr(alice, Some(broadcast_id)).await.unwrap();
|
||||
// Something goes wrong with the title, e.g. maybe it gets ellipsized
|
||||
// Note that the title always comes at the end for human readability
|
||||
qr += "+modified+title";
|
||||
|
||||
{
|
||||
tcm.section("Alice invites Bob to her channel");
|
||||
let Qr::AskJoinBroadcast { name, .. } = check_qr(bob, &qr).await? else {
|
||||
panic!();
|
||||
};
|
||||
assert_eq!(name, "Channel modified title");
|
||||
|
||||
// The channel's name gets fixed after actually joining the channel:
|
||||
let bob_chat_id = tcm.exec_securejoin_qr(bob, alice, &qr).await;
|
||||
let bob_chat = Chat::load_from_db(bob, bob_chat_id).await?;
|
||||
assert_eq!(bob_chat.name, "Channel");
|
||||
}
|
||||
let qr = get_securejoin_qr(alice, Some(broadcast_id)).await.unwrap();
|
||||
|
||||
tcm.section("Alice invites Bob to her channel");
|
||||
tcm.exec_securejoin_qr(bob, alice, &qr).await;
|
||||
tcm.section("Alice invites Fiona to her channel");
|
||||
tcm.exec_securejoin_qr(fiona, alice, &qr).await;
|
||||
|
||||
|
||||
@@ -324,7 +324,6 @@ SELECT ?1, rfc724_mid, pre_rfc724_mid, timestamp, ?, ? FROM msgs WHERE id=?1
|
||||
if duration != 0 {
|
||||
ret += &format!("Duration: {duration} ms\n",);
|
||||
}
|
||||
ret += &format!("\nDatabase ID: {}", msg.id);
|
||||
if !msg.rfc724_mid.is_empty() {
|
||||
ret += &format!("\nMessage-ID: {}", msg.rfc724_mid);
|
||||
|
||||
@@ -2042,6 +2041,13 @@ pub(crate) async fn update_msg_state(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// as we do not cut inside words, this results in about 32-42 characters.
|
||||
// Do not use too long subjects - we add a tag after the subject which gets truncated by the clients otherwise.
|
||||
// It should also be very clear, the subject is _not_ the whole message.
|
||||
// The value is also used for CC:-summaries
|
||||
|
||||
// Context functions to work with messages
|
||||
|
||||
pub(crate) async fn set_msg_failed(
|
||||
context: &Context,
|
||||
msg: &mut Message,
|
||||
|
||||
@@ -231,10 +231,7 @@ static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new
|
||||
HashMap::from([
|
||||
(
|
||||
"imap.163.com",
|
||||
vec![
|
||||
IpAddr::V4(Ipv4Addr::new(111, 124, 203, 45)),
|
||||
IpAddr::V4(Ipv4Addr::new(111, 124, 203, 50)),
|
||||
],
|
||||
vec![IpAddr::V4(Ipv4Addr::new(111, 124, 203, 45))],
|
||||
),
|
||||
(
|
||||
"smtp.163.com",
|
||||
@@ -425,12 +422,12 @@ static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new
|
||||
"nine.testrun.org",
|
||||
vec![
|
||||
IpAddr::V4(Ipv4Addr::new(128, 140, 126, 197)),
|
||||
IpAddr::V4(Ipv4Addr::new(116, 202, 233, 236)),
|
||||
IpAddr::V4(Ipv4Addr::new(216, 144, 228, 100)),
|
||||
IpAddr::V4(Ipv4Addr::new(77, 42, 49, 41)),
|
||||
IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0x241, 0x4ce8, 0, 0, 0, 2)),
|
||||
IpAddr::V6(Ipv6Addr::new(
|
||||
0x2001, 0x41d0, 0x701, 0x1100, 0, 0, 0, 0x8ab1,
|
||||
)),
|
||||
IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f9, 0xfff1, 0x59, 0, 0, 0, 1)),
|
||||
],
|
||||
),
|
||||
(
|
||||
@@ -700,10 +697,6 @@ static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new
|
||||
"chatmail.hackea.org",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(82, 165, 11, 85))],
|
||||
),
|
||||
(
|
||||
"chat.adminforge.de",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(94, 130, 17, 142))],
|
||||
),
|
||||
(
|
||||
"chika.aangat.lahat.computer",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(71, 19, 150, 113))],
|
||||
@@ -745,46 +738,6 @@ static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new
|
||||
"danneskjold.de",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(46, 62, 216, 132))],
|
||||
),
|
||||
(
|
||||
"chat.in-the.eu",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(78, 46, 190, 129))],
|
||||
),
|
||||
(
|
||||
"chat.nuvon.app",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(178, 238, 38, 165))],
|
||||
),
|
||||
(
|
||||
"nibblehole.com",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(94, 247, 42, 209))],
|
||||
),
|
||||
(
|
||||
"chat.zashm.org",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(91, 245, 76, 39))],
|
||||
),
|
||||
(
|
||||
"chat.sus.fr",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(152, 67, 76, 190))],
|
||||
),
|
||||
(
|
||||
"delta.thelab.uno",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(146, 59, 228, 39))],
|
||||
),
|
||||
(
|
||||
"chat.vim.wtf",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(116, 203, 206, 170))],
|
||||
),
|
||||
(
|
||||
"uninterest.ing",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(172, 245, 70, 237))],
|
||||
),
|
||||
(
|
||||
"sweetfern.net",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(178, 156, 228, 133))],
|
||||
),
|
||||
(
|
||||
"delta.disobey.net",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(37, 74, 102, 44))],
|
||||
),
|
||||
(
|
||||
"darkrun.dev",
|
||||
vec![IpAddr::V4(Ipv4Addr::new(72, 11, 149, 146))],
|
||||
|
||||
@@ -126,12 +126,9 @@ pub async fn wrap_rustls<'a>(
|
||||
let root_cert_store =
|
||||
rustls::RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
||||
|
||||
let mut config = rustls::ClientConfig::builder_with_provider(Arc::new(
|
||||
rustls::crypto::aws_lc_rs::default_provider(),
|
||||
))
|
||||
.with_safe_default_protocol_versions()?
|
||||
.with_root_certificates(root_cert_store)
|
||||
.with_no_client_auth();
|
||||
let mut config = rustls::ClientConfig::builder()
|
||||
.with_root_certificates(root_cert_store)
|
||||
.with_no_client_auth();
|
||||
config.alpn_protocols = if alpn.is_empty() {
|
||||
vec![]
|
||||
} else {
|
||||
|
||||
@@ -51,7 +51,7 @@ impl rustls::client::danger::ServerCertVerifier for CustomCertificateVerifier {
|
||||
|
||||
let spki = parsed_certificate.subject_public_key_info();
|
||||
|
||||
let provider = rustls::crypto::aws_lc_rs::default_provider();
|
||||
let provider = rustls::crypto::ring::default_provider();
|
||||
|
||||
if let ServerName::DnsName(dns_name) = server_name
|
||||
&& dns_name.as_ref().starts_with("_")
|
||||
@@ -97,7 +97,7 @@ impl rustls::client::danger::ServerCertVerifier for CustomCertificateVerifier {
|
||||
cert: &CertificateDer<'_>,
|
||||
dss: &rustls::DigitallySignedStruct,
|
||||
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||
let provider = rustls::crypto::aws_lc_rs::default_provider();
|
||||
let provider = rustls::crypto::ring::default_provider();
|
||||
let supported_schemes = &provider.signature_verification_algorithms;
|
||||
rustls::crypto::verify_tls12_signature(message, cert, dss, supported_schemes)
|
||||
}
|
||||
@@ -108,13 +108,13 @@ impl rustls::client::danger::ServerCertVerifier for CustomCertificateVerifier {
|
||||
cert: &CertificateDer<'_>,
|
||||
dss: &rustls::DigitallySignedStruct,
|
||||
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||
let provider = rustls::crypto::aws_lc_rs::default_provider();
|
||||
let provider = rustls::crypto::ring::default_provider();
|
||||
let supported_schemes = &provider.signature_verification_algorithms;
|
||||
rustls::crypto::verify_tls13_signature(message, cert, dss, supported_schemes)
|
||||
}
|
||||
|
||||
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
|
||||
let provider = rustls::crypto::aws_lc_rs::default_provider();
|
||||
let provider = rustls::crypto::ring::default_provider();
|
||||
provider
|
||||
.signature_verification_algorithms
|
||||
.supported_schemes()
|
||||
|
||||
@@ -3790,17 +3790,13 @@ async fn apply_out_broadcast_changes(
|
||||
} else if from_id == ContactId::SELF
|
||||
&& let Some(removed_id) = removed_id
|
||||
{
|
||||
if chat::remove_from_chat_contacts_table_without_trace(context, chat.id, removed_id)
|
||||
.await?
|
||||
{
|
||||
better_msg.get_or_insert(
|
||||
stock_str::msg_del_member_local(context, removed_id, ContactId::SELF).await,
|
||||
);
|
||||
added_removed_id = Some(removed_id);
|
||||
} else {
|
||||
info!(context, "No-op broadcast member removal message (TRASH).");
|
||||
better_msg = Some("".to_string());
|
||||
}
|
||||
chat::remove_from_chat_contacts_table_without_trace(context, chat.id, removed_id)
|
||||
.await?;
|
||||
|
||||
better_msg.get_or_insert(
|
||||
stock_str::msg_del_member_local(context, removed_id, ContactId::SELF).await,
|
||||
);
|
||||
added_removed_id = Some(removed_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3874,20 +3870,17 @@ async fn apply_in_broadcast_changes(
|
||||
}
|
||||
chat::delete_broadcast_secret(context, chat.id).await?;
|
||||
|
||||
let removed =
|
||||
chat::remove_from_chat_contacts_table_without_trace(context, chat.id, ContactId::SELF)
|
||||
.await?;
|
||||
if !removed {
|
||||
info!(context, "No-op broadcast SELF-removal message (TRASH).");
|
||||
better_msg = Some("".to_string());
|
||||
} else if from_id == ContactId::SELF {
|
||||
if from_id == ContactId::SELF {
|
||||
better_msg.get_or_insert(stock_str::msg_you_left_broadcast(context));
|
||||
} else {
|
||||
better_msg.get_or_insert(
|
||||
stock_str::msg_del_member_local(context, ContactId::SELF, from_id).await,
|
||||
);
|
||||
}
|
||||
send_event_chat_modified |= removed;
|
||||
|
||||
chat::remove_from_chat_contacts_table_without_trace(context, chat.id, ContactId::SELF)
|
||||
.await?;
|
||||
send_event_chat_modified = true;
|
||||
} else if !chat.is_self_in_chat(context).await? {
|
||||
chat::add_to_chat_contacts_table(
|
||||
context,
|
||||
|
||||
26
src/stats.rs
26
src/stats.rs
@@ -18,7 +18,7 @@ use crate::config::Config;
|
||||
use crate::constants::{Chattype, DC_VERSION_STR};
|
||||
use crate::contact::{Contact, ContactId, Origin, import_vcard, mark_contact_id_as_verified};
|
||||
use crate::context::Context;
|
||||
use crate::key::{DcKey, load_self_public_key};
|
||||
use crate::key::load_self_public_keyring;
|
||||
use crate::log::LogExt;
|
||||
use crate::message::{Message, Viewtype};
|
||||
use crate::securejoin::QrInvite;
|
||||
@@ -33,14 +33,7 @@ const MESSAGE_STATS_UPDATE_INTERVAL_SECONDS: i64 = 4 * 60; // 4 minutes (less th
|
||||
#[derive(Serialize)]
|
||||
struct Statistics {
|
||||
core_version: String,
|
||||
number_of_transports: usize,
|
||||
key_create_timestamps: Vec<u32>,
|
||||
number_of_keys: u32,
|
||||
/// OpenPGP version of the key.
|
||||
key_version: u8,
|
||||
key_algorithm: String,
|
||||
/// Size of the public key in bytes (encoded in binary, not base64).
|
||||
pubkey_size: usize,
|
||||
stats_id: String,
|
||||
is_chatmail: bool,
|
||||
contact_stats: Vec<ContactStat>,
|
||||
@@ -352,15 +345,11 @@ async fn get_stats(context: &Context) -> Result<String> {
|
||||
.get_config_u32(Config::StatsLastOldContactId)
|
||||
.await?;
|
||||
|
||||
let self_public_key = load_self_public_key(context).await?;
|
||||
// `key_create_timestamps` is a `Vec` for historical reasons,
|
||||
// support for using multiple keys is being phased out.
|
||||
let key_create_timestamps: Vec<u32> = vec![self_public_key.created_at().as_secs()];
|
||||
let number_of_keys: u32 = context
|
||||
.sql
|
||||
.query_get_value("SELECT COUNT(*) FROM keypairs", ())
|
||||
let key_create_timestamps: Vec<u32> = load_self_public_keyring(context)
|
||||
.await?
|
||||
.unwrap_or(0);
|
||||
.iter()
|
||||
.map(|k| k.created_at().as_secs())
|
||||
.collect();
|
||||
|
||||
let sending_enabled_timestamps =
|
||||
get_timestamps(context, "stats_sending_enabled_events").await?;
|
||||
@@ -369,12 +358,7 @@ async fn get_stats(context: &Context) -> Result<String> {
|
||||
|
||||
let stats = Statistics {
|
||||
core_version: DC_VERSION_STR.to_string(),
|
||||
number_of_transports: context.count_transports().await?,
|
||||
key_create_timestamps,
|
||||
number_of_keys,
|
||||
key_version: self_public_key.primary_key.version().into(),
|
||||
key_algorithm: format!("{:?}", self_public_key.algorithm()),
|
||||
pubkey_size: DcKey::to_bytes(&self_public_key).len(),
|
||||
stats_id: stats_id(context).await?,
|
||||
is_chatmail: context.is_chatmail().await?,
|
||||
contact_stats: get_contact_stats(context, last_old_contact).await?,
|
||||
|
||||
@@ -595,33 +595,3 @@ async fn test_stats_enable_disable_timestamps() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_cryptography_stats() -> Result<()> {
|
||||
let alice = &TestContext::new_alice().await;
|
||||
let stats = get_stats(alice).await.unwrap();
|
||||
let stats: serde_json::Value = serde_json::from_str(&stats)?;
|
||||
|
||||
let number_of_transports: u64 = stats.get("number_of_transports").unwrap().as_u64().unwrap();
|
||||
assert_eq!(number_of_transports, 1);
|
||||
|
||||
let key_version = stats.get("key_version").unwrap().as_u64().unwrap();
|
||||
// Alice's key is v4
|
||||
assert_eq!(key_version, 4);
|
||||
|
||||
let key_algorithm = stats.get("key_algorithm").unwrap().as_str().unwrap();
|
||||
assert_eq!(key_algorithm, "EdDSALegacy");
|
||||
|
||||
let pubkey_size = stats.get("pubkey_size").unwrap().as_u64().unwrap();
|
||||
assert_eq!(pubkey_size, 583);
|
||||
|
||||
crate::transport::add_pseudo_transport(alice, "alice@ten.testrun.org").await?;
|
||||
|
||||
let stats = get_stats(alice).await.unwrap();
|
||||
let stats: serde_json::Value = serde_json::from_str(&stats)?;
|
||||
|
||||
let number_of_transports: u64 = stats.get("number_of_transports").unwrap().as_u64().unwrap();
|
||||
assert_eq!(number_of_transports, 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ async fn test_parse_receive_headers_integration() {
|
||||
let raw = include_bytes!("../../test-data/message/mail_with_cc.txt");
|
||||
let expected = r"State: Fresh
|
||||
|
||||
Database ID: X
|
||||
Message-ID: 2dfdbde7@example.org
|
||||
|
||||
Hop: From: localhost; By: hq5.merlinux.eu; Date: Sat, 14 Sep 2019 17:00:22 +0000
|
||||
@@ -51,7 +50,6 @@ Hop: From: hq5.merlinux.eu; By: hq5.merlinux.eu; Date: Sat, 14 Sep 2019 17:00:25
|
||||
let raw = include_bytes!("../../test-data/message/encrypted_with_received_headers.eml");
|
||||
let expected = "State: Fresh, Encrypted
|
||||
|
||||
Database ID: X
|
||||
Message-ID: Mr.adQpEwndXLH.LPDdlFVJ7wG@example.net
|
||||
|
||||
Hop: From: [127.0.0.1]; By: mail.example.org; Date: Mon, 27 Dec 2021 11:21:21 +0000
|
||||
@@ -73,10 +71,7 @@ async fn check_parse_receive_headers_integration(raw: &[u8], expected: &str) {
|
||||
// received time that depends on the test time which makes it impossible to
|
||||
// compare with a static string
|
||||
let capped_result = &msg_info[msg_info.find("State").unwrap()..];
|
||||
assert_eq!(
|
||||
expected.replace("\nDatabase ID: X", &format!("\nDatabase ID: {msg_id}")),
|
||||
capped_result
|
||||
);
|
||||
assert_eq!(expected, capped_result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -252,11 +252,7 @@ impl fmt::Display for ConfiguredLoginParam {
|
||||
write!(f, "{imap}")?;
|
||||
first = false;
|
||||
}
|
||||
write!(f, "]")?;
|
||||
if let Some(folder) = &self.imap_folder {
|
||||
write!(f, " folder:{folder:?}")?;
|
||||
}
|
||||
write!(f, " smtp:[")?;
|
||||
write!(f, "] smtp:[")?;
|
||||
let mut first = true;
|
||||
for smtp in &self.smtp {
|
||||
if !first {
|
||||
|
||||
@@ -34,7 +34,7 @@ async fn test_save_load_login_param() -> Result<()> {
|
||||
},
|
||||
user: "alice".to_string(),
|
||||
}],
|
||||
imap_folder: Some("Folder".to_string()),
|
||||
imap_folder: None,
|
||||
imap_user: "".to_string(),
|
||||
imap_password: "foo".to_string(),
|
||||
smtp: vec![ConfiguredServerLoginParam {
|
||||
@@ -56,7 +56,7 @@ async fn test_save_load_login_param() -> Result<()> {
|
||||
.clone()
|
||||
.save_to_transports_table(&t, &EnteredLoginParam::default(), time())
|
||||
.await?;
|
||||
let expected_param = r#"{"addr":"alice@example.org","imap":[{"connection":{"host":"imap.example.com","port":123,"security":"Starttls"},"user":"alice"}],"imap_folder":"Folder","imap_user":"","imap_password":"foo","smtp":[{"connection":{"host":"smtp.example.com","port":456,"security":"Tls"},"user":"alice@example.org"}],"smtp_user":"","smtp_password":"bar","provider_id":null,"certificate_checks":"Strict","oauth2":false}"#;
|
||||
let expected_param = r#"{"addr":"alice@example.org","imap":[{"connection":{"host":"imap.example.com","port":123,"security":"Starttls"},"user":"alice"}],"imap_user":"","imap_password":"foo","smtp":[{"connection":{"host":"smtp.example.com","port":456,"security":"Tls"},"user":"alice@example.org"}],"smtp_user":"","smtp_password":"bar","provider_id":null,"certificate_checks":"Strict","oauth2":false}"#;
|
||||
assert_eq!(
|
||||
t.sql
|
||||
.query_get_value::<String>("SELECT configured_param FROM transports", ())
|
||||
@@ -68,14 +68,6 @@ async fn test_save_load_login_param() -> Result<()> {
|
||||
let (_transport_id, loaded) = ConfiguredLoginParam::load(&t).await?.unwrap();
|
||||
assert_eq!(param, loaded);
|
||||
|
||||
let formatted = format!(" {loaded}");
|
||||
assert!(formatted.contains(" ***@example.org"));
|
||||
assert!(formatted.contains(" imap:[imap.example.com:123:starttls]"));
|
||||
assert!(formatted.contains(" folder:\"Folder\""));
|
||||
assert!(formatted.contains(" smtp:[smtp.example.com:456:tls]"));
|
||||
assert!(formatted.contains(" provider:none"));
|
||||
assert!(formatted.contains(" cert_strict"));
|
||||
|
||||
// Legacy ConfiguredImapCertificateChecks config is ignored
|
||||
t.set_config(Config::ConfiguredImapCertificateChecks, Some("999"))
|
||||
.await?;
|
||||
|
||||
Reference in New Issue
Block a user