mirror of
https://github.com/chatmail/core.git
synced 2026-04-02 13:32:11 +03:00
Compare commits
2 Commits
safe-e2ee
...
cleanup/ch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f40cdcc2ac | ||
|
|
957f099037 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,7 +16,6 @@ python/.tox
|
||||
*.egg-info
|
||||
__pycache__
|
||||
python/src/deltachat/capi*.so
|
||||
python/.venv/
|
||||
|
||||
python/liveconfig*
|
||||
|
||||
|
||||
143
Cargo.lock
generated
143
Cargo.lock
generated
@@ -84,7 +84,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.38"
|
||||
version = "0.3.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -130,7 +130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.0"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -317,7 +317,7 @@ name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -419,7 +419,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.11"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -481,11 +481,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat"
|
||||
version = "1.0.0-alpha.5"
|
||||
version = "1.0.0-alpha.4"
|
||||
dependencies = [
|
||||
"backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -508,6 +508,7 @@ dependencies = [
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pgp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)",
|
||||
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -530,8 +531,8 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deltachat-provider-database"
|
||||
version = "0.2.1"
|
||||
name = "deltachat-provider-overview"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -550,10 +551,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat_ffi"
|
||||
version = "1.0.0-alpha.5"
|
||||
version = "1.0.0-alpha.4"
|
||||
dependencies = [
|
||||
"deltachat 1.0.0-alpha.5",
|
||||
"deltachat-provider-database 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"deltachat 1.0.0-alpha.4",
|
||||
"deltachat-provider-overview 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -686,7 +687,7 @@ name = "error-chain"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -703,7 +704,7 @@ name = "failure"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -779,7 +780,7 @@ name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -900,7 +901,7 @@ name = "human-panic"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"os_type 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1088,7 +1089,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.4.6"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1299,7 +1300,7 @@ name = "nix"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1325,7 +1326,7 @@ name = "nom"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lexical-core 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1408,7 +1409,7 @@ name = "openssl"
|
||||
version = "0.10.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1600,6 +1601,46 @@ dependencies = [
|
||||
"x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.7.24"
|
||||
source = "git+https://github.com/sfackler/rust-phf?rev=0d00821#0d0082178568036736bb6d51cb91f95ca5a616c3"
|
||||
dependencies = [
|
||||
"phf_macros 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)",
|
||||
"phf_shared 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)",
|
||||
"proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.7.24"
|
||||
source = "git+https://github.com/sfackler/rust-phf?rev=0d00821#0d0082178568036736bb6d51cb91f95ca5a616c3"
|
||||
dependencies = [
|
||||
"phf_shared 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)",
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.7.24"
|
||||
source = "git+https://github.com/sfackler/rust-phf?rev=0d00821#0d0082178568036736bb6d51cb91f95ca5a616c3"
|
||||
dependencies = [
|
||||
"phf_generator 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)",
|
||||
"phf_shared 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)",
|
||||
"proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.7.24"
|
||||
source = "git+https://github.com/sfackler/rust-phf?rev=0d00821#0d0082178568036736bb6d51cb91f95ca5a616c3"
|
||||
dependencies = [
|
||||
"siphasher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.16"
|
||||
@@ -1616,7 +1657,7 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ctor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1631,6 +1672,16 @@ dependencies = [
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
@@ -1641,7 +1692,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.4"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1653,7 +1704,7 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1683,7 +1734,7 @@ name = "pulldown-cmark"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1721,7 +1772,7 @@ name = "quote"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1784,6 +1835,7 @@ dependencies = [
|
||||
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1881,6 +1933,15 @@ dependencies = [
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
@@ -2002,7 +2063,7 @@ name = "rusqlite"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libsqlite3-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -2152,7 +2213,7 @@ name = "serde_derive"
|
||||
version = "1.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -2212,6 +2273,11 @@ dependencies = [
|
||||
"opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "skeptic"
|
||||
version = "0.13.4"
|
||||
@@ -2289,7 +2355,7 @@ version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -2334,7 +2400,7 @@ name = "syn"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -2860,13 +2926,13 @@ dependencies = [
|
||||
"checksum ascii_utils 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
|
||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
||||
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
|
||||
"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5"
|
||||
"checksum backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2"
|
||||
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
|
||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||
"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
|
||||
"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
|
||||
"checksum bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
|
||||
"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
|
||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||
"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
|
||||
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||
"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774"
|
||||
@@ -2901,13 +2967,13 @@ dependencies = [
|
||||
"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
|
||||
"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
|
||||
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
||||
"checksum ctor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3e061727ebef83bbccac7c27b9a5ff9fd83094d34cb20f4005440a9562a27de7"
|
||||
"checksum ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5b6b2f4752cc29efbfd03474c532ce8f916f2d44ec5bb8c21f93bc76e5365528"
|
||||
"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d"
|
||||
"checksum darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfbcb0c5961907597a7d1148e3af036268f2b773886b8bb3eeb1e1281d3d3d6"
|
||||
"checksum darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6afc018370c3bff3eb51f89256a6bdb18b4fdcda72d577982a14954a7a0b402c"
|
||||
"checksum darling_macro 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6d8dac1c6f1d29a41c4712b4400f878cb4fcc4c7628f298dd75038e024998d1"
|
||||
"checksum debug_stub_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "496b7f8a2f853313c3ca370641d7ff3e42c32974fdccda8f0684599ed0a3ff6b"
|
||||
"checksum deltachat-provider-database 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "814dba060d9fdc7a989fccdc4810ada9d1c7a1f09131c78e42412bc6c634b93b"
|
||||
"checksum deltachat-provider-overview 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bef7b3626b0f859878db86ed54e4eef317adbcc3bcc3617eb38dec52e3f40e3"
|
||||
"checksum derive_builder 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ac53fa6a3cda160df823a9346442525dcaf1e171999a1cf23e67067e4fd64d4"
|
||||
"checksum derive_builder_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0288a23da9333c246bb18c143426074a6ae96747995c5819d2947b64cd942b37"
|
||||
"checksum derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d944ac6003ed268757ef1ee686753b57efc5fcf0ebe7b64c9fc81e7e32ff839"
|
||||
@@ -2969,7 +3035,7 @@ dependencies = [
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum lettre 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c66afaa5dfadbb81d4e00fd1d1ab057c7cd4c799c5a44e0009386d553587e728"
|
||||
"checksum lexical-core 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14"
|
||||
"checksum lexical-core 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d11f3928ffd249baadf9f083cdea16d7cf317b2a8be6227e1169102432a36d2"
|
||||
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
|
||||
"checksum libsqlite3-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5b95e89c330291768dc840238db7f9e204fd208511ab6319b56193a7f2ae25"
|
||||
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
||||
@@ -3020,12 +3086,17 @@ dependencies = [
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
"checksum pgp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb80b37b7debf9a98dc0caca3ed40ddf1d383691208763d0458df0b91521020f"
|
||||
"checksum phf 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)" = "<none>"
|
||||
"checksum phf_generator 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)" = "<none>"
|
||||
"checksum phf_macros 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)" = "<none>"
|
||||
"checksum phf_shared 0.7.24 (git+https://github.com/sfackler/rust-phf?rev=0d00821)" = "<none>"
|
||||
"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea"
|
||||
"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
|
||||
"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
|
||||
"checksum pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074"
|
||||
"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc"
|
||||
"checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8"
|
||||
"checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f"
|
||||
"checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510"
|
||||
"checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15"
|
||||
@@ -3050,6 +3121,7 @@ dependencies = [
|
||||
"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||
"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6"
|
||||
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
@@ -3084,6 +3156,7 @@ dependencies = [
|
||||
"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68"
|
||||
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
|
||||
"checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf"
|
||||
"checksum siphasher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9913c75df657d84a03fa689c016b0bb2863ff0b497b26a8d6e9703f8d5df03a8"
|
||||
"checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165"
|
||||
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||
"checksum slice-deque 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffddf594f5f597f63533d897427a570dbaa9feabaaa06595b74b71b7014507d7"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat"
|
||||
version = "1.0.0-alpha.5"
|
||||
version = "1.0.0-alpha.4"
|
||||
authors = ["dignifiedquire <dignifiedquire@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MPL"
|
||||
@@ -14,6 +14,7 @@ pgp = { version = "0.2", default-features = false }
|
||||
hex = "0.3.2"
|
||||
sha2 = "0.8.0"
|
||||
rand = "0.6.5"
|
||||
phf = { git = "https://github.com/sfackler/rust-phf", rev = "0d00821", features = ["macros"] }
|
||||
smallvec = "0.6.9"
|
||||
reqwest = "0.9.15"
|
||||
num-derive = "0.2.5"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat_ffi"
|
||||
version = "1.0.0-alpha.5"
|
||||
version = "1.0.0-alpha.4"
|
||||
description = "Deltachat FFI"
|
||||
authors = ["dignifiedquire <dignifiedquire@gmail.com>"]
|
||||
edition = "2018"
|
||||
@@ -16,7 +16,7 @@ crate-type = ["cdylib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
deltachat = { path = "../", default-features = false }
|
||||
deltachat-provider-database = "0.2.1"
|
||||
deltachat-provider-overview = "0.1.0"
|
||||
libc = "0.2"
|
||||
human-panic = "1.0.1"
|
||||
num-traits = "0.2.6"
|
||||
|
||||
@@ -405,14 +405,9 @@ char* dc_get_config (dc_context_t* context, const char*
|
||||
|
||||
/**
|
||||
* Get information about the context.
|
||||
*
|
||||
* The information is returned by a multi-line string
|
||||
* and contains information about the current configuration.
|
||||
*
|
||||
* If the context is not open or configured only a subset of the information
|
||||
* will be available. There is no guarantee about which information will be
|
||||
* included when however.
|
||||
*
|
||||
* @memberof dc_context_t
|
||||
* @param context The context as created by dc_context_new().
|
||||
* @return String which must be free()'d after usage. Never returns NULL.
|
||||
@@ -3485,7 +3480,7 @@ int dc_contact_is_verified (dc_contact_t* contact);
|
||||
* accessor functions. If no provider info is found, NULL will be
|
||||
* returned.
|
||||
*/
|
||||
dc_provider_t* dc_provider_new_from_domain (const char* domain);
|
||||
dc_provider_t* dc_provider_new_from_domain (char* domain);
|
||||
|
||||
|
||||
/**
|
||||
@@ -3499,7 +3494,7 @@ dc_provider_t* dc_provider_new_from_domain (const char* domain);
|
||||
* accessor functions. If no provider info is found, NULL will be
|
||||
* returned.
|
||||
*/
|
||||
dc_provider_t* dc_provider_new_from_email (const char* email);
|
||||
dc_provider_t* dc_provider_new_from_email (char* email);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -225,8 +225,8 @@ pub unsafe extern "C" fn dc_get_userdata(context: *mut dc_context_t) -> *mut lib
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_open(
|
||||
context: *mut dc_context_t,
|
||||
dbfile: *const libc::c_char,
|
||||
blobdir: *const libc::c_char,
|
||||
dbfile: *mut libc::c_char,
|
||||
blobdir: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
if context.is_null() || dbfile.is_null() {
|
||||
eprintln!("ignoring careless call to dc_open()");
|
||||
@@ -275,11 +275,11 @@ pub unsafe extern "C" fn dc_is_open(context: *mut dc_context_t) -> libc::c_int {
|
||||
eprintln!("ignoring careless call to dc_is_open()");
|
||||
return 0;
|
||||
}
|
||||
let ffi_context = &*context;
|
||||
let ffi_context = &mut *context;
|
||||
let inner_guard = ffi_context.inner.read().unwrap();
|
||||
match *inner_guard {
|
||||
Some(_) => 1,
|
||||
None => 0,
|
||||
Some(_) => 0,
|
||||
None => 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,8 +298,8 @@ pub unsafe extern "C" fn dc_get_blobdir(context: *mut dc_context_t) -> *mut libc
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_set_config(
|
||||
context: *mut dc_context_t,
|
||||
key: *const libc::c_char,
|
||||
value: *const libc::c_char,
|
||||
key: *mut libc::c_char,
|
||||
value: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
if context.is_null() || key.is_null() {
|
||||
eprintln!("ignoring careless call to dc_set_config()");
|
||||
@@ -322,7 +322,7 @@ pub unsafe extern "C" fn dc_set_config(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_get_config(
|
||||
context: *mut dc_context_t,
|
||||
key: *const libc::c_char,
|
||||
key: *mut libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
if context.is_null() || key.is_null() {
|
||||
eprintln!("ignoring careless call to dc_get_config()");
|
||||
@@ -347,12 +347,9 @@ pub unsafe extern "C" fn dc_get_info(context: *mut dc_context_t) -> *mut libc::c
|
||||
return dc_strdup(ptr::null());
|
||||
}
|
||||
let ffi_context = &*context;
|
||||
let guard = ffi_context.inner.read().unwrap();
|
||||
let info = match guard.as_ref() {
|
||||
Some(ref ctx) => ctx.get_info(),
|
||||
None => context::get_info(),
|
||||
};
|
||||
render_info(info).unwrap_or_default().strdup()
|
||||
ffi_context
|
||||
.with_inner(|ctx| render_info(ctx.get_info()).unwrap_or_default().strdup())
|
||||
.unwrap_or_else(|_| "".strdup())
|
||||
}
|
||||
|
||||
fn render_info(
|
||||
@@ -369,8 +366,8 @@ fn render_info(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_get_oauth2_url(
|
||||
context: *mut dc_context_t,
|
||||
addr: *const libc::c_char,
|
||||
redirect: *const libc::c_char,
|
||||
addr: *mut libc::c_char,
|
||||
redirect: *mut libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
if context.is_null() {
|
||||
eprintln!("ignoring careless call to dc_get_oauth2_url()");
|
||||
@@ -612,7 +609,7 @@ pub unsafe extern "C" fn dc_maybe_network(context: *mut dc_context_t) {
|
||||
pub unsafe extern "C" fn dc_get_chatlist(
|
||||
context: *mut dc_context_t,
|
||||
flags: libc::c_int,
|
||||
query_str: *const libc::c_char,
|
||||
query_str: *mut libc::c_char,
|
||||
query_id: u32,
|
||||
) -> *mut dc_chatlist_t {
|
||||
if context.is_null() {
|
||||
@@ -733,7 +730,7 @@ pub unsafe extern "C" fn dc_send_msg(
|
||||
pub unsafe extern "C" fn dc_send_text_msg(
|
||||
context: *mut dc_context_t,
|
||||
chat_id: u32,
|
||||
text_to_send: *const libc::c_char,
|
||||
text_to_send: *mut libc::c_char,
|
||||
) -> u32 {
|
||||
if context.is_null() || text_to_send.is_null() {
|
||||
eprintln!("ignoring careless call to dc_send_text_msg()");
|
||||
@@ -1017,7 +1014,7 @@ pub unsafe extern "C" fn dc_get_chat_contacts(
|
||||
pub unsafe extern "C" fn dc_search_msgs(
|
||||
context: *mut dc_context_t,
|
||||
chat_id: u32,
|
||||
query: *const libc::c_char,
|
||||
query: *mut libc::c_char,
|
||||
) -> *mut dc_array::dc_array_t {
|
||||
if context.is_null() || query.is_null() {
|
||||
eprintln!("ignoring careless call to dc_search_msgs()");
|
||||
@@ -1054,7 +1051,7 @@ pub unsafe extern "C" fn dc_get_chat(context: *mut dc_context_t, chat_id: u32) -
|
||||
pub unsafe extern "C" fn dc_create_group_chat(
|
||||
context: *mut dc_context_t,
|
||||
verified: libc::c_int,
|
||||
name: *const libc::c_char,
|
||||
name: *mut libc::c_char,
|
||||
) -> u32 {
|
||||
if context.is_null() || name.is_null() {
|
||||
eprintln!("ignoring careless call to dc_create_group_chat()");
|
||||
@@ -1131,7 +1128,7 @@ pub unsafe extern "C" fn dc_remove_contact_from_chat(
|
||||
pub unsafe extern "C" fn dc_set_chat_name(
|
||||
context: *mut dc_context_t,
|
||||
chat_id: u32,
|
||||
name: *const libc::c_char,
|
||||
name: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
if context.is_null() || chat_id <= constants::DC_CHAT_ID_LAST_SPECIAL as u32 || name.is_null() {
|
||||
eprintln!("ignoring careless call to dc_set_chat_name()");
|
||||
@@ -1151,7 +1148,7 @@ pub unsafe extern "C" fn dc_set_chat_name(
|
||||
pub unsafe extern "C" fn dc_set_chat_profile_image(
|
||||
context: *mut dc_context_t,
|
||||
chat_id: u32,
|
||||
image: *const libc::c_char,
|
||||
image: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
if context.is_null() || chat_id <= constants::DC_CHAT_ID_LAST_SPECIAL as u32 {
|
||||
eprintln!("ignoring careless call to dc_set_chat_profile_image()");
|
||||
@@ -1322,7 +1319,7 @@ pub unsafe extern "C" fn dc_get_msg(context: *mut dc_context_t, msg_id: u32) ->
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_may_be_valid_addr(addr: *const libc::c_char) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_may_be_valid_addr(addr: *mut libc::c_char) -> libc::c_int {
|
||||
if addr.is_null() {
|
||||
eprintln!("ignoring careless call to dc_may_be_valid_addr()");
|
||||
return 0;
|
||||
@@ -1334,7 +1331,7 @@ pub unsafe extern "C" fn dc_may_be_valid_addr(addr: *const libc::c_char) -> libc
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_lookup_contact_id_by_addr(
|
||||
context: *mut dc_context_t,
|
||||
addr: *const libc::c_char,
|
||||
addr: *mut libc::c_char,
|
||||
) -> u32 {
|
||||
if context.is_null() || addr.is_null() {
|
||||
eprintln!("ignoring careless call to dc_lookup_contact_id_by_addr()");
|
||||
@@ -1349,8 +1346,8 @@ pub unsafe extern "C" fn dc_lookup_contact_id_by_addr(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_create_contact(
|
||||
context: *mut dc_context_t,
|
||||
name: *const libc::c_char,
|
||||
addr: *const libc::c_char,
|
||||
name: *mut libc::c_char,
|
||||
addr: *mut libc::c_char,
|
||||
) -> u32 {
|
||||
if context.is_null() || addr.is_null() {
|
||||
eprintln!("ignoring careless call to dc_create_contact()");
|
||||
@@ -1369,7 +1366,7 @@ pub unsafe extern "C" fn dc_create_contact(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_add_address_book(
|
||||
context: *mut dc_context_t,
|
||||
addr_book: *const libc::c_char,
|
||||
addr_book: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
if context.is_null() || addr_book.is_null() {
|
||||
eprintln!("ignoring careless call to dc_add_address_book()");
|
||||
@@ -1390,7 +1387,7 @@ pub unsafe extern "C" fn dc_add_address_book(
|
||||
pub unsafe extern "C" fn dc_get_contacts(
|
||||
context: *mut dc_context_t,
|
||||
flags: u32,
|
||||
query: *const libc::c_char,
|
||||
query: *mut libc::c_char,
|
||||
) -> *mut dc_array::dc_array_t {
|
||||
if context.is_null() {
|
||||
eprintln!("ignoring careless call to dc_get_contacts()");
|
||||
@@ -1521,31 +1518,23 @@ pub unsafe extern "C" fn dc_get_contact(
|
||||
pub unsafe extern "C" fn dc_imex(
|
||||
context: *mut dc_context_t,
|
||||
what: libc::c_int,
|
||||
param1: *const libc::c_char,
|
||||
_param2: *const libc::c_char,
|
||||
param1: *mut libc::c_char,
|
||||
param2: *mut libc::c_char,
|
||||
) {
|
||||
if context.is_null() {
|
||||
eprintln!("ignoring careless call to dc_imex()");
|
||||
return;
|
||||
}
|
||||
let what = match imex::ImexMode::from_i32(what as i32) {
|
||||
Some(what) => what,
|
||||
None => {
|
||||
eprintln!("ignoring invalid argument {} to dc_imex", what);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let ffi_context = &*context;
|
||||
ffi_context
|
||||
.with_inner(|ctx| imex::imex(ctx, what, as_opt_str(param1)))
|
||||
.with_inner(|ctx| dc_imex::dc_imex(ctx, what, as_opt_str(param1), param2))
|
||||
.ok();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_imex_has_backup(
|
||||
context: *mut dc_context_t,
|
||||
dir: *const libc::c_char,
|
||||
dir: *mut libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
if context.is_null() || dir.is_null() {
|
||||
eprintln!("ignoring careless call to dc_imex_has_backup()");
|
||||
@@ -1553,13 +1542,7 @@ pub unsafe extern "C" fn dc_imex_has_backup(
|
||||
}
|
||||
let ffi_context = &*context;
|
||||
ffi_context
|
||||
.with_inner(|ctx| match imex::has_backup(ctx, as_str(dir)) {
|
||||
Ok(res) => res.strdup(),
|
||||
Err(err) => {
|
||||
error!(ctx, "dc_imex_has_backup: {}", err);
|
||||
ptr::null_mut()
|
||||
}
|
||||
})
|
||||
.with_inner(|ctx| dc_imex::dc_imex_has_backup(ctx, as_str(dir)))
|
||||
.unwrap_or_else(|_| ptr::null_mut())
|
||||
}
|
||||
|
||||
@@ -1571,13 +1554,7 @@ pub unsafe extern "C" fn dc_initiate_key_transfer(context: *mut dc_context_t) ->
|
||||
}
|
||||
let ffi_context = &*context;
|
||||
ffi_context
|
||||
.with_inner(|ctx| match imex::initiate_key_transfer(ctx) {
|
||||
Ok(res) => res.strdup(),
|
||||
Err(err) => {
|
||||
error!(ctx, "dc_initiate_key_transfer(): {}", err);
|
||||
ptr::null_mut()
|
||||
}
|
||||
})
|
||||
.with_inner(|ctx| dc_imex::dc_initiate_key_transfer(ctx))
|
||||
.unwrap_or_else(|_| ptr::null_mut())
|
||||
}
|
||||
|
||||
@@ -1585,7 +1562,7 @@ pub unsafe extern "C" fn dc_initiate_key_transfer(context: *mut dc_context_t) ->
|
||||
pub unsafe extern "C" fn dc_continue_key_transfer(
|
||||
context: *mut dc_context_t,
|
||||
msg_id: u32,
|
||||
setup_code: *const libc::c_char,
|
||||
setup_code: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
if context.is_null()
|
||||
|| msg_id <= constants::DC_MSG_ID_LAST_SPECIAL as u32
|
||||
@@ -1596,15 +1573,7 @@ pub unsafe extern "C" fn dc_continue_key_transfer(
|
||||
}
|
||||
let ffi_context = &*context;
|
||||
ffi_context
|
||||
.with_inner(
|
||||
|ctx| match imex::continue_key_transfer(ctx, msg_id, as_str(setup_code)) {
|
||||
Ok(()) => 1,
|
||||
Err(err) => {
|
||||
error!(ctx, "dc_continue_key_transfer: {}", err);
|
||||
0
|
||||
}
|
||||
},
|
||||
)
|
||||
.with_inner(|ctx| dc_imex::dc_continue_key_transfer(ctx, msg_id, setup_code) as libc::c_int)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
@@ -1623,7 +1592,7 @@ pub unsafe extern "C" fn dc_stop_ongoing_process(context: *mut dc_context_t) {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_check_qr(
|
||||
context: *mut dc_context_t,
|
||||
qr: *const libc::c_char,
|
||||
qr: *mut libc::c_char,
|
||||
) -> *mut dc_lot_t {
|
||||
if context.is_null() || qr.is_null() {
|
||||
eprintln!("ignoring careless call to dc_check_qr()");
|
||||
@@ -1660,7 +1629,7 @@ pub unsafe extern "C" fn dc_get_securejoin_qr(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_join_securejoin(
|
||||
context: *mut dc_context_t,
|
||||
qr: *const libc::c_char,
|
||||
qr: *mut libc::c_char,
|
||||
) -> u32 {
|
||||
if context.is_null() || qr.is_null() {
|
||||
eprintln!("ignoring careless call to dc_join_securejoin()");
|
||||
@@ -2376,11 +2345,7 @@ pub unsafe extern "C" fn dc_msg_get_filemime(msg: *mut dc_msg_t) -> *mut libc::c
|
||||
return dc_strdup(ptr::null());
|
||||
}
|
||||
let ffi_msg = &*msg;
|
||||
if let Some(x) = ffi_msg.message.get_filemime() {
|
||||
x.strdup()
|
||||
} else {
|
||||
return dc_strdup(ptr::null());
|
||||
}
|
||||
ffi_msg.message.get_filemime().strdup()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -2577,7 +2542,7 @@ pub unsafe extern "C" fn dc_msg_get_setupcodebegin(msg: *mut dc_msg_t) -> *mut l
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_set_text(msg: *mut dc_msg_t, text: *const libc::c_char) {
|
||||
pub unsafe extern "C" fn dc_msg_set_text(msg: *mut dc_msg_t, text: *mut libc::c_char) {
|
||||
if msg.is_null() {
|
||||
eprintln!("ignoring careless call to dc_msg_set_text()");
|
||||
return;
|
||||
@@ -2590,8 +2555,8 @@ pub unsafe extern "C" fn dc_msg_set_text(msg: *mut dc_msg_t, text: *const libc::
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_set_file(
|
||||
msg: *mut dc_msg_t,
|
||||
file: *const libc::c_char,
|
||||
filemime: *const libc::c_char,
|
||||
file: *mut libc::c_char,
|
||||
filemime: *mut libc::c_char,
|
||||
) {
|
||||
if msg.is_null() || file.is_null() {
|
||||
eprintln!("ignoring careless call to dc_msg_set_file()");
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
extern crate deltachat_provider_database;
|
||||
extern crate deltachat_provider_overview;
|
||||
|
||||
use std::ptr;
|
||||
|
||||
use deltachat::dc_tools::{as_str, StrExt};
|
||||
use deltachat_provider_database::StatusState;
|
||||
use deltachat_provider_overview::StatusState;
|
||||
|
||||
#[no_mangle]
|
||||
pub type dc_provider_t = deltachat_provider_database::Provider;
|
||||
pub type dc_provider_t = deltachat_provider_overview::Provider;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_provider_new_from_domain(
|
||||
domain: *const libc::c_char,
|
||||
) -> *const dc_provider_t {
|
||||
match deltachat_provider_database::get_provider_info(as_str(domain)) {
|
||||
match deltachat_provider_overview::get_provider_info(as_str(domain)) {
|
||||
Some(provider) => provider,
|
||||
None => ptr::null(),
|
||||
}
|
||||
@@ -22,8 +22,8 @@ pub unsafe extern "C" fn dc_provider_new_from_domain(
|
||||
pub unsafe extern "C" fn dc_provider_new_from_email(
|
||||
email: *const libc::c_char,
|
||||
) -> *const dc_provider_t {
|
||||
let domain = deltachat_provider_database::get_domain_from_email(as_str(email));
|
||||
match deltachat_provider_database::get_provider_info(domain) {
|
||||
let domain = deltachat_provider_overview::get_domain_from_email(as_str(email));
|
||||
match deltachat_provider_overview::get_provider_info(domain) {
|
||||
Some(provider) => provider,
|
||||
None => ptr::null(),
|
||||
}
|
||||
@@ -44,7 +44,7 @@ pub unsafe extern "C" fn dc_provider_get_overview_page(
|
||||
null_guard!(provider);
|
||||
format!(
|
||||
"{}/{}",
|
||||
deltachat_provider_database::PROVIDER_OVERVIEW_URL,
|
||||
deltachat_provider_overview::PROVIDER_OVERVIEW_URL,
|
||||
(*provider).overview_page
|
||||
)
|
||||
.strdup()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use deltachat::chat::{self, Chat};
|
||||
@@ -8,10 +9,10 @@ use deltachat::configure::*;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::contact::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_imex::*;
|
||||
use deltachat::dc_receive_imf::*;
|
||||
use deltachat::dc_tools::*;
|
||||
use deltachat::error::Error;
|
||||
use deltachat::imex::*;
|
||||
use deltachat::job::*;
|
||||
use deltachat::location;
|
||||
use deltachat::lot::LotState;
|
||||
@@ -96,13 +97,22 @@ pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 {
|
||||
fn dc_poke_eml_file(context: &Context, filename: impl AsRef<Path>) -> Result<(), Error> {
|
||||
let data = dc_read_file(context, filename)?;
|
||||
|
||||
unsafe { dc_receive_imf(context, &data, "import", 0, 0) };
|
||||
unsafe {
|
||||
dc_receive_imf(
|
||||
context,
|
||||
data.as_ptr() as *const _,
|
||||
data.len(),
|
||||
"import",
|
||||
0,
|
||||
0,
|
||||
)
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Import a file to the database.
|
||||
/// For testing, import a folder with eml-files, a single eml-file, e-mail plus public key and so on.
|
||||
/// For normal importing, use imex().
|
||||
/// For normal importing, use dc_imex().
|
||||
///
|
||||
/// @private @memberof Context
|
||||
/// @param context The context as created by dc_context_new().
|
||||
@@ -317,8 +327,12 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
arg1.strdup() as *const _
|
||||
};
|
||||
let arg2 = args.next().unwrap_or_default();
|
||||
let arg2_c = if arg2.is_empty() {
|
||||
std::ptr::null()
|
||||
} else {
|
||||
arg2.strdup() as *const _
|
||||
};
|
||||
|
||||
let blobdir = context.get_blobdir();
|
||||
match arg0 {
|
||||
"help" | "?" => match arg1 {
|
||||
// TODO: reuse commands definition in main.rs.
|
||||
@@ -405,13 +419,18 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
============================================="
|
||||
),
|
||||
},
|
||||
"initiate-key-transfer" => match initiate_key_transfer(context) {
|
||||
Ok(setup_code) => println!(
|
||||
"Setup code for the transferred setup message: {}",
|
||||
setup_code,
|
||||
),
|
||||
Err(err) => bail!("Failed to generate setup code: {}", err),
|
||||
},
|
||||
"initiate-key-transfer" => {
|
||||
let setup_code = dc_initiate_key_transfer(context);
|
||||
if !setup_code.is_null() {
|
||||
println!(
|
||||
"Setup code for the transferred setup message: {}",
|
||||
as_str(setup_code),
|
||||
);
|
||||
free(setup_code as *mut libc::c_void);
|
||||
} else {
|
||||
bail!("Failed to generate setup code");
|
||||
};
|
||||
}
|
||||
"get-setupcodebegin" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <msg-id> missing.");
|
||||
let msg_id: u32 = arg1.parse()?;
|
||||
@@ -432,28 +451,33 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
!arg1.is_empty() && !arg2.is_empty(),
|
||||
"Arguments <msg-id> <setup-code> expected"
|
||||
);
|
||||
continue_key_transfer(context, arg1.parse()?, &arg2)?;
|
||||
if !dc_continue_key_transfer(context, arg1.parse()?, arg2_c) {
|
||||
bail!("Continue key transfer failed");
|
||||
}
|
||||
}
|
||||
"has-backup" => {
|
||||
has_backup(context, blobdir)?;
|
||||
let ret = dc_imex_has_backup(context, context.get_blobdir());
|
||||
if ret.is_null() {
|
||||
println!("No backup found.");
|
||||
}
|
||||
}
|
||||
"export-backup" => {
|
||||
imex(context, ImexMode::ExportBackup, Some(blobdir));
|
||||
dc_imex(context, 11, Some(context.get_blobdir()), ptr::null());
|
||||
}
|
||||
"import-backup" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <backup-file> missing.");
|
||||
imex(context, ImexMode::ImportBackup, Some(arg1));
|
||||
dc_imex(context, 12, Some(arg1), ptr::null());
|
||||
}
|
||||
"export-keys" => {
|
||||
imex(context, ImexMode::ExportSelfKeys, Some(blobdir));
|
||||
dc_imex(context, 1, Some(context.get_blobdir()), ptr::null());
|
||||
}
|
||||
"import-keys" => {
|
||||
imex(context, ImexMode::ImportSelfKeys, Some(blobdir));
|
||||
dc_imex(context, 2, Some(context.get_blobdir()), ptr::null());
|
||||
}
|
||||
"export-setup" => {
|
||||
let setup_code = create_setup_code(context);
|
||||
let file_name = blobdir.join("autocrypt-setup-message.html");
|
||||
let file_content = render_setup_file(context, &setup_code)?;
|
||||
let setup_code = dc_create_setup_code(context);
|
||||
let file_name = context.get_blobdir().join("autocrypt-setup-message.html");
|
||||
let file_content = dc_render_setup_file(context, &setup_code)?;
|
||||
std::fs::write(&file_name, file_content)?;
|
||||
println!(
|
||||
"Setup message written to: {}\nSetup code: {}",
|
||||
@@ -977,6 +1001,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
}
|
||||
|
||||
free(arg1_c as *mut _);
|
||||
free(arg2_c as *mut _);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
pub const MAIL_ERROR_SSL: libc::c_uint = 58;
|
||||
pub const MAIL_ERROR_FOLDER: libc::c_uint = 57;
|
||||
pub const MAIL_ERROR_UNABLE: libc::c_uint = 56;
|
||||
pub const MAIL_ERROR_SYSTEM: libc::c_uint = 55;
|
||||
pub const MAIL_ERROR_COMMAND: libc::c_uint = 54;
|
||||
pub const MAIL_ERROR_SEND: libc::c_uint = 53;
|
||||
pub const MAIL_ERROR_CHAR_ENCODING_FAILED: libc::c_uint = 52;
|
||||
pub const MAIL_ERROR_SUBJECT_NOT_FOUND: libc::c_uint = 51;
|
||||
/* 50 */
|
||||
pub const MAIL_ERROR_PROGRAM_ERROR: libc::c_uint = 50;
|
||||
pub const MAIL_ERROR_NO_PERMISSION: libc::c_uint = 49;
|
||||
pub const MAIL_ERROR_COMMAND_NOT_SUPPORTED: libc::c_uint = 48;
|
||||
pub const MAIL_ERROR_NO_APOP: libc::c_uint = 47;
|
||||
pub const MAIL_ERROR_READONLY: libc::c_uint = 46;
|
||||
pub const MAIL_ERROR_FATAL: libc::c_uint = 45;
|
||||
pub const MAIL_ERROR_CLOSE: libc::c_uint = 44;
|
||||
pub const MAIL_ERROR_CAPABILITY: libc::c_uint = 43;
|
||||
pub const MAIL_ERROR_PROTOCOL: libc::c_uint = 42;
|
||||
/* misc errors */
|
||||
pub const MAIL_ERROR_MISC: libc::c_uint = 41;
|
||||
/* 40 */
|
||||
pub const MAIL_ERROR_EXPUNGE: libc::c_uint = 40;
|
||||
pub const MAIL_ERROR_NO_TLS: libc::c_uint = 39;
|
||||
pub const MAIL_ERROR_CACHE_MISS: libc::c_uint = 38;
|
||||
pub const MAIL_ERROR_STARTTLS: libc::c_uint = 37;
|
||||
pub const MAIL_ERROR_MOVE: libc::c_uint = 36;
|
||||
pub const MAIL_ERROR_FOLDER_NOT_FOUND: libc::c_uint = 35;
|
||||
pub const MAIL_ERROR_REMOVE: libc::c_uint = 34;
|
||||
pub const MAIL_ERROR_PART_NOT_FOUND: libc::c_uint = 33;
|
||||
pub const MAIL_ERROR_INVAL: libc::c_uint = 32;
|
||||
pub const MAIL_ERROR_PARSE: libc::c_uint = 31;
|
||||
/* 30 */
|
||||
pub const MAIL_ERROR_MSG_NOT_FOUND: libc::c_uint = 30;
|
||||
pub const MAIL_ERROR_DISKSPACE: libc::c_uint = 29;
|
||||
pub const MAIL_ERROR_SEARCH: libc::c_uint = 28;
|
||||
pub const MAIL_ERROR_STORE: libc::c_uint = 27;
|
||||
pub const MAIL_ERROR_FETCH: libc::c_uint = 26;
|
||||
pub const MAIL_ERROR_COPY: libc::c_uint = 25;
|
||||
pub const MAIL_ERROR_APPEND: libc::c_uint = 24;
|
||||
pub const MAIL_ERROR_LSUB: libc::c_uint = 23;
|
||||
pub const MAIL_ERROR_LIST: libc::c_uint = 22;
|
||||
pub const MAIL_ERROR_UNSUBSCRIBE: libc::c_uint = 21;
|
||||
/* 20 */
|
||||
pub const MAIL_ERROR_SUBSCRIBE: libc::c_uint = 20;
|
||||
pub const MAIL_ERROR_STATUS: libc::c_uint = 19;
|
||||
pub const MAIL_ERROR_MEMORY: libc::c_uint = 18;
|
||||
pub const MAIL_ERROR_SELECT: libc::c_uint = 17;
|
||||
pub const MAIL_ERROR_EXAMINE: libc::c_uint = 16;
|
||||
pub const MAIL_ERROR_CHECK: libc::c_uint = 15;
|
||||
pub const MAIL_ERROR_RENAME: libc::c_uint = 14;
|
||||
pub const MAIL_ERROR_NOOP: libc::c_uint = 13;
|
||||
pub const MAIL_ERROR_LOGOUT: libc::c_uint = 12;
|
||||
pub const MAIL_ERROR_DELETE: libc::c_uint = 11;
|
||||
/* 10 */
|
||||
pub const MAIL_ERROR_CREATE: libc::c_uint = 10;
|
||||
pub const MAIL_ERROR_LOGIN: libc::c_uint = 9;
|
||||
pub const MAIL_ERROR_STREAM: libc::c_uint = 8;
|
||||
pub const MAIL_ERROR_FILE: libc::c_uint = 7;
|
||||
pub const MAIL_ERROR_BAD_STATE: libc::c_uint = 6;
|
||||
pub const MAIL_ERROR_CONNECT: libc::c_uint = 5;
|
||||
pub const MAIL_ERROR_UNKNOWN: libc::c_uint = 4;
|
||||
pub const MAIL_ERROR_NOT_IMPLEMENTED: libc::c_uint = 3;
|
||||
pub const MAIL_NO_ERROR_NON_AUTHENTICATED: libc::c_uint = 2;
|
||||
pub const MAIL_NO_ERROR_AUTHENTICATED: libc::c_uint = 1;
|
||||
pub const MAIL_NO_ERROR: libc::c_uint = 0;
|
||||
|
||||
pub const MAILIMF_ERROR_FILE: libc::c_uint = 4;
|
||||
pub const MAILIMF_ERROR_INVAL: libc::c_uint = 3;
|
||||
pub const MAILIMF_ERROR_MEMORY: libc::c_uint = 2;
|
||||
pub const MAILIMF_ERROR_PARSE: libc::c_uint = 1;
|
||||
pub const MAILIMF_NO_ERROR: libc::c_uint = 0;
|
||||
@@ -1,386 +0,0 @@
|
||||
use crate::clist::*;
|
||||
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailmime::types::*;
|
||||
|
||||
use std::ffi::CStr;
|
||||
|
||||
pub unsafe fn display_mime(mut mime: *mut Mailmime) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
println!("{}", (*mime).mm_type);
|
||||
|
||||
match (*mime).mm_type as u32 {
|
||||
MAILMIME_SINGLE => {
|
||||
println!("single part");
|
||||
}
|
||||
MAILMIME_MULTIPLE => {
|
||||
println!("multipart");
|
||||
}
|
||||
MAILMIME_MESSAGE => println!("message"),
|
||||
_ => {}
|
||||
}
|
||||
if !(*mime).mm_mime_fields.is_null() {
|
||||
if !(*(*(*mime).mm_mime_fields).fld_list).first.is_null() {
|
||||
print!("MIME headers begin");
|
||||
display_mime_fields((*mime).mm_mime_fields);
|
||||
println!("MIME headers end");
|
||||
}
|
||||
}
|
||||
display_mime_content((*mime).mm_content_type);
|
||||
match (*mime).mm_type as u32 {
|
||||
MAILMIME_SINGLE => {
|
||||
display_mime_data((*mime).mm_data.mm_single);
|
||||
}
|
||||
MAILMIME_MULTIPLE => {
|
||||
cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
|
||||
while !cur.is_null() {
|
||||
display_mime(
|
||||
(if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut Mailmime,
|
||||
);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
MAILMIME_MESSAGE => {
|
||||
if !(*mime).mm_data.mm_message.mm_fields.is_null() {
|
||||
if !(*(*(*mime).mm_data.mm_message.mm_fields).fld_list)
|
||||
.first
|
||||
.is_null()
|
||||
{
|
||||
println!("headers begin");
|
||||
display_fields((*mime).mm_data.mm_message.mm_fields);
|
||||
println!("headers end");
|
||||
}
|
||||
if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() {
|
||||
display_mime((*mime).mm_data.mm_message.mm_msg_mime);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
unsafe fn display_mime_content(mut content_type: *mut mailmime_content) {
|
||||
print!("type: ");
|
||||
display_mime_type((*content_type).ct_type);
|
||||
println!(
|
||||
"/{}",
|
||||
CStr::from_ptr((*content_type).ct_subtype).to_str().unwrap()
|
||||
);
|
||||
}
|
||||
unsafe fn display_mime_type(mut type_0: *mut mailmime_type) {
|
||||
match (*type_0).tp_type {
|
||||
1 => {
|
||||
display_mime_discrete_type((*type_0).tp_data.tp_discrete_type);
|
||||
}
|
||||
2 => {
|
||||
display_mime_composite_type((*type_0).tp_data.tp_composite_type);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_composite_type(mut ct: *mut mailmime_composite_type) {
|
||||
match (*ct).ct_type {
|
||||
1 => {
|
||||
print!("message");
|
||||
}
|
||||
2 => {
|
||||
print!("multipart");
|
||||
}
|
||||
3 => {
|
||||
print!("{}", CStr::from_ptr((*ct).ct_token).to_str().unwrap());
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_discrete_type(mut discrete_type: *mut mailmime_discrete_type) {
|
||||
match (*discrete_type).dt_type {
|
||||
1 => {
|
||||
print!("text");
|
||||
}
|
||||
2 => {
|
||||
print!("image");
|
||||
}
|
||||
3 => {
|
||||
print!("audio");
|
||||
}
|
||||
4 => {
|
||||
print!("video");
|
||||
}
|
||||
5 => {
|
||||
print!("application");
|
||||
}
|
||||
6 => {
|
||||
print!("{}", (*discrete_type).dt_extension as u8 as char);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_data(mut data: *mut mailmime_data) {
|
||||
match (*data).dt_type {
|
||||
0 => {
|
||||
println!(
|
||||
"data : {} bytes",
|
||||
(*data).dt_data.dt_text.dt_length as libc::c_uint,
|
||||
);
|
||||
}
|
||||
1 => {
|
||||
println!(
|
||||
"data (file) : {}",
|
||||
CStr::from_ptr((*data).dt_data.dt_filename)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_dsp_parm(mut param: *mut mailmime_disposition_parm) {
|
||||
match (*param).pa_type {
|
||||
0 => {
|
||||
println!(
|
||||
"filename: {}",
|
||||
CStr::from_ptr((*param).pa_data.pa_filename)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_disposition(mut disposition: *mut mailmime_disposition) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*disposition).dsp_parms).first;
|
||||
while !cur.is_null() {
|
||||
let mut param: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm;
|
||||
param = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailmime_disposition_parm;
|
||||
display_mime_dsp_parm(param);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn display_mime_field(mut field: *mut mailmime_field) {
|
||||
match (*field).fld_type {
|
||||
1 => {
|
||||
print!("content-type: ");
|
||||
display_mime_content((*field).fld_data.fld_content);
|
||||
println!("");
|
||||
}
|
||||
6 => {
|
||||
display_mime_disposition((*field).fld_data.fld_disposition);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_fields(mut fields: *mut mailmime_fields) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut field: *mut mailmime_field = 0 as *mut mailmime_field;
|
||||
field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailmime_field;
|
||||
display_mime_field(field);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn display_date_time(mut d: *mut mailimf_date_time) {
|
||||
print!(
|
||||
"{:02}/{:02}/{:02} {:02}:{:02}:{:02} +{:04}",
|
||||
(*d).dt_day,
|
||||
(*d).dt_month,
|
||||
(*d).dt_year,
|
||||
(*d).dt_hour,
|
||||
(*d).dt_min,
|
||||
(*d).dt_sec,
|
||||
(*d).dt_zone,
|
||||
);
|
||||
}
|
||||
unsafe fn display_orig_date(mut orig_date: *mut mailimf_orig_date) {
|
||||
display_date_time((*orig_date).dt_date_time);
|
||||
}
|
||||
unsafe fn display_mailbox(mut mb: *mut mailimf_mailbox) {
|
||||
if !(*mb).mb_display_name.is_null() {
|
||||
print!(
|
||||
"{}",
|
||||
CStr::from_ptr((*mb).mb_display_name).to_str().unwrap()
|
||||
);
|
||||
}
|
||||
print!("<{}>", CStr::from_ptr((*mb).mb_addr_spec).to_str().unwrap());
|
||||
}
|
||||
unsafe fn display_mailbox_list(mut mb_list: *mut mailimf_mailbox_list) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*mb_list).mb_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox;
|
||||
mb = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_mailbox;
|
||||
display_mailbox(mb);
|
||||
if !if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
.is_null()
|
||||
{
|
||||
print!(", ");
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn display_group(mut group: *mut mailimf_group) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
print!(
|
||||
"{}: ",
|
||||
CStr::from_ptr((*group).grp_display_name).to_str().unwrap()
|
||||
);
|
||||
cur = (*(*(*group).grp_mb_list).mb_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox;
|
||||
mb = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_mailbox;
|
||||
display_mailbox(mb);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
print!("; ");
|
||||
}
|
||||
unsafe fn display_address(mut a: *mut mailimf_address) {
|
||||
match (*a).ad_type {
|
||||
2 => {
|
||||
display_group((*a).ad_data.ad_group);
|
||||
}
|
||||
1 => {
|
||||
display_mailbox((*a).ad_data.ad_mailbox);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_address_list(mut addr_list: *mut mailimf_address_list) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*addr_list).ad_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut addr: *mut mailimf_address = 0 as *mut mailimf_address;
|
||||
addr = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_address;
|
||||
display_address(addr);
|
||||
if !if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
.is_null()
|
||||
{
|
||||
print!(", ");
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn display_from(mut from: *mut mailimf_from) {
|
||||
display_mailbox_list((*from).frm_mb_list);
|
||||
}
|
||||
unsafe fn display_to(mut to: *mut mailimf_to) {
|
||||
display_address_list((*to).to_addr_list);
|
||||
}
|
||||
unsafe fn display_cc(mut cc: *mut mailimf_cc) {
|
||||
display_address_list((*cc).cc_addr_list);
|
||||
}
|
||||
unsafe fn display_subject(mut subject: *mut mailimf_subject) {
|
||||
print!("{}", CStr::from_ptr((*subject).sbj_value).to_str().unwrap());
|
||||
}
|
||||
unsafe fn display_field(mut field: *mut mailimf_field) {
|
||||
match (*field).fld_type {
|
||||
9 => {
|
||||
print!("Date: ");
|
||||
display_orig_date((*field).fld_data.fld_orig_date);
|
||||
println!("");
|
||||
}
|
||||
10 => {
|
||||
print!("From: ");
|
||||
display_from((*field).fld_data.fld_from);
|
||||
println!("");
|
||||
}
|
||||
13 => {
|
||||
print!("To: ");
|
||||
display_to((*field).fld_data.fld_to);
|
||||
println!("");
|
||||
}
|
||||
14 => {
|
||||
print!("Cc: ");
|
||||
display_cc((*field).fld_data.fld_cc);
|
||||
println!("");
|
||||
}
|
||||
19 => {
|
||||
print!("Subject: ");
|
||||
display_subject((*field).fld_data.fld_subject);
|
||||
println!("");
|
||||
}
|
||||
16 => {
|
||||
println!(
|
||||
"Message-ID: {}",
|
||||
CStr::from_ptr((*(*field).fld_data.fld_message_id).mid_value)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_fields(mut fields: *mut mailimf_fields) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut f: *mut mailimf_field = 0 as *mut mailimf_field;
|
||||
f = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_field;
|
||||
display_field(f);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
408
mmime/src/lib.rs
408
mmime/src/lib.rs
@@ -19,24 +19,44 @@
|
||||
pub mod charconv;
|
||||
pub mod chash;
|
||||
pub mod clist;
|
||||
pub mod display;
|
||||
pub mod mailimf;
|
||||
pub mod mailimf_types;
|
||||
pub mod mailimf_types_helper;
|
||||
pub mod mailimf_write_generic;
|
||||
pub mod mailmime;
|
||||
pub mod mailmime_content;
|
||||
pub mod mailmime_decode;
|
||||
pub mod mailmime_disposition;
|
||||
pub mod mailmime_types;
|
||||
pub mod mailmime_types_helper;
|
||||
pub mod mailmime_write_generic;
|
||||
pub mod mailmime_write_mem;
|
||||
pub mod mmapstring;
|
||||
pub mod other;
|
||||
|
||||
pub use self::charconv::*;
|
||||
pub use self::chash::*;
|
||||
pub use self::clist::*;
|
||||
pub use self::display::*;
|
||||
pub use self::mailimf::*;
|
||||
pub use self::mailimf_types::*;
|
||||
pub use self::mailimf_types_helper::*;
|
||||
pub use self::mailimf_write_generic::*;
|
||||
pub use self::mailmime::*;
|
||||
pub use self::mailmime_content::*;
|
||||
pub use self::mailmime_decode::*;
|
||||
pub use self::mailmime_disposition::*;
|
||||
pub use self::mailmime_types::*;
|
||||
pub use self::mailmime_types_helper::*;
|
||||
pub use self::mailmime_write_generic::*;
|
||||
pub use self::mailmime_write_mem::*;
|
||||
pub use self::mmapstring::*;
|
||||
pub use self::other::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mailmime_types::{mailmime, mailmime_content, mailmime_disposition};
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[test]
|
||||
fn mailmime_parse_test() {
|
||||
@@ -60,7 +80,7 @@ mod tests {
|
||||
|
||||
let mut current_index = 0;
|
||||
let mut mime = std::ptr::null_mut();
|
||||
let res = crate::mailmime::content::mailmime_parse(
|
||||
let res = crate::mailmime_content::mailmime_parse(
|
||||
c_data.as_ptr(),
|
||||
data.len() as usize,
|
||||
&mut current_index,
|
||||
@@ -72,7 +92,387 @@ mod tests {
|
||||
|
||||
display_mime(mime);
|
||||
|
||||
mailmime::types::mailmime_free(mime);
|
||||
mailmime_types::mailmime_free(mime);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn display_mime(mut mime: *mut mailmime) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
println!("{}", (*mime).mm_type);
|
||||
|
||||
match (*mime).mm_type {
|
||||
1 => {
|
||||
println!("single part");
|
||||
}
|
||||
2 => {
|
||||
println!("multipart");
|
||||
}
|
||||
3 => println!("message"),
|
||||
_ => {}
|
||||
}
|
||||
if !(*mime).mm_mime_fields.is_null() {
|
||||
if !(*(*(*mime).mm_mime_fields).fld_list).first.is_null() {
|
||||
print!("MIME headers begin");
|
||||
display_mime_fields((*mime).mm_mime_fields);
|
||||
println!("MIME headers end");
|
||||
}
|
||||
}
|
||||
display_mime_content((*mime).mm_content_type);
|
||||
match (*mime).mm_type {
|
||||
1 => {
|
||||
display_mime_data((*mime).mm_data.mm_single);
|
||||
}
|
||||
2 => {
|
||||
cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
|
||||
while !cur.is_null() {
|
||||
display_mime(
|
||||
(if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailmime,
|
||||
);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
if !(*mime).mm_data.mm_message.mm_fields.is_null() {
|
||||
if !(*(*(*mime).mm_data.mm_message.mm_fields).fld_list)
|
||||
.first
|
||||
.is_null()
|
||||
{
|
||||
println!("headers begin");
|
||||
display_fields((*mime).mm_data.mm_message.mm_fields);
|
||||
println!("headers end");
|
||||
}
|
||||
if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() {
|
||||
display_mime((*mime).mm_data.mm_message.mm_msg_mime);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
unsafe fn display_mime_content(mut content_type: *mut mailmime_content) {
|
||||
print!("type: ");
|
||||
display_mime_type((*content_type).ct_type);
|
||||
println!(
|
||||
"/{}",
|
||||
CStr::from_ptr((*content_type).ct_subtype).to_str().unwrap()
|
||||
);
|
||||
}
|
||||
unsafe fn display_mime_type(mut type_0: *mut mailmime_type) {
|
||||
match (*type_0).tp_type {
|
||||
1 => {
|
||||
display_mime_discrete_type((*type_0).tp_data.tp_discrete_type);
|
||||
}
|
||||
2 => {
|
||||
display_mime_composite_type((*type_0).tp_data.tp_composite_type);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_composite_type(mut ct: *mut mailmime_composite_type) {
|
||||
match (*ct).ct_type {
|
||||
1 => {
|
||||
print!("message");
|
||||
}
|
||||
2 => {
|
||||
print!("multipart");
|
||||
}
|
||||
3 => {
|
||||
print!("{}", CStr::from_ptr((*ct).ct_token).to_str().unwrap());
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_discrete_type(mut discrete_type: *mut mailmime_discrete_type) {
|
||||
match (*discrete_type).dt_type {
|
||||
1 => {
|
||||
print!("text");
|
||||
}
|
||||
2 => {
|
||||
print!("image");
|
||||
}
|
||||
3 => {
|
||||
print!("audio");
|
||||
}
|
||||
4 => {
|
||||
print!("video");
|
||||
}
|
||||
5 => {
|
||||
print!("application");
|
||||
}
|
||||
6 => {
|
||||
print!("{}", (*discrete_type).dt_extension as u8 as char);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_data(mut data: *mut mailmime_data) {
|
||||
match (*data).dt_type {
|
||||
0 => {
|
||||
println!(
|
||||
"data : {} bytes",
|
||||
(*data).dt_data.dt_text.dt_length as libc::c_uint,
|
||||
);
|
||||
}
|
||||
1 => {
|
||||
println!(
|
||||
"data (file) : {}",
|
||||
CStr::from_ptr((*data).dt_data.dt_filename)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_dsp_parm(mut param: *mut mailmime_disposition_parm) {
|
||||
match (*param).pa_type {
|
||||
0 => {
|
||||
println!(
|
||||
"filename: {}",
|
||||
CStr::from_ptr((*param).pa_data.pa_filename)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_disposition(mut disposition: *mut mailmime_disposition) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*disposition).dsp_parms).first;
|
||||
while !cur.is_null() {
|
||||
let mut param: *mut mailmime_disposition_parm = 0 as *mut mailmime_disposition_parm;
|
||||
param = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailmime_disposition_parm;
|
||||
display_mime_dsp_parm(param);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn display_mime_field(mut field: *mut mailmime_field) {
|
||||
match (*field).fld_type {
|
||||
1 => {
|
||||
print!("content-type: ");
|
||||
display_mime_content((*field).fld_data.fld_content);
|
||||
println!("");
|
||||
}
|
||||
6 => {
|
||||
display_mime_disposition((*field).fld_data.fld_disposition);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_mime_fields(mut fields: *mut mailmime_fields) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut field: *mut mailmime_field = 0 as *mut mailmime_field;
|
||||
field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailmime_field;
|
||||
display_mime_field(field);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn display_date_time(mut d: *mut mailimf_date_time) {
|
||||
print!(
|
||||
"{:02}/{:02}/{:02} {:02}:{:02}:{:02} +{:04}",
|
||||
(*d).dt_day,
|
||||
(*d).dt_month,
|
||||
(*d).dt_year,
|
||||
(*d).dt_hour,
|
||||
(*d).dt_min,
|
||||
(*d).dt_sec,
|
||||
(*d).dt_zone,
|
||||
);
|
||||
}
|
||||
unsafe fn display_orig_date(mut orig_date: *mut mailimf_orig_date) {
|
||||
display_date_time((*orig_date).dt_date_time);
|
||||
}
|
||||
unsafe fn display_mailbox(mut mb: *mut mailimf_mailbox) {
|
||||
if !(*mb).mb_display_name.is_null() {
|
||||
print!(
|
||||
"{}",
|
||||
CStr::from_ptr((*mb).mb_display_name).to_str().unwrap()
|
||||
);
|
||||
}
|
||||
print!("<{}>", CStr::from_ptr((*mb).mb_addr_spec).to_str().unwrap());
|
||||
}
|
||||
unsafe fn display_mailbox_list(mut mb_list: *mut mailimf_mailbox_list) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*mb_list).mb_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox;
|
||||
mb = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_mailbox;
|
||||
display_mailbox(mb);
|
||||
if !if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
.is_null()
|
||||
{
|
||||
print!(", ");
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn display_group(mut group: *mut mailimf_group) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
print!(
|
||||
"{}: ",
|
||||
CStr::from_ptr((*group).grp_display_name).to_str().unwrap()
|
||||
);
|
||||
cur = (*(*(*group).grp_mb_list).mb_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox;
|
||||
mb = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_mailbox;
|
||||
display_mailbox(mb);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
print!("; ");
|
||||
}
|
||||
unsafe fn display_address(mut a: *mut mailimf_address) {
|
||||
match (*a).ad_type {
|
||||
2 => {
|
||||
display_group((*a).ad_data.ad_group);
|
||||
}
|
||||
1 => {
|
||||
display_mailbox((*a).ad_data.ad_mailbox);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_address_list(mut addr_list: *mut mailimf_address_list) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*addr_list).ad_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut addr: *mut mailimf_address = 0 as *mut mailimf_address;
|
||||
addr = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_address;
|
||||
display_address(addr);
|
||||
if !if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
.is_null()
|
||||
{
|
||||
print!(", ");
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn display_from(mut from: *mut mailimf_from) {
|
||||
display_mailbox_list((*from).frm_mb_list);
|
||||
}
|
||||
unsafe fn display_to(mut to: *mut mailimf_to) {
|
||||
display_address_list((*to).to_addr_list);
|
||||
}
|
||||
unsafe fn display_cc(mut cc: *mut mailimf_cc) {
|
||||
display_address_list((*cc).cc_addr_list);
|
||||
}
|
||||
unsafe fn display_subject(mut subject: *mut mailimf_subject) {
|
||||
print!("{}", CStr::from_ptr((*subject).sbj_value).to_str().unwrap());
|
||||
}
|
||||
unsafe fn display_field(mut field: *mut mailimf_field) {
|
||||
match (*field).fld_type {
|
||||
9 => {
|
||||
print!("Date: ");
|
||||
display_orig_date((*field).fld_data.fld_orig_date);
|
||||
println!("");
|
||||
}
|
||||
10 => {
|
||||
print!("From: ");
|
||||
display_from((*field).fld_data.fld_from);
|
||||
println!("");
|
||||
}
|
||||
13 => {
|
||||
print!("To: ");
|
||||
display_to((*field).fld_data.fld_to);
|
||||
println!("");
|
||||
}
|
||||
14 => {
|
||||
print!("Cc: ");
|
||||
display_cc((*field).fld_data.fld_cc);
|
||||
println!("");
|
||||
}
|
||||
19 => {
|
||||
print!("Subject: ");
|
||||
display_subject((*field).fld_data.fld_subject);
|
||||
println!("");
|
||||
}
|
||||
16 => {
|
||||
println!(
|
||||
"Message-ID: {}",
|
||||
CStr::from_ptr((*(*field).fld_data.fld_message_id).mid_value)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
unsafe fn display_fields(mut fields: *mut mailimf_fields) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut f: *mut mailimf_field = 0 as *mut mailimf_field;
|
||||
f = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_field;
|
||||
display_field(f);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
pub mod types;
|
||||
pub mod types_helper;
|
||||
pub(crate) mod write_generic;
|
||||
|
||||
use libc::{self, toupper};
|
||||
use libc;
|
||||
use libc::toupper;
|
||||
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailmime::decode::*;
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailimf_types::*;
|
||||
use crate::mailmime_decode::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::mmapstring::*;
|
||||
use crate::other::*;
|
||||
|
||||
@@ -43,14 +43,15 @@ pub struct mailimf_date_time {
|
||||
pub dt_zone: libc::c_int,
|
||||
}
|
||||
/* this is the type of address */
|
||||
pub type unnamed = libc::c_uint;
|
||||
/* if this is a group
|
||||
(group_name: address1@domain1,
|
||||
address2@domain2; ) */
|
||||
pub const MAILIMF_ADDRESS_GROUP: libc::c_uint = 2;
|
||||
pub const MAILIMF_ADDRESS_GROUP: unnamed = 2;
|
||||
/* if this is a mailbox (mailbox@domain) */
|
||||
pub const MAILIMF_ADDRESS_MAILBOX: libc::c_uint = 1;
|
||||
pub const MAILIMF_ADDRESS_MAILBOX: unnamed = 1;
|
||||
/* on parse error */
|
||||
pub const MAILIMF_ADDRESS_ERROR: libc::c_uint = 0;
|
||||
pub const MAILIMF_ADDRESS_ERROR: unnamed = 0;
|
||||
/*
|
||||
mailimf_address is an address
|
||||
|
||||
@@ -888,7 +889,6 @@ pub unsafe fn mailimf_fields_new(mut fld_list: *mut clist) -> *mut mailimf_field
|
||||
(*fields).fld_list = fld_list;
|
||||
return fields;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn mailimf_field_new(
|
||||
mut fld_type: libc::c_int,
|
||||
@@ -948,20 +948,6 @@ pub unsafe fn mailimf_field_new(
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn mailimf_field_new_subject(fld_subject: *mut mailimf_subject) -> *mut mailimf_field {
|
||||
let mut field: *mut mailimf_field = 0 as *mut mailimf_field;
|
||||
field = malloc(::std::mem::size_of::<mailimf_field>() as libc::size_t) as *mut mailimf_field;
|
||||
if field.is_null() {
|
||||
return 0 as *mut mailimf_field;
|
||||
}
|
||||
(*field).fld_type = MAILIMF_FIELD_SUBJECT as libc::c_int;
|
||||
(*field).fld_data.fld_subject = fld_subject;
|
||||
|
||||
field
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn mailimf_orig_date_new(
|
||||
mut dt_date_time: *mut mailimf_date_time,
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailimf_types::*;
|
||||
use crate::other::*;
|
||||
|
||||
/*
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailimf_types::*;
|
||||
use crate::other::*;
|
||||
|
||||
pub const STATE_WORD: libc::c_uint = 1;
|
||||
@@ -1983,3 +1983,43 @@ unsafe fn mailimf_path_write_driver(
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
}
|
||||
/*
|
||||
mailimf_envelope_fields_write writes only some fields to a given stream
|
||||
|
||||
@param f is the stream
|
||||
@param col (* col) is the column number where we will start to
|
||||
write the text, the ending column will be stored in (* col)
|
||||
@param fields is the fields to write
|
||||
*/
|
||||
pub unsafe fn mailimf_envelope_fields_write_driver(
|
||||
mut do_write: Option<
|
||||
unsafe fn(_: *mut libc::c_void, _: *const libc::c_char, _: size_t) -> libc::c_int,
|
||||
>,
|
||||
mut data: *mut libc::c_void,
|
||||
mut col: *mut libc::c_int,
|
||||
mut fields: *mut mailimf_fields,
|
||||
) -> libc::c_int {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
cur = (*(*fields).fld_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut field: *mut mailimf_field = 0 as *mut mailimf_field;
|
||||
field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_field;
|
||||
if (*field).fld_type != MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
||||
r = mailimf_field_write_driver(do_write, data, col, field);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
}
|
||||
@@ -1,19 +1,13 @@
|
||||
pub mod content;
|
||||
pub mod decode;
|
||||
pub mod disposition;
|
||||
pub mod types;
|
||||
pub mod types_helper;
|
||||
pub(crate) mod write_generic;
|
||||
pub mod write_mem;
|
||||
use libc;
|
||||
|
||||
use libc::toupper;
|
||||
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailimf::*;
|
||||
use crate::mailmime::decode::*;
|
||||
use crate::mailmime::disposition::*;
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailimf_types::*;
|
||||
use crate::mailmime_decode::*;
|
||||
use crate::mailmime_disposition::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::other::*;
|
||||
|
||||
pub const MAILMIME_COMPOSITE_TYPE_EXTENSION: libc::c_uint = 3;
|
||||
@@ -1,9 +1,9 @@
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailimf::*;
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailmime::types_helper::*;
|
||||
use crate::mailimf_types::*;
|
||||
use crate::mailmime::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::mailmime_types_helper::*;
|
||||
use crate::mmapstring::*;
|
||||
use crate::other::*;
|
||||
|
||||
@@ -80,9 +80,9 @@ pub unsafe fn mailmime_parse(
|
||||
mut message: *const libc::c_char,
|
||||
mut length: size_t,
|
||||
mut indx: *mut size_t,
|
||||
mut result: *mut *mut Mailmime,
|
||||
mut result: *mut *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut mime: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut mime: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut res: libc::c_int = 0;
|
||||
let mut content_message: *mut mailmime_content = 0 as *mut mailmime_content;
|
||||
@@ -174,7 +174,7 @@ unsafe fn mailmime_parse_with_default(
|
||||
mut default_type: libc::c_int,
|
||||
mut content_type: *mut mailmime_content,
|
||||
mut mime_fields: *mut mailmime_fields,
|
||||
mut result: *mut *mut Mailmime,
|
||||
mut result: *mut *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut current_block: u64;
|
||||
let mut cur_token: size_t = 0;
|
||||
@@ -184,8 +184,8 @@ unsafe fn mailmime_parse_with_default(
|
||||
let mut boundary: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields;
|
||||
let mut list: *mut clist = 0 as *mut clist;
|
||||
let mut msg_mime: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut mime: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut msg_mime: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut mime: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut res: libc::c_int = 0;
|
||||
let mut preamble: *mut mailmime_data = 0 as *mut mailmime_data;
|
||||
@@ -312,7 +312,7 @@ unsafe fn mailmime_parse_with_default(
|
||||
res = MAILIMF_ERROR_MEMORY as libc::c_int
|
||||
} else {
|
||||
list = 0 as *mut clist;
|
||||
msg_mime = 0 as *mut Mailmime;
|
||||
msg_mime = 0 as *mut mailmime;
|
||||
fields = 0 as *mut mailimf_fields;
|
||||
match body_type {
|
||||
3 => {
|
||||
@@ -361,7 +361,7 @@ unsafe fn mailmime_parse_with_default(
|
||||
current_block = 12065775993741208975;
|
||||
} else if r == MAILIMF_ERROR_PARSE as libc::c_int {
|
||||
mailmime_fields_free(mime_fields);
|
||||
msg_mime = 0 as *mut Mailmime;
|
||||
msg_mime = 0 as *mut mailmime;
|
||||
current_block = 12065775993741208975;
|
||||
} else {
|
||||
mailmime_fields_free(mime_fields);
|
||||
@@ -456,7 +456,7 @@ unsafe fn mailmime_parse_with_default(
|
||||
clist_foreach(
|
||||
list,
|
||||
::std::mem::transmute::<
|
||||
Option<unsafe fn(_: *mut Mailmime) -> ()>,
|
||||
Option<unsafe fn(_: *mut mailmime) -> ()>,
|
||||
clist_func,
|
||||
>(Some(
|
||||
mailmime_free,
|
||||
@@ -605,7 +605,7 @@ unsafe fn mailmime_multipart_body_parse(
|
||||
break;
|
||||
}
|
||||
let mut bp_token: size_t = 0;
|
||||
let mut mime_bp: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut mime_bp: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut data_str: *const libc::c_char = 0 as *const libc::c_char;
|
||||
let mut data_size: size_t = 0;
|
||||
let mut fields: *mut mailimf_fields = 0 as *mut mailimf_fields;
|
||||
@@ -821,7 +821,7 @@ unsafe fn mailmime_multipart_body_parse(
|
||||
clist_foreach(
|
||||
list,
|
||||
::std::mem::transmute::<
|
||||
Option<unsafe fn(_: *mut Mailmime) -> ()>,
|
||||
Option<unsafe fn(_: *mut mailmime) -> ()>,
|
||||
clist_func,
|
||||
>(Some(mailmime_free)),
|
||||
0 as *mut libc::c_void,
|
||||
@@ -1344,20 +1344,20 @@ pub unsafe fn mailmime_extract_boundary(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_get_section(
|
||||
mut mime: *mut Mailmime,
|
||||
mut mime: *mut mailmime,
|
||||
mut section: *mut mailmime_section,
|
||||
mut result: *mut *mut Mailmime,
|
||||
mut result: *mut *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
return mailmime_get_section_list(mime, (*(*section).sec_list).first, result);
|
||||
}
|
||||
unsafe fn mailmime_get_section_list(
|
||||
mut mime: *mut Mailmime,
|
||||
mut mime: *mut mailmime,
|
||||
mut list: *mut clistiter,
|
||||
mut result: *mut *mut Mailmime,
|
||||
mut result: *mut *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut id: uint32_t = 0;
|
||||
let mut data: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut submime: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut data: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut submime: *mut mailmime = 0 as *mut mailmime;
|
||||
if list.is_null() {
|
||||
*result = mime;
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
@@ -1367,14 +1367,14 @@ unsafe fn mailmime_get_section_list(
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut uint32_t);
|
||||
data = 0 as *mut Mailmime;
|
||||
data = 0 as *mut mailmime;
|
||||
match (*mime).mm_type {
|
||||
1 => return MAILIMF_ERROR_INVAL as libc::c_int,
|
||||
2 => {
|
||||
data = clist_nth_data(
|
||||
(*mime).mm_data.mm_multipart.mm_mp_list,
|
||||
id.wrapping_sub(1i32 as libc::c_uint) as libc::c_int,
|
||||
) as *mut Mailmime;
|
||||
) as *mut mailmime;
|
||||
if data.is_null() {
|
||||
return MAILIMF_ERROR_INVAL as libc::c_int;
|
||||
}
|
||||
@@ -1406,7 +1406,7 @@ unsafe fn mailmime_get_section_list(
|
||||
data = clist_nth_data(
|
||||
(*submime).mm_data.mm_multipart.mm_mp_list,
|
||||
id.wrapping_sub(1i32 as libc::c_uint) as libc::c_int,
|
||||
) as *mut Mailmime;
|
||||
) as *mut mailmime;
|
||||
if data.is_null() {
|
||||
return MAILIMF_ERROR_INVAL as libc::c_int;
|
||||
}
|
||||
@@ -2147,7 +2147,7 @@ pub unsafe fn mailmime_part_parse_partial(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_get_section_id(
|
||||
mut mime: *mut Mailmime,
|
||||
mut mime: *mut mailmime,
|
||||
mut result: *mut *mut mailmime_section,
|
||||
) -> libc::c_int {
|
||||
let mut current_block: u64;
|
||||
@@ -2173,7 +2173,7 @@ pub unsafe fn mailmime_get_section_id(
|
||||
let mut id: uint32_t = 0;
|
||||
let mut p_id: *mut uint32_t = 0 as *mut uint32_t;
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
let mut parent: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut parent: *mut mailmime = 0 as *mut mailmime;
|
||||
r = mailmime_get_section_id((*mime).mm_parent, &mut section_id);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int {
|
||||
res = r;
|
||||
@@ -3,11 +3,14 @@ use libc::toupper;
|
||||
|
||||
use crate::charconv::*;
|
||||
use crate::mailimf::*;
|
||||
use crate::mailmime::content::*;
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailmime_content::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::mmapstring::*;
|
||||
use crate::other::*;
|
||||
|
||||
pub const MAIL_CHARCONV_ERROR_CONV: libc::c_uint = 3;
|
||||
pub const MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: libc::c_uint = 1;
|
||||
pub const MAIL_CHARCONV_ERROR_MEMORY: libc::c_uint = 2;
|
||||
pub const TYPE_WORD: libc::c_uint = 1;
|
||||
pub const TYPE_ENCODED_WORD: libc::c_uint = 2;
|
||||
pub const MAILMIME_ENCODING_Q: libc::c_uint = 1;
|
||||
@@ -847,7 +850,7 @@ unsafe fn mailmime_etoken_parse(
|
||||
return mailimf_custom_string_parse(message, length, indx, result, Some(is_etoken_char));
|
||||
}
|
||||
|
||||
unsafe fn is_etoken_char(mut ch: libc::c_char) -> libc::c_int {
|
||||
pub unsafe fn is_etoken_char(mut ch: libc::c_char) -> libc::c_int {
|
||||
let mut uch: libc::c_uchar = ch as libc::c_uchar;
|
||||
if (uch as libc::c_int) < 31i32 {
|
||||
return 0i32;
|
||||
@@ -1,9 +1,10 @@
|
||||
use libc::{self, toupper};
|
||||
use libc;
|
||||
use libc::toupper;
|
||||
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::*;
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailmime::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::other::*;
|
||||
|
||||
pub const MAILMIME_DISPOSITION_TYPE_EXTENSION: libc::c_uint = 3;
|
||||
@@ -1,5 +1,7 @@
|
||||
use libc;
|
||||
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailimf_types::*;
|
||||
use crate::mmapstring::*;
|
||||
use crate::other::*;
|
||||
|
||||
@@ -162,9 +164,9 @@ pub const MAILMIME_NONE: unnamed_7 = 0;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct Mailmime {
|
||||
pub struct mailmime {
|
||||
pub mm_parent_type: libc::c_int,
|
||||
pub mm_parent: *mut Mailmime,
|
||||
pub mm_parent: *mut mailmime,
|
||||
pub mm_multipart_pos: *mut clistiter,
|
||||
pub mm_type: libc::c_int,
|
||||
pub mm_mime_start: *const libc::c_char,
|
||||
@@ -186,7 +188,7 @@ pub union unnamed_8 {
|
||||
#[repr(C)]
|
||||
pub struct unnamed_9 {
|
||||
pub mm_fields: *mut mailimf_fields,
|
||||
pub mm_msg_mime: *mut Mailmime,
|
||||
pub mm_msg_mime: *mut mailmime,
|
||||
}
|
||||
/* multi-part */
|
||||
#[derive(Copy, Clone)]
|
||||
@@ -654,15 +656,15 @@ pub unsafe fn mailmime_new(
|
||||
mut mm_epilogue: *mut mailmime_data,
|
||||
mut mm_mp_list: *mut clist,
|
||||
mut mm_fields: *mut mailimf_fields,
|
||||
mut mm_msg_mime: *mut Mailmime,
|
||||
) -> *mut Mailmime {
|
||||
let mut mime: *mut Mailmime = 0 as *mut Mailmime;
|
||||
mut mm_msg_mime: *mut mailmime,
|
||||
) -> *mut mailmime {
|
||||
let mut mime: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
mime = malloc(::std::mem::size_of::<Mailmime>() as libc::size_t) as *mut Mailmime;
|
||||
mime = malloc(::std::mem::size_of::<mailmime>() as libc::size_t) as *mut mailmime;
|
||||
if mime.is_null() {
|
||||
return 0 as *mut Mailmime;
|
||||
return 0 as *mut mailmime;
|
||||
}
|
||||
(*mime).mm_parent = 0 as *mut Mailmime;
|
||||
(*mime).mm_parent = 0 as *mut mailmime;
|
||||
(*mime).mm_parent_type = MAILMIME_NONE as libc::c_int;
|
||||
(*mime).mm_multipart_pos = 0 as *mut clistiter;
|
||||
(*mime).mm_type = mm_type;
|
||||
@@ -679,12 +681,12 @@ pub unsafe fn mailmime_new(
|
||||
(*mime).mm_data.mm_multipart.mm_mp_list = mm_mp_list;
|
||||
cur = (*mm_mp_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut submime: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut submime: *mut mailmime = 0 as *mut mailmime;
|
||||
submime = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut Mailmime;
|
||||
}) as *mut mailmime;
|
||||
(*submime).mm_parent = mime;
|
||||
(*submime).mm_parent_type = MAILMIME_MULTIPLE as libc::c_int;
|
||||
(*submime).mm_multipart_pos = cur;
|
||||
@@ -708,29 +710,7 @@ pub unsafe fn mailmime_new(
|
||||
return mime;
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_new_simple(
|
||||
mut mm_type: libc::c_int,
|
||||
mut mm_mime_fields: *mut mailmime_fields,
|
||||
mut mm_content_type: *mut mailmime_content,
|
||||
mut mm_fields: *mut mailimf_fields,
|
||||
mut mm_msg_mime: *mut Mailmime,
|
||||
) -> *mut Mailmime {
|
||||
mailmime_new(
|
||||
mm_type,
|
||||
std::ptr::null(),
|
||||
0,
|
||||
mm_mime_fields,
|
||||
mm_content_type,
|
||||
std::ptr::null_mut(),
|
||||
std::ptr::null_mut(),
|
||||
std::ptr::null_mut(),
|
||||
std::ptr::null_mut(),
|
||||
mm_fields,
|
||||
mm_msg_mime,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_free(mut mime: *mut Mailmime) {
|
||||
pub unsafe fn mailmime_free(mut mime: *mut mailmime) {
|
||||
match (*mime).mm_type {
|
||||
1 => {
|
||||
if (*mime).mm_body.is_null() && !(*mime).mm_data.mm_single.is_null() {
|
||||
@@ -747,7 +727,7 @@ pub unsafe fn mailmime_free(mut mime: *mut Mailmime) {
|
||||
}
|
||||
clist_foreach(
|
||||
(*mime).mm_data.mm_multipart.mm_mp_list,
|
||||
::std::mem::transmute::<Option<unsafe fn(_: *mut Mailmime) -> ()>, clist_func>(
|
||||
::std::mem::transmute::<Option<unsafe fn(_: *mut mailmime) -> ()>, clist_func>(
|
||||
Some(mailmime_free),
|
||||
),
|
||||
0 as *mut libc::c_void,
|
||||
@@ -1,9 +1,10 @@
|
||||
use libc;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailimf_types::*;
|
||||
use crate::mailmime::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::other::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@@ -636,9 +637,9 @@ pub unsafe fn mailmime_data_new_file(
|
||||
);
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_new_message_data(mut msg_mime: *mut Mailmime) -> *mut Mailmime {
|
||||
pub unsafe fn mailmime_new_message_data(mut msg_mime: *mut mailmime) -> *mut mailmime {
|
||||
let mut content: *mut mailmime_content = 0 as *mut mailmime_content;
|
||||
let mut build_info: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut build_info: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields;
|
||||
content = mailmime_get_content_message();
|
||||
if !content.is_null() {
|
||||
@@ -671,15 +672,15 @@ pub unsafe fn mailmime_new_message_data(mut msg_mime: *mut Mailmime) -> *mut Mai
|
||||
}
|
||||
mailmime_content_free(content);
|
||||
}
|
||||
return 0 as *mut Mailmime;
|
||||
return 0 as *mut mailmime;
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_new_empty(
|
||||
mut content: *mut mailmime_content,
|
||||
mut mime_fields: *mut mailmime_fields,
|
||||
) -> *mut Mailmime {
|
||||
) -> *mut mailmime {
|
||||
let mut current_block: u64;
|
||||
let mut build_info: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut build_info: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut list: *mut clist = 0 as *mut clist;
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut mime_type: libc::c_int = 0;
|
||||
@@ -822,11 +823,11 @@ pub unsafe fn mailmime_new_empty(
|
||||
0 as *mut mailmime_data,
|
||||
list,
|
||||
0 as *mut mailimf_fields,
|
||||
0 as *mut Mailmime,
|
||||
0 as *mut mailmime,
|
||||
);
|
||||
if build_info.is_null() {
|
||||
clist_free(list);
|
||||
return 0 as *mut Mailmime;
|
||||
return 0 as *mut mailmime;
|
||||
}
|
||||
return build_info;
|
||||
}
|
||||
@@ -834,7 +835,7 @@ pub unsafe fn mailmime_new_empty(
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return 0 as *mut Mailmime;
|
||||
return 0 as *mut mailmime;
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_generate_boundary() -> *mut libc::c_char {
|
||||
@@ -855,12 +856,12 @@ pub unsafe fn mailmime_generate_boundary() -> *mut libc::c_char {
|
||||
pub unsafe fn mailmime_new_with_content(
|
||||
mut content_type: *const libc::c_char,
|
||||
mut mime_fields: *mut mailmime_fields,
|
||||
mut result: *mut *mut Mailmime,
|
||||
mut result: *mut *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut r: libc::c_int = 0;
|
||||
let mut cur_token: size_t = 0;
|
||||
let mut content: *mut mailmime_content = 0 as *mut mailmime_content;
|
||||
let mut build_info: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut build_info: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut res: libc::c_int = 0;
|
||||
cur_token = 0i32 as size_t;
|
||||
r = mailmime_content_parse(
|
||||
@@ -885,7 +886,7 @@ pub unsafe fn mailmime_new_with_content(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_set_preamble_file(
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
mut filename: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
let mut data: *mut mailmime_data = 0 as *mut mailmime_data;
|
||||
@@ -905,7 +906,7 @@ pub unsafe fn mailmime_set_preamble_file(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_set_epilogue_file(
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
mut filename: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
let mut data: *mut mailmime_data = 0 as *mut mailmime_data;
|
||||
@@ -925,7 +926,7 @@ pub unsafe fn mailmime_set_epilogue_file(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_set_preamble_text(
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
mut data_str: *mut libc::c_char,
|
||||
mut length: size_t,
|
||||
) -> libc::c_int {
|
||||
@@ -946,7 +947,7 @@ pub unsafe fn mailmime_set_preamble_text(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_set_epilogue_text(
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
mut data_str: *mut libc::c_char,
|
||||
mut length: size_t,
|
||||
) -> libc::c_int {
|
||||
@@ -967,7 +968,7 @@ pub unsafe fn mailmime_set_epilogue_text(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_set_body_file(
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
mut filename: *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
let mut encoding: libc::c_int = 0;
|
||||
@@ -989,7 +990,7 @@ pub unsafe fn mailmime_set_body_file(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_set_body_text(
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
mut data_str: *mut libc::c_char,
|
||||
mut length: size_t,
|
||||
) -> libc::c_int {
|
||||
@@ -1012,8 +1013,8 @@ pub unsafe fn mailmime_set_body_text(
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_add_part(
|
||||
mut build_info: *mut Mailmime,
|
||||
mut part: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
mut part: *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut r: libc::c_int = 0;
|
||||
if (*build_info).mm_type == MAILMIME_MESSAGE as libc::c_int {
|
||||
@@ -1038,19 +1039,19 @@ pub unsafe fn mailmime_add_part(
|
||||
return MAILIMF_NO_ERROR as libc::c_int;
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_remove_part(mut mime: *mut Mailmime) {
|
||||
let mut parent: *mut Mailmime = 0 as *mut Mailmime;
|
||||
pub unsafe fn mailmime_remove_part(mut mime: *mut mailmime) {
|
||||
let mut parent: *mut mailmime = 0 as *mut mailmime;
|
||||
parent = (*mime).mm_parent;
|
||||
if parent.is_null() {
|
||||
return;
|
||||
}
|
||||
match (*mime).mm_parent_type {
|
||||
3 => {
|
||||
(*mime).mm_parent = 0 as *mut Mailmime;
|
||||
(*parent).mm_data.mm_message.mm_msg_mime = 0 as *mut Mailmime
|
||||
(*mime).mm_parent = 0 as *mut mailmime;
|
||||
(*parent).mm_data.mm_message.mm_msg_mime = 0 as *mut mailmime
|
||||
}
|
||||
2 => {
|
||||
(*mime).mm_parent = 0 as *mut Mailmime;
|
||||
(*mime).mm_parent = 0 as *mut mailmime;
|
||||
clist_delete(
|
||||
(*parent).mm_data.mm_multipart.mm_mp_list,
|
||||
(*mime).mm_multipart_pos,
|
||||
@@ -1061,7 +1062,7 @@ pub unsafe fn mailmime_remove_part(mut mime: *mut Mailmime) {
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_set_imf_fields(
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
mut mm_fields: *mut mailimf_fields,
|
||||
) {
|
||||
(*build_info).mm_data.mm_message.mm_fields = mm_fields;
|
||||
@@ -1212,11 +1213,11 @@ pub unsafe fn mailmime_single_fields_free(mut single_fields: *mut mailmime_singl
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_smart_add_part(
|
||||
mut mime: *mut Mailmime,
|
||||
mut mime_sub: *mut Mailmime,
|
||||
mut mime: *mut mailmime,
|
||||
mut mime_sub: *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut saved_sub: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut mp: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut saved_sub: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut mp: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut res: libc::c_int = 0;
|
||||
let mut r: libc::c_int = 0;
|
||||
match (*mime).mm_type {
|
||||
@@ -1277,10 +1278,10 @@ pub unsafe fn mailmime_smart_add_part(
|
||||
return res;
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_multiple_new(mut type_0: *const libc::c_char) -> *mut Mailmime {
|
||||
pub unsafe fn mailmime_multiple_new(mut type_0: *const libc::c_char) -> *mut mailmime {
|
||||
let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields;
|
||||
let mut content: *mut mailmime_content = 0 as *mut mailmime_content;
|
||||
let mut mp: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut mp: *mut mailmime = 0 as *mut mailmime;
|
||||
mime_fields = mailmime_fields_new_empty();
|
||||
if !mime_fields.is_null() {
|
||||
content = mailmime_content_new_with_str(type_0);
|
||||
@@ -1294,7 +1295,7 @@ pub unsafe fn mailmime_multiple_new(mut type_0: *const libc::c_char) -> *mut Mai
|
||||
}
|
||||
mailmime_fields_free(mime_fields);
|
||||
}
|
||||
return 0 as *mut Mailmime;
|
||||
return 0 as *mut mailmime;
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_content_new_with_str(mut str: *const libc::c_char) -> *mut mailmime_content {
|
||||
@@ -1309,8 +1310,8 @@ pub unsafe fn mailmime_content_new_with_str(mut str: *const libc::c_char) -> *mu
|
||||
return content;
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_smart_remove_part(mut mime: *mut Mailmime) -> libc::c_int {
|
||||
let mut parent: *mut Mailmime = 0 as *mut Mailmime;
|
||||
pub unsafe fn mailmime_smart_remove_part(mut mime: *mut mailmime) -> libc::c_int {
|
||||
let mut parent: *mut mailmime = 0 as *mut mailmime;
|
||||
let mut res: libc::c_int = 0;
|
||||
parent = (*mime).mm_parent;
|
||||
if parent.is_null() {
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::ffi::CStr;
|
||||
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::write_generic::*;
|
||||
use crate::mailmime::content::*;
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailmime::types_helper::*;
|
||||
use crate::mailimf_write_generic::*;
|
||||
use crate::mailmime::*;
|
||||
use crate::mailmime_content::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::mailmime_types_helper::*;
|
||||
use crate::other::*;
|
||||
|
||||
pub const STATE_INIT: libc::c_uint = 0;
|
||||
@@ -1017,7 +1017,7 @@ pub unsafe fn mailmime_write_driver(
|
||||
>,
|
||||
mut data: *mut libc::c_void,
|
||||
mut col: *mut libc::c_int,
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
if !(*build_info).mm_parent.is_null() {
|
||||
return mailmime_sub_write_driver(do_write, data, col, build_info);
|
||||
@@ -1038,7 +1038,7 @@ unsafe fn mailmime_part_write_driver(
|
||||
>,
|
||||
mut data: *mut libc::c_void,
|
||||
mut col: *mut libc::c_int,
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut current_block: u64;
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
@@ -1152,8 +1152,8 @@ unsafe fn mailmime_part_write_driver(
|
||||
current_block = 3546145585875536353;
|
||||
break;
|
||||
}
|
||||
let mut subpart: *mut Mailmime = 0 as *mut Mailmime;
|
||||
subpart = (*cur).data as *mut Mailmime;
|
||||
let mut subpart: *mut mailmime = 0 as *mut mailmime;
|
||||
subpart = (*cur).data as *mut mailmime;
|
||||
if 0 == first {
|
||||
r = mailimf_string_write_driver(
|
||||
do_write,
|
||||
@@ -1421,7 +1421,7 @@ unsafe fn mailmime_sub_write_driver(
|
||||
>,
|
||||
mut data: *mut libc::c_void,
|
||||
mut col: *mut libc::c_int,
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut r: libc::c_int = 0;
|
||||
if !(*build_info).mm_content_type.is_null() {
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailmime::write_generic::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::mailmime_write_generic::*;
|
||||
use crate::mmapstring::*;
|
||||
use crate::other::*;
|
||||
|
||||
@@ -41,7 +41,7 @@ pub unsafe fn mailmime_content_type_write_mem(
|
||||
pub unsafe fn mailmime_write_mem(
|
||||
mut f: *mut MMAPString,
|
||||
mut col: *mut libc::c_int,
|
||||
mut build_info: *mut Mailmime,
|
||||
mut build_info: *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
return mailmime_write_driver(Some(do_write), f as *mut libc::c_void, col, build_info);
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
use chrono::{Datelike, Local, TimeZone, Timelike};
|
||||
|
||||
use crate::clist::*;
|
||||
use crate::mailimf::types::*;
|
||||
use crate::mailimf::types_helper::*;
|
||||
use crate::mailmime::types::*;
|
||||
use crate::mailmime::types_helper::*;
|
||||
use crate::mailimf_types::*;
|
||||
use crate::mailimf_types_helper::*;
|
||||
use crate::mailmime_types::*;
|
||||
use crate::mailmime_types_helper::*;
|
||||
|
||||
pub(crate) use libc::{
|
||||
calloc, close, free, isalpha, isdigit, malloc, memcmp, memcpy, memmove, memset, realloc,
|
||||
@@ -132,7 +132,7 @@ pub const MAILIMF_ERROR_MEMORY: libc::c_uint = 2;
|
||||
pub const MAILIMF_ERROR_PARSE: libc::c_uint = 1;
|
||||
pub const MAILIMF_NO_ERROR: libc::c_uint = 0;
|
||||
|
||||
pub unsafe fn mailprivacy_prepare_mime(mut mime: *mut Mailmime) {
|
||||
pub unsafe fn mailprivacy_prepare_mime(mut mime: *mut mailmime) {
|
||||
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
||||
match (*mime).mm_type {
|
||||
1 => {
|
||||
@@ -143,12 +143,12 @@ pub unsafe fn mailprivacy_prepare_mime(mut mime: *mut Mailmime) {
|
||||
2 => {
|
||||
cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut child: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut child: *mut mailmime = 0 as *mut mailmime;
|
||||
child = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut Mailmime;
|
||||
}) as *mut mailmime;
|
||||
mailprivacy_prepare_mime(child);
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
@@ -166,7 +166,7 @@ pub unsafe fn mailprivacy_prepare_mime(mut mime: *mut Mailmime) {
|
||||
};
|
||||
}
|
||||
|
||||
unsafe fn prepare_mime_single(mut mime: *mut Mailmime) {
|
||||
unsafe fn prepare_mime_single(mut mime: *mut mailmime) {
|
||||
let mut single_fields: mailmime_single_fields = mailmime_single_fields {
|
||||
fld_content: 0 as *mut mailmime_content,
|
||||
fld_content_charset: 0 as *mut libc::c_char,
|
||||
@@ -251,10 +251,10 @@ unsafe fn prepare_mime_single(mut mime: *mut Mailmime) {
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_substitute(
|
||||
mut old_mime: *mut Mailmime,
|
||||
mut new_mime: *mut Mailmime,
|
||||
mut old_mime: *mut mailmime,
|
||||
mut new_mime: *mut mailmime,
|
||||
) -> libc::c_int {
|
||||
let mut parent: *mut Mailmime = 0 as *mut Mailmime;
|
||||
let mut parent: *mut mailmime = 0 as *mut mailmime;
|
||||
parent = (*old_mime).mm_parent;
|
||||
if parent.is_null() {
|
||||
return MAIL_ERROR_INVAL as libc::c_int;
|
||||
@@ -266,7 +266,7 @@ pub unsafe fn mailmime_substitute(
|
||||
}
|
||||
(*new_mime).mm_parent = parent;
|
||||
(*new_mime).mm_parent_type = (*old_mime).mm_parent_type;
|
||||
(*old_mime).mm_parent = 0 as *mut Mailmime;
|
||||
(*old_mime).mm_parent = 0 as *mut mailmime;
|
||||
(*old_mime).mm_parent_type = MAILMIME_NONE as libc::c_int;
|
||||
return MAIL_NO_ERROR as libc::c_int;
|
||||
}
|
||||
|
||||
@@ -5,4 +5,3 @@
|
||||
# It is recommended to check this file in to source control so that
|
||||
# everyone who runs the test benefits from these saved cases.
|
||||
cc 679506fe9ac59df773f8cfa800fdab5f0a32fe49d2ab370394000a1aa5bc2a72 # shrinks to buf = "%0A"
|
||||
cc e34960438edb2426904b44fb4215154e7e2880f2fd1c3183b98bfcc76fec4882 # shrinks to input = " 0"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ["DCC_RS_TARGET"] = target = "release"
|
||||
@@ -21,5 +21,5 @@ if __name__ == "__main__":
|
||||
subprocess.check_call("rm -rf build/ src/deltachat/*.so" , shell=True)
|
||||
|
||||
subprocess.check_call([
|
||||
sys.executable, "-m", "pip", "install", "-e", "."
|
||||
"pip", "install", "-e", "."
|
||||
])
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import print_function
|
||||
import threading
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
from array import array
|
||||
@@ -22,7 +23,7 @@ class Account(object):
|
||||
by the underlying deltachat c-library. All public Account methods are
|
||||
meant to be memory-safe and return memory-safe objects.
|
||||
"""
|
||||
def __init__(self, db_path, logid=None, eventlogging=True, debug=True):
|
||||
def __init__(self, db_path, logid=None, eventlogging=True):
|
||||
""" initialize account object.
|
||||
|
||||
:param db_path: a path to the account database. The database
|
||||
@@ -30,14 +31,13 @@ class Account(object):
|
||||
:param logid: an optional logging prefix that should be used with
|
||||
the default internal logging.
|
||||
:param eventlogging: if False no eventlogging and no context callback will be configured
|
||||
:param debug: turn on debug logging for events.
|
||||
"""
|
||||
self._dc_context = ffi.gc(
|
||||
lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL),
|
||||
_destroy_dc_context,
|
||||
)
|
||||
if eventlogging:
|
||||
self._evlogger = EventLogger(self._dc_context, logid, debug)
|
||||
self._evlogger = EventLogger(self._dc_context, logid)
|
||||
deltachat.set_context_callback(self._dc_context, self._process_event)
|
||||
self._threads = IOThreads(self._dc_context, self._evlogger._log_event)
|
||||
else:
|
||||
@@ -48,7 +48,7 @@ class Account(object):
|
||||
if not lib.dc_open(self._dc_context, db_path, ffi.NULL):
|
||||
raise ValueError("Could not dc_open: {}".format(db_path))
|
||||
self._configkeys = self.get_config("sys.config_keys").split()
|
||||
self._imex_events = Queue()
|
||||
self._imex_completed = threading.Event()
|
||||
|
||||
def __del__(self):
|
||||
self.shutdown()
|
||||
@@ -289,64 +289,31 @@ class Account(object):
|
||||
msg_ids = [msg.id for msg in messages]
|
||||
lib.dc_delete_msgs(self._dc_context, msg_ids, len(msg_ids))
|
||||
|
||||
def export_self_keys(self, path):
|
||||
""" export public and private keys to the specified directory. """
|
||||
return self._export(path, imex_cmd=1)
|
||||
|
||||
def export_all(self, path):
|
||||
"""return new file containing a backup of all database state
|
||||
(chats, contacts, keys, media, ...). The file is created in the
|
||||
the `path` directory.
|
||||
def export_to_dir(self, backupdir):
|
||||
"""return after all delta chat state is exported to a new file in
|
||||
the specified directory.
|
||||
"""
|
||||
export_files = self._export(path, 11)
|
||||
if len(export_files) != 1:
|
||||
raise RuntimeError("found more than one new file")
|
||||
return export_files[0]
|
||||
|
||||
def _imex_events_clear(self):
|
||||
try:
|
||||
while True:
|
||||
self._imex_events.get_nowait()
|
||||
except Empty:
|
||||
pass
|
||||
|
||||
def _export(self, path, imex_cmd):
|
||||
self._imex_events_clear()
|
||||
lib.dc_imex(self._dc_context, imex_cmd, as_dc_charpointer(path), ffi.NULL)
|
||||
snap_files = os.listdir(backupdir)
|
||||
self._imex_completed.clear()
|
||||
lib.dc_imex(self._dc_context, 11, as_dc_charpointer(backupdir), ffi.NULL)
|
||||
if not self._threads.is_started():
|
||||
lib.dc_perform_imap_jobs(self._dc_context)
|
||||
files_written = []
|
||||
while True:
|
||||
ev = self._imex_events.get()
|
||||
if isinstance(ev, str):
|
||||
files_written.append(ev)
|
||||
elif isinstance(ev, bool):
|
||||
if not ev:
|
||||
raise ValueError("export failed, exp-files: {}".format(files_written))
|
||||
return files_written
|
||||
self._imex_completed.wait()
|
||||
for x in os.listdir(backupdir):
|
||||
if x not in snap_files:
|
||||
return os.path.join(backupdir, x)
|
||||
|
||||
def import_self_keys(self, path):
|
||||
""" Import private keys found in the `path` directory.
|
||||
The last imported key is made the default keys unless its name
|
||||
contains the string legacy. Public keys are not imported.
|
||||
"""
|
||||
self._import(path, imex_cmd=2)
|
||||
|
||||
def import_all(self, path):
|
||||
"""import delta chat state from the specified backup `path` (a file).
|
||||
def import_from_file(self, path):
|
||||
"""import delta chat state from the specified backup file.
|
||||
|
||||
The account must be in unconfigured state for import to attempted.
|
||||
"""
|
||||
assert not self.is_configured(), "cannot import into configured account"
|
||||
self._import(path, imex_cmd=12)
|
||||
|
||||
def _import(self, path, imex_cmd):
|
||||
self._imex_events_clear()
|
||||
lib.dc_imex(self._dc_context, imex_cmd, as_dc_charpointer(path), ffi.NULL)
|
||||
self._imex_completed.clear()
|
||||
lib.dc_imex(self._dc_context, 12, as_dc_charpointer(path), ffi.NULL)
|
||||
if not self._threads.is_started():
|
||||
lib.dc_perform_imap_jobs(self._dc_context)
|
||||
if not self._imex_events.get():
|
||||
raise ValueError("import from path '{}' failed".format(path))
|
||||
self._imex_completed.wait()
|
||||
|
||||
def initiate_key_transfer(self):
|
||||
"""return setup code after a Autocrypt setup message
|
||||
@@ -456,12 +423,7 @@ class Account(object):
|
||||
|
||||
def on_dc_event_imex_progress(self, data1, data2):
|
||||
if data1 == 1000:
|
||||
self._imex_events.put(True)
|
||||
elif data1 == 0:
|
||||
self._imex_events.put(False)
|
||||
|
||||
def on_dc_event_imex_file_written(self, data1, data2):
|
||||
self._imex_events.put(data1)
|
||||
self._imex_completed.set()
|
||||
|
||||
|
||||
class IOThreads:
|
||||
|
||||
@@ -101,10 +101,6 @@ class Message(object):
|
||||
""" return True if this message is a setup message. """
|
||||
return lib.dc_msg_is_setupmessage(self._dc_msg)
|
||||
|
||||
def get_setupcodebegin(self):
|
||||
""" return the first characters of a setup code in a setup message. """
|
||||
return from_dc_charpointer(lib.dc_msg_get_setupcodebegin(self._dc_msg))
|
||||
|
||||
def is_encrypted(self):
|
||||
""" return True if this message was encrypted. """
|
||||
return bool(lib.dc_msg_get_showpadlock(self._dc_msg))
|
||||
|
||||
@@ -93,9 +93,8 @@ class TestOfflineContact:
|
||||
ac1 = acfactory.get_configured_offline_account()
|
||||
contact1 = ac1.create_contact(email="some1@example.com", name="some1")
|
||||
chat = ac1.create_chat_by_contact(contact1)
|
||||
msg = chat.send_text("one messae")
|
||||
chat.send_text("one messae")
|
||||
assert not ac1.delete_contact(contact1)
|
||||
assert not msg.filemime
|
||||
|
||||
|
||||
class TestOfflineChat:
|
||||
@@ -294,10 +293,10 @@ class TestOfflineChat:
|
||||
assert contact == ac1.get_self_contact()
|
||||
assert not backupdir.listdir()
|
||||
|
||||
path = ac1.export_all(backupdir.strpath)
|
||||
path = ac1.export_to_dir(backupdir.strpath)
|
||||
assert os.path.exists(path)
|
||||
ac2 = acfactory.get_unconfigured_account()
|
||||
ac2.import_all(path)
|
||||
ac2.import_from_file(path)
|
||||
contacts = ac2.get_contacts(query="some1")
|
||||
assert len(contacts) == 1
|
||||
contact2 = contacts[0]
|
||||
@@ -341,16 +340,6 @@ class TestOnlineAccount:
|
||||
assert chat.id > const.DC_CHAT_ID_LAST_SPECIAL
|
||||
return chat
|
||||
|
||||
def test_export_import_self_keys(self, acfactory, tmpdir):
|
||||
ac1, ac2 = acfactory.get_two_online_accounts()
|
||||
dir = tmpdir.mkdir("exportdir")
|
||||
export_files = ac1.export_self_keys(dir.strpath)
|
||||
assert len(export_files) == 2
|
||||
for x in export_files:
|
||||
assert x.startswith(dir.strpath)
|
||||
ac1._evlogger.consume_events()
|
||||
ac1.import_self_keys(dir.strpath)
|
||||
|
||||
def test_one_account_send(self, acfactory):
|
||||
ac1 = acfactory.get_online_configuring_account()
|
||||
c2 = ac1.create_contact(email=ac1.get_config("addr"))
|
||||
@@ -512,7 +501,7 @@ class TestOnlineAccount:
|
||||
assert os.path.exists(msg_in.filename)
|
||||
assert os.stat(msg_in.filename).st_size == os.stat(path).st_size
|
||||
|
||||
def test_import_export_online_all(self, acfactory, tmpdir):
|
||||
def test_import_export_online(self, acfactory, tmpdir):
|
||||
ac1 = acfactory.get_online_configuring_account()
|
||||
wait_configuration_progress(ac1, 1000)
|
||||
|
||||
@@ -520,11 +509,11 @@ class TestOnlineAccount:
|
||||
chat = ac1.create_chat_by_contact(contact1)
|
||||
chat.send_text("msg1")
|
||||
backupdir = tmpdir.mkdir("backup")
|
||||
path = ac1.export_all(backupdir.strpath)
|
||||
path = ac1.export_to_dir(backupdir.strpath)
|
||||
assert os.path.exists(path)
|
||||
|
||||
ac2 = acfactory.get_unconfigured_account()
|
||||
ac2.import_all(path)
|
||||
ac2.import_from_file(path)
|
||||
contacts = ac2.get_contacts(query="some1")
|
||||
assert len(contacts) == 1
|
||||
contact2 = contacts[0]
|
||||
@@ -534,7 +523,7 @@ class TestOnlineAccount:
|
||||
assert len(messages) == 1
|
||||
assert messages[0].text == "msg1"
|
||||
|
||||
def test_ac_setup_message(self, acfactory, lp):
|
||||
def test_ac_setup_message(self, acfactory):
|
||||
# note that the receiving account needs to be configured and running
|
||||
# before ther setup message is send. DC does not read old messages
|
||||
# as of Jul2019
|
||||
@@ -542,18 +531,15 @@ class TestOnlineAccount:
|
||||
ac2 = acfactory.clone_online_account(ac1)
|
||||
wait_configuration_progress(ac2, 1000)
|
||||
wait_configuration_progress(ac1, 1000)
|
||||
lp.sec("trigger ac setup message and return setupcode")
|
||||
assert ac1.get_info()["fingerprint"] != ac2.get_info()["fingerprint"]
|
||||
setup_code = ac1.initiate_key_transfer()
|
||||
ac2._evlogger.set_timeout(30)
|
||||
ev = ac2._evlogger.get_matching("DC_EVENT_INCOMING_MSG|DC_EVENT_MSGS_CHANGED")
|
||||
msg = ac2.get_message_by_id(ev[2])
|
||||
assert msg.is_setup_message()
|
||||
assert msg.get_setupcodebegin() == setup_code[:2]
|
||||
lp.sec("try a bad setup code")
|
||||
# first try a bad setup code
|
||||
with pytest.raises(ValueError):
|
||||
msg.continue_key_transfer(str(reversed(setup_code)))
|
||||
lp.sec("try a good setup code")
|
||||
print("*************** Incoming ASM File at: ", msg.filename)
|
||||
print("*************** Setup Code: ", setup_code)
|
||||
msg.continue_key_transfer(setup_code)
|
||||
|
||||
@@ -108,43 +108,3 @@ def test_provider_info():
|
||||
|
||||
def test_provider_info_none():
|
||||
assert lib.dc_provider_new_from_email(cutil.as_dc_charpointer("email@unexistent.no")) == ffi.NULL
|
||||
|
||||
|
||||
def test_get_info_closed():
|
||||
ctx = ffi.gc(
|
||||
lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL),
|
||||
lib.dc_context_unref,
|
||||
)
|
||||
info = cutil.from_dc_charpointer(lib.dc_get_info(ctx))
|
||||
assert 'deltachat_core_version' in info
|
||||
assert 'database_dir' not in info
|
||||
|
||||
|
||||
def test_get_info_open(tmpdir):
|
||||
ctx = ffi.gc(
|
||||
lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL),
|
||||
lib.dc_context_unref,
|
||||
)
|
||||
db_fname = tmpdir.join("test.db")
|
||||
lib.dc_open(ctx, db_fname.strpath.encode("ascii"), ffi.NULL)
|
||||
info = cutil.from_dc_charpointer(lib.dc_get_info(ctx))
|
||||
assert 'deltachat_core_version' in info
|
||||
assert 'database_dir' in info
|
||||
|
||||
|
||||
def test_is_open_closed():
|
||||
ctx = ffi.gc(
|
||||
lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL),
|
||||
lib.dc_context_unref,
|
||||
)
|
||||
assert lib.dc_is_open(ctx) == 0
|
||||
|
||||
|
||||
def test_is_open_actually_open(tmpdir):
|
||||
ctx = ffi.gc(
|
||||
lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL),
|
||||
lib.dc_context_unref,
|
||||
)
|
||||
db_fname = tmpdir.join("test.db")
|
||||
lib.dc_open(ctx, db_fname.strpath.encode("ascii"), ffi.NULL)
|
||||
assert lib.dc_is_open(ctx) == 1
|
||||
|
||||
23
spec.md
23
spec.md
@@ -117,8 +117,7 @@ The sender plus the recipients are the group members.
|
||||
To allow different groups with the same members,
|
||||
groups are identified by a group-id.
|
||||
The group-id MUST be created only from the characters
|
||||
`0`-`9`, `A`-`Z`, `a`-`z` `_` and `-`
|
||||
and MUST have a length of at least 11 characters.
|
||||
`0`-`9`, `A`-`Z`, `a`-`z` `_` and `-`.
|
||||
|
||||
Groups MUST have a group-name.
|
||||
The group-name is any non-zero-length UTF-8 string.
|
||||
@@ -145,9 +144,9 @@ The message-id MUST have the format `Gr.<group-id>.<unique data>`.
|
||||
From: member1@domain
|
||||
To: member2@domain, member3@domain
|
||||
Chat-Version: 1.0
|
||||
Chat-Group-ID: 12345uvwxyZ
|
||||
Chat-Group-ID: 1234xyZ
|
||||
Chat-Group-Name: My Group
|
||||
Message-ID: Gr.12345uvwxyZ.0001@domain
|
||||
Message-ID: Gr.1234xyZ.0001@domain
|
||||
Subject: Chat: My Group: Hello group ...
|
||||
|
||||
Hello group - this group contains three members
|
||||
@@ -197,10 +196,10 @@ and the message SHOULD appear as a message or action from the sender.
|
||||
From: member1@domain
|
||||
To: member2@domain, member3@domain, member4@domain
|
||||
Chat-Version: 1.0
|
||||
Chat-Group-ID: 12345uvwxyZ
|
||||
Chat-Group-ID: 1234xyZ
|
||||
Chat-Group-Name: My Group
|
||||
Chat-Group-Member-Added: member4@domain
|
||||
Message-ID: Gr.12345uvwxyZ.0002@domain
|
||||
Message-ID: Gr.1234xyZ.0002@domain
|
||||
Subject: Chat: My Group: Hello, ...
|
||||
|
||||
Hello, I've added member4@domain to our group. Now we have 4 members.
|
||||
@@ -210,10 +209,10 @@ To remove a member:
|
||||
From: member1@domain
|
||||
To: member2@domain, member3@domain
|
||||
Chat-Version: 1.0
|
||||
Chat-Group-ID: 12345uvwxyZ
|
||||
Chat-Group-ID: 1234xyZ
|
||||
Chat-Group-Name: My Group
|
||||
Chat-Group-Member-Removed: member4@domain
|
||||
Message-ID: Gr.12345uvwxyZ.0003@domain
|
||||
Message-ID: Gr.1234xyZ.0003@domain
|
||||
Subject: Chat: My Group: Hello, ...
|
||||
|
||||
Hello, I've removed member4@domain from our group. Now we have 3 members.
|
||||
@@ -234,10 +233,10 @@ and the message SHOULD appear as a message or action from the sender.
|
||||
From: member1@domain
|
||||
To: member2@domain, member3@domain
|
||||
Chat-Version: 1.0
|
||||
Chat-Group-ID: 12345uvwxyZ
|
||||
Chat-Group-ID: 1234xyZ
|
||||
Chat-Group-Name: Our Group
|
||||
Chat-Group-Name-Changed: My Group
|
||||
Message-ID: Gr.12345uvwxyZ.0004@domain
|
||||
Message-ID: Gr.1234xyZ.0004@domain
|
||||
Subject: Chat: Our Group: Hello, ...
|
||||
|
||||
Hello, I've changed the group name from "My Group" to "Our Group".
|
||||
@@ -263,10 +262,10 @@ and the message SHOULD appear as a message or action from the sender.
|
||||
From: member1@domain
|
||||
To: member2@domain, member3@domain
|
||||
Chat-Version: 1.0
|
||||
Chat-Group-ID: 12345uvwxyZ
|
||||
Chat-Group-ID: 1234xyZ
|
||||
Chat-Group-Name: Our Group
|
||||
Chat-Group-Image: image.jpg
|
||||
Message-ID: Gr.12345uvwxyZ.0005@domain
|
||||
Message-ID: Gr.1234xyZ.0005@domain
|
||||
Subject: Chat: Our Group: Hello, ...
|
||||
Content-Type: multipart/mixed; boundary="==break=="
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::ffi::CStr;
|
||||
use std::str::FromStr;
|
||||
use std::{fmt, str};
|
||||
|
||||
use mmime::mailimf::types::*;
|
||||
use mmime::mailimf_types::*;
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
|
||||
146
src/chat.rs
146
src/chat.rs
@@ -925,9 +925,7 @@ fn get_draft_msg_id(context: &Context, chat_id: u32) -> u32 {
|
||||
}
|
||||
|
||||
pub fn get_draft(context: &Context, chat_id: u32) -> Result<Option<Message>, Error> {
|
||||
if chat_id <= DC_CHAT_ID_LAST_SPECIAL {
|
||||
return Ok(None);
|
||||
}
|
||||
ensure!(chat_id > DC_CHAT_ID_LAST_SPECIAL, "Invalid chat ID");
|
||||
let draft_msg_id = get_draft_msg_id(context, chat_id);
|
||||
if draft_msg_id == 0 {
|
||||
return Ok(None);
|
||||
@@ -1334,7 +1332,7 @@ pub fn add_to_chat_contacts_table(context: &Context, chat_id: u32, contact_id: u
|
||||
|
||||
pub fn add_contact_to_chat(context: &Context, chat_id: u32, contact_id: u32) -> bool {
|
||||
match add_contact_to_chat_ex(context, chat_id, contact_id, false) {
|
||||
Ok(res) => res,
|
||||
Ok(res) => res,
|
||||
Err(err) => {
|
||||
error!(context, "failed to add contact: {}", err);
|
||||
false
|
||||
@@ -1349,10 +1347,7 @@ pub(crate) fn add_contact_to_chat_ex(
|
||||
contact_id: u32,
|
||||
from_handshake: bool,
|
||||
) -> Result<bool, Error> {
|
||||
ensure!(
|
||||
chat_id > DC_CHAT_ID_LAST_SPECIAL,
|
||||
"can not add member to special chats"
|
||||
);
|
||||
ensure!(chat_id > DC_CHAT_ID_LAST_SPECIAL, "can not add member to special chats");
|
||||
let contact = Contact::get_by_id(context, contact_id)?;
|
||||
let mut msg = Message::default();
|
||||
|
||||
@@ -1360,77 +1355,74 @@ pub(crate) fn add_contact_to_chat_ex(
|
||||
|
||||
/*this also makes sure, not contacts are added to special or normal chats*/
|
||||
let mut chat = Chat::load_from_db(context, chat_id)?;
|
||||
ensure!(
|
||||
real_group_exists(context, chat_id),
|
||||
"chat_id {} is not a group where one can add members",
|
||||
chat_id
|
||||
);
|
||||
ensure!(
|
||||
Contact::real_exists_by_id(context, contact_id) && contact_id != DC_CONTACT_ID_SELF,
|
||||
"invalid contact_id {} for removal in group",
|
||||
contact_id
|
||||
);
|
||||
ensure!(real_group_exists(context, chat_id),
|
||||
"chat_id {} is not a group where one can add members", chat_id);
|
||||
ensure!(Contact::real_exists_by_id(context, contact_id) && contact_id != DC_CONTACT_ID_SELF,
|
||||
"invalid contact_id {} for removal in group", contact_id);
|
||||
|
||||
if !is_contact_in_chat(context, chat_id, DC_CONTACT_ID_SELF as u32) {
|
||||
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
|
||||
emit_event!(
|
||||
context,
|
||||
Event::ErrorSelfNotInGroup("Cannot add contact to group; self not in group.".into())
|
||||
);
|
||||
bail!("can not add contact because our account is not part of it");
|
||||
}
|
||||
if from_handshake && chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 {
|
||||
chat.param.remove(Param::Unpromoted);
|
||||
chat.update_param(context).unwrap();
|
||||
}
|
||||
let self_addr = context
|
||||
.sql
|
||||
.get_config(context, "configured_addr")
|
||||
.unwrap_or_default();
|
||||
if contact.get_addr() == &self_addr {
|
||||
bail!("invalid attempt to add self e-mail address to group");
|
||||
}
|
||||
// ourself is added using DC_CONTACT_ID_SELF, do not add it explicitly.
|
||||
// if SELF is not in the group, members cannot be added at all.
|
||||
|
||||
if is_contact_in_chat(context, chat_id, contact_id) {
|
||||
if !from_handshake {
|
||||
return Ok(true);
|
||||
}
|
||||
} else {
|
||||
// else continue and send status mail
|
||||
if chat.typ == Chattype::VerifiedGroup {
|
||||
if contact.is_verified(context) != VerifiedStatus::BidirectVerified {
|
||||
error!(
|
||||
if !is_contact_in_chat(context, chat_id, DC_CONTACT_ID_SELF as u32) {
|
||||
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
|
||||
emit_event!(
|
||||
context,
|
||||
"Only bidirectional verified contacts can be added to verified groups."
|
||||
Event::ErrorSelfNotInGroup(
|
||||
"Cannot add contact to group; self not in group.".into()
|
||||
)
|
||||
);
|
||||
return Ok(false);
|
||||
bail!("can not add contact because our account is not part of it");
|
||||
}
|
||||
}
|
||||
if !add_to_chat_contacts_table(context, chat_id, contact_id) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||
msg.type_0 = Viewtype::Text;
|
||||
msg.text = Some(context.stock_system_msg(
|
||||
StockMessage::MsgAddMember,
|
||||
contact.get_addr(),
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
msg.param.set_int(Param::Cmd, 4);
|
||||
msg.param.set(Param::Arg, contact.get_addr());
|
||||
msg.param.set_int(Param::Arg2, from_handshake.into());
|
||||
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
|
||||
context.call_cb(Event::MsgsChanged {
|
||||
chat_id,
|
||||
msg_id: msg.id,
|
||||
});
|
||||
}
|
||||
context.call_cb(Event::MsgsChanged { chat_id, msg_id: 0 });
|
||||
return Ok(true);
|
||||
if from_handshake && chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 1
|
||||
{
|
||||
chat.param.remove(Param::Unpromoted);
|
||||
chat.update_param(context).unwrap();
|
||||
}
|
||||
let self_addr = context
|
||||
.sql
|
||||
.get_config(context, "configured_addr")
|
||||
.unwrap_or_default();
|
||||
if contact.get_addr() == &self_addr {
|
||||
bail!("invalid attempt to add self e-mail address to group");
|
||||
}
|
||||
// ourself is added using DC_CONTACT_ID_SELF, do not add it explicitly.
|
||||
// if SELF is not in the group, members cannot be added at all.
|
||||
|
||||
if is_contact_in_chat(context, chat_id, contact_id) {
|
||||
if !from_handshake {
|
||||
return Ok(true);
|
||||
}
|
||||
} else {
|
||||
// else continue and send status mail
|
||||
if chat.typ == Chattype::VerifiedGroup {
|
||||
if contact.is_verified(context) != VerifiedStatus::BidirectVerified {
|
||||
error!(
|
||||
context,
|
||||
"Only bidirectional verified contacts can be added to verified groups."
|
||||
);
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
if !add_to_chat_contacts_table(context, chat_id, contact_id) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||
msg.type_0 = Viewtype::Text;
|
||||
msg.text = Some(context.stock_system_msg(
|
||||
StockMessage::MsgAddMember,
|
||||
contact.get_addr(),
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
msg.param.set_int(Param::Cmd, 4);
|
||||
msg.param.set(Param::Arg, contact.get_addr());
|
||||
msg.param.set_int(Param::Arg2, from_handshake.into());
|
||||
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
|
||||
context.call_cb(Event::MsgsChanged {
|
||||
chat_id,
|
||||
msg_id: msg.id,
|
||||
});
|
||||
}
|
||||
context.call_cb(Event::MsgsChanged { chat_id, msg_id: 0 });
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
fn real_group_exists(context: &Context, chat_id: u32) -> bool {
|
||||
@@ -1888,8 +1880,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_get_draft_special_chat_id() {
|
||||
let t = dummy_context();
|
||||
let draft = get_draft(&t.ctx, DC_CHAT_ID_LAST_SPECIAL).unwrap();
|
||||
assert!(draft.is_none());
|
||||
let draft = get_draft(&t.ctx, DC_CHAT_ID_LAST_SPECIAL);
|
||||
assert!(draft.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -64,6 +64,15 @@ pub const DC_GCL_ADD_SELF: usize = 0x02;
|
||||
pub(crate) const DC_FP_NO_AUTOCRYPT_HEADER: i32 = 2;
|
||||
pub(crate) const DC_FP_ADD_AUTOCRYPT_HEADER: i32 = 1;
|
||||
|
||||
/// param1 is a directory where the keys are written to
|
||||
const DC_IMEX_EXPORT_SELF_KEYS: usize = 1;
|
||||
/// param1 is a directory where the keys are searched in and read from
|
||||
const DC_IMEX_IMPORT_SELF_KEYS: usize = 2;
|
||||
/// param1 is a directory where the backup is written to
|
||||
const DC_IMEX_EXPORT_BACKUP: usize = 11;
|
||||
/// param1 is the file with the backup to import
|
||||
const DC_IMEX_IMPORT_BACKUP: usize = 12;
|
||||
|
||||
/// virtual chat showing all messages belonging to chats flagged with chats.blocked=2
|
||||
pub(crate) const DC_CHAT_ID_DEADDROP: u32 = 1;
|
||||
/// messages that should be deleted get this chat_id; the messages are deleted from the working thread later then. This is also needed as rfc724_mid should be preset as long as the message is not deleted on the server (otherwise it is downloaded again)
|
||||
|
||||
@@ -804,14 +804,14 @@ impl Contact {
|
||||
}
|
||||
|
||||
if let Some(peerstate) = peerstate {
|
||||
if peerstate.verified_key.is_some() {
|
||||
if peerstate.verified_key().is_some() {
|
||||
return VerifiedStatus::BidirectVerified;
|
||||
}
|
||||
}
|
||||
|
||||
let peerstate = Peerstate::from_addr(context, &context.sql, &self.addr);
|
||||
if let Some(ps) = peerstate {
|
||||
if ps.verified_key.is_some() {
|
||||
if ps.verified_key().is_some() {
|
||||
return VerifiedStatus::BidirectVerified;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,30 +66,6 @@ pub struct RunningState {
|
||||
pub shall_stop_ongoing: bool,
|
||||
}
|
||||
|
||||
/// Return some info about deltachat-core
|
||||
///
|
||||
/// This contains information mostly about the library itself, the
|
||||
/// actual keys and their values which will be present are not
|
||||
/// guaranteed. Calling [Context::get_info] also includes information
|
||||
/// about the context on top of the information here.
|
||||
pub fn get_info() -> HashMap<&'static str, String> {
|
||||
let mut res = HashMap::new();
|
||||
res.insert("deltachat_core_version", format!("v{}", &*DC_VERSION_STR));
|
||||
res.insert("sqlite_version", rusqlite::version().to_string());
|
||||
res.insert(
|
||||
"sqlite_thread_safe",
|
||||
unsafe { rusqlite::ffi::sqlite3_threadsafe() }.to_string(),
|
||||
);
|
||||
res.insert(
|
||||
"arch",
|
||||
(::std::mem::size_of::<*mut libc::c_void>())
|
||||
.wrapping_mul(8)
|
||||
.to_string(),
|
||||
);
|
||||
res.insert("level", "awesome".into());
|
||||
res
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(cb: Box<ContextCallback>, os_name: String, dbfile: PathBuf) -> Result<Context> {
|
||||
let mut blob_fname = OsString::new();
|
||||
@@ -233,7 +209,19 @@ impl Context {
|
||||
.get_config(self, "configured_mvbox_folder")
|
||||
.unwrap_or_else(|| "<unset>".to_string());
|
||||
|
||||
let mut res = get_info();
|
||||
let mut res = HashMap::new();
|
||||
res.insert("deltachat_core_version", format!("v{}", &*DC_VERSION_STR));
|
||||
res.insert("sqlite_version", rusqlite::version().to_string());
|
||||
res.insert(
|
||||
"sqlite_thread_safe",
|
||||
unsafe { rusqlite::ffi::sqlite3_threadsafe() }.to_string(),
|
||||
);
|
||||
res.insert(
|
||||
"arch",
|
||||
(::std::mem::size_of::<*mut libc::c_void>())
|
||||
.wrapping_mul(8)
|
||||
.to_string(),
|
||||
);
|
||||
res.insert("number_of_chats", chats.to_string());
|
||||
res.insert("number_of_chat_messages", real_msgs.to_string());
|
||||
res.insert("messages_in_contact_requests", deaddrop_msgs.to_string());
|
||||
@@ -263,6 +251,7 @@ impl Context {
|
||||
pub_key_cnt.unwrap_or_default().to_string(),
|
||||
);
|
||||
res.insert("fingerprint", fingerprint_str);
|
||||
res.insert("level", "awesome".into());
|
||||
|
||||
res
|
||||
}
|
||||
@@ -515,14 +504,6 @@ mod tests {
|
||||
let t = dummy_context();
|
||||
|
||||
let info = t.ctx.get_info();
|
||||
assert!(info.get("database_dir").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_info_no_context() {
|
||||
let info = get_info();
|
||||
assert!(info.get("deltachat_core_version").is_some());
|
||||
assert!(info.get("database_dir").is_none());
|
||||
assert_eq!(info.get("level").unwrap(), "awesome");
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,12 +5,13 @@ use std::ptr;
|
||||
use charset::Charset;
|
||||
use deltachat_derive::{FromSql, ToSql};
|
||||
use libc::{strcmp, strlen, strncmp};
|
||||
use mmime::mailimf::types::*;
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf::*;
|
||||
use mmime::mailmime::content::*;
|
||||
use mmime::mailmime::disposition::*;
|
||||
use mmime::mailmime::types::*;
|
||||
use mmime::mailimf_types::*;
|
||||
use mmime::mailmime::*;
|
||||
use mmime::mailmime_content::*;
|
||||
use mmime::mailmime_disposition::*;
|
||||
use mmime::mailmime_types::*;
|
||||
use mmime::mmapstring::*;
|
||||
use mmime::other::*;
|
||||
|
||||
@@ -20,7 +21,7 @@ use crate::context::Context;
|
||||
use crate::dc_simplify::*;
|
||||
use crate::dc_strencode::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::e2ee;
|
||||
use crate::e2ee::*;
|
||||
use crate::error::Error;
|
||||
use crate::location;
|
||||
use crate::param::*;
|
||||
@@ -30,18 +31,16 @@ use crate::stock::StockMessage;
|
||||
pub struct MimeParser<'a> {
|
||||
pub context: &'a Context,
|
||||
pub parts: Vec<Part>,
|
||||
pub mimeroot: *mut Mailmime,
|
||||
pub mimeroot: *mut mailmime,
|
||||
pub header: HashMap<String, *mut mailimf_field>,
|
||||
pub header_root: *mut mailimf_fields,
|
||||
pub header_protected: *mut mailimf_fields,
|
||||
pub subject: Option<String>,
|
||||
pub is_send_by_messenger: bool,
|
||||
pub decrypting_failed: bool,
|
||||
pub encrypted: bool,
|
||||
pub signatures: HashSet<String>,
|
||||
pub gossipped_addr: HashSet<String>,
|
||||
pub e2ee_helper: E2eeHelper,
|
||||
pub is_forwarded: bool,
|
||||
pub reports: Vec<*mut Mailmime>,
|
||||
pub reports: Vec<*mut mailmime>,
|
||||
pub is_system_message: SystemMessage,
|
||||
pub location_kml: Option<location::Kml>,
|
||||
pub message_kml: Option<location::Kml>,
|
||||
@@ -93,9 +92,7 @@ impl<'a> MimeParser<'a> {
|
||||
subject: None,
|
||||
is_send_by_messenger: false,
|
||||
decrypting_failed: false,
|
||||
encrypted: false,
|
||||
signatures: Default::default(),
|
||||
gossipped_addr: Default::default(),
|
||||
e2ee_helper: Default::default(),
|
||||
is_forwarded: false,
|
||||
context,
|
||||
reports: Vec::new(),
|
||||
@@ -105,7 +102,7 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn parse(&mut self, body: &[u8]) -> Result<(), Error> {
|
||||
pub unsafe fn parse(&mut self, body: &[u8]) {
|
||||
let mut index = 0;
|
||||
|
||||
let r = mailmime_parse(
|
||||
@@ -116,11 +113,7 @@ impl<'a> MimeParser<'a> {
|
||||
);
|
||||
|
||||
if r == MAILIMF_NO_ERROR as libc::c_int && !self.mimeroot.is_null() {
|
||||
let (encrypted, signatures, gossipped_addr) =
|
||||
e2ee::try_decrypt(self.context, self.mimeroot)?;
|
||||
self.encrypted = encrypted;
|
||||
self.signatures = signatures;
|
||||
self.gossipped_addr = gossipped_addr;
|
||||
self.e2ee_helper.decrypt(self.context, self.mimeroot);
|
||||
self.parse_mime_recursive(self.mimeroot);
|
||||
|
||||
if let Some(field) = self.lookup_field("Subject") {
|
||||
@@ -324,7 +317,6 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
self.parts.push(part_5);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_last_nonmeta(&mut self) -> Option<&mut Part> {
|
||||
@@ -371,7 +363,7 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn parse_mime_recursive(&mut self, mime: *mut Mailmime) -> bool {
|
||||
unsafe fn parse_mime_recursive(&mut self, mime: *mut mailmime) -> bool {
|
||||
if mime.is_null() {
|
||||
return false;
|
||||
}
|
||||
@@ -436,7 +428,7 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn handle_multiple(&mut self, mime: *mut Mailmime) -> bool {
|
||||
unsafe fn handle_multiple(&mut self, mime: *mut mailmime) -> bool {
|
||||
let mut any_part_added = false;
|
||||
match mailmime_get_mime_type(mime) {
|
||||
/* Most times, mutlipart/alternative contains true alternatives
|
||||
@@ -476,7 +468,7 @@ impl<'a> MimeParser<'a> {
|
||||
however, most times it seems okay. */
|
||||
let cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
|
||||
if !cur.is_null() {
|
||||
any_part_added = self.parse_mime_recursive((*cur).data as *mut Mailmime);
|
||||
any_part_added = self.parse_mime_recursive((*cur).data as *mut mailmime);
|
||||
}
|
||||
}
|
||||
(DC_MIMETYPE_MP_NOT_DECRYPTABLE, _, _) => {
|
||||
@@ -546,7 +538,7 @@ impl<'a> MimeParser<'a> {
|
||||
plain_cnt += 1;
|
||||
}
|
||||
(DC_MIMETYPE_TEXT_HTML, _, _) => {
|
||||
html_part = cur_data as *mut Mailmime;
|
||||
html_part = cur_data as *mut mailmime;
|
||||
html_cnt += 1;
|
||||
}
|
||||
_ => {}
|
||||
@@ -573,7 +565,7 @@ impl<'a> MimeParser<'a> {
|
||||
any_part_added
|
||||
}
|
||||
|
||||
unsafe fn add_single_part_if_known(&mut self, mime: *mut Mailmime) -> bool {
|
||||
unsafe fn add_single_part_if_known(&mut self, mime: *mut mailmime) -> bool {
|
||||
// return true if a part was added
|
||||
if mime.is_null() || (*mime).mm_data.mm_single.is_null() {
|
||||
return false;
|
||||
@@ -801,9 +793,9 @@ impl<'a> MimeParser<'a> {
|
||||
}
|
||||
|
||||
fn do_add_single_part(&mut self, mut part: Part) {
|
||||
if self.encrypted && self.signatures.len() > 0 {
|
||||
if self.e2ee_helper.encrypted && self.e2ee_helper.signatures.len() > 0 {
|
||||
part.param.set_int(Param::GuranteeE2ee, 1);
|
||||
} else if self.encrypted {
|
||||
} else if self.e2ee_helper.encrypted {
|
||||
part.param.set_int(Param::ErroneousE2ee, 0x2);
|
||||
}
|
||||
self.parts.push(part);
|
||||
@@ -897,6 +889,7 @@ impl<'a> Drop for MimeParser<'a> {
|
||||
if !self.mimeroot.is_null() {
|
||||
unsafe { mailmime_free(self.mimeroot) };
|
||||
}
|
||||
unsafe { self.e2ee_helper.thanks() };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -976,7 +969,7 @@ unsafe fn hash_header(out: &mut HashMap<String, *mut mailimf_field>, in_0: *cons
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn mailmime_get_mime_type(mime: *mut Mailmime) -> (libc::c_int, Viewtype, Option<String>) {
|
||||
unsafe fn mailmime_get_mime_type(mime: *mut mailmime) -> (libc::c_int, Viewtype, Option<String>) {
|
||||
let c = (*mime).mm_content_type;
|
||||
|
||||
let unknown_type = (0, Viewtype::Unknown, None);
|
||||
@@ -1063,8 +1056,7 @@ unsafe fn mailmime_get_mime_type(mime: *mut Mailmime) -> (libc::c_int, Viewtype,
|
||||
Some("alternative") => DC_MIMETYPE_MP_ALTERNATIVE,
|
||||
Some("related") => DC_MIMETYPE_MP_RELATED,
|
||||
Some("encrypted") => {
|
||||
// maybe try_decrypt failed to decrypt
|
||||
// or it wasn't in proper Autocrypt format
|
||||
// decryptable parts are already converted to other mime parts in dc_e2ee_decrypt()
|
||||
DC_MIMETYPE_MP_NOT_DECRYPTABLE
|
||||
}
|
||||
Some("signed") => DC_MIMETYPE_MP_SIGNED,
|
||||
@@ -1101,7 +1093,7 @@ fn reconcat_mime(typ: Option<&str>, subtype: Option<&str>) -> String {
|
||||
format!("{}/{}", typ, subtype)
|
||||
}
|
||||
|
||||
unsafe fn mailmime_is_attachment_disposition(mime: *mut Mailmime) -> bool {
|
||||
unsafe fn mailmime_is_attachment_disposition(mime: *mut mailmime) -> bool {
|
||||
if (*mime).mm_mime_fields.is_null() {
|
||||
return false;
|
||||
}
|
||||
@@ -1126,7 +1118,7 @@ unsafe fn mailmime_is_attachment_disposition(mime: *mut Mailmime) -> bool {
|
||||
|
||||
/* low-level-tools for working with mailmime structures directly */
|
||||
pub unsafe fn mailmime_find_ct_parameter(
|
||||
mime: *mut Mailmime,
|
||||
mime: *mut mailmime,
|
||||
name: &str,
|
||||
) -> *mut mailmime_parameter {
|
||||
if mime.is_null()
|
||||
@@ -1148,7 +1140,7 @@ pub unsafe fn mailmime_find_ct_parameter(
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
pub unsafe fn mailmime_transfer_decode(mime: *mut Mailmime) -> Result<Vec<u8>, Error> {
|
||||
pub unsafe fn mailmime_transfer_decode(mime: *mut mailmime) -> Result<Vec<u8>, Error> {
|
||||
ensure!(!mime.is_null(), "invalid inputs");
|
||||
|
||||
let mut mime_transfer_encoding = MAILMIME_MECHANISM_BINARY as libc::c_int;
|
||||
@@ -1211,61 +1203,50 @@ pub unsafe fn mailmime_transfer_decode(mime: *mut Mailmime) -> Result<Vec<u8>, E
|
||||
Err(format_err!("Failed to to decode"))
|
||||
}
|
||||
|
||||
pub fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet<String> {
|
||||
pub unsafe fn mailimf_get_recipients(imffields: *mut mailimf_fields) -> HashSet<String> {
|
||||
/* returned addresses are normalized. */
|
||||
let mut recipients: HashSet<String> = Default::default();
|
||||
|
||||
for cur in unsafe { (*(*imffields).fld_list).into_iter() } {
|
||||
for cur in (*(*imffields).fld_list).into_iter() {
|
||||
let fld = cur as *mut mailimf_field;
|
||||
|
||||
let fld_to: *mut mailimf_to;
|
||||
let fld_cc: *mut mailimf_cc;
|
||||
|
||||
let mut addr_list: *mut mailimf_address_list = ptr::null_mut();
|
||||
if fld.is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let fld = unsafe { *fld };
|
||||
|
||||
// TODO match on enums /rtn
|
||||
match fld.fld_type {
|
||||
match (*fld).fld_type {
|
||||
13 => {
|
||||
fld_to = unsafe { fld.fld_data.fld_to };
|
||||
fld_to = (*fld).fld_data.fld_to;
|
||||
if !fld_to.is_null() {
|
||||
addr_list = unsafe { (*fld_to).to_addr_list };
|
||||
addr_list = (*fld_to).to_addr_list
|
||||
}
|
||||
}
|
||||
14 => {
|
||||
fld_cc = unsafe { fld.fld_data.fld_cc };
|
||||
fld_cc = (*fld).fld_data.fld_cc;
|
||||
if !fld_cc.is_null() {
|
||||
addr_list = unsafe { (*fld_cc).cc_addr_list };
|
||||
addr_list = (*fld_cc).cc_addr_list
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if !addr_list.is_null() {
|
||||
for cur2 in unsafe { &(*(*addr_list).ad_list) } {
|
||||
for cur2 in (*(*addr_list).ad_list).into_iter() {
|
||||
let adr = cur2 as *mut mailimf_address;
|
||||
|
||||
if adr.is_null() {
|
||||
continue;
|
||||
}
|
||||
let adr = unsafe { *adr };
|
||||
|
||||
if adr.ad_type == MAILIMF_ADDRESS_MAILBOX as libc::c_int {
|
||||
mailimf_get_recipients_add_addr(&mut recipients, unsafe {
|
||||
adr.ad_data.ad_mailbox
|
||||
});
|
||||
} else if adr.ad_type == MAILIMF_ADDRESS_GROUP as libc::c_int {
|
||||
let group = unsafe { adr.ad_data.ad_group };
|
||||
if !group.is_null() && unsafe { !(*group).grp_mb_list.is_null() } {
|
||||
for cur3 in unsafe { &(*(*(*group).grp_mb_list).mb_list) } {
|
||||
mailimf_get_recipients_add_addr(
|
||||
&mut recipients,
|
||||
cur3 as *mut mailimf_mailbox,
|
||||
);
|
||||
if !adr.is_null() {
|
||||
if (*adr).ad_type == MAILIMF_ADDRESS_MAILBOX as libc::c_int {
|
||||
mailimf_get_recipients_add_addr(&mut recipients, (*adr).ad_data.ad_mailbox);
|
||||
} else if (*adr).ad_type == MAILIMF_ADDRESS_GROUP as libc::c_int {
|
||||
let group: *mut mailimf_group = (*adr).ad_data.ad_group;
|
||||
if !group.is_null() && !(*group).grp_mb_list.is_null() {
|
||||
for cur3 in (*(*(*group).grp_mb_list).mb_list).into_iter() {
|
||||
mailimf_get_recipients_add_addr(
|
||||
&mut recipients,
|
||||
cur3 as *mut mailimf_mailbox,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1284,33 +1265,37 @@ fn mailimf_get_recipients_add_addr(recipients: &mut HashSet<String>, mb: *mut ma
|
||||
}
|
||||
|
||||
/*the result is a pointer to mime, must not be freed*/
|
||||
pub fn mailimf_find_field(
|
||||
pub unsafe fn mailimf_find_field(
|
||||
header: *mut mailimf_fields,
|
||||
wanted_fld_type: libc::c_int,
|
||||
) -> *mut mailimf_field {
|
||||
if header.is_null() {
|
||||
if header.is_null() || (*header).fld_list.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
let header = unsafe { (*header) };
|
||||
if header.fld_list.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
for cur in unsafe { &(*header.fld_list) } {
|
||||
let field = cur as *mut mailimf_field;
|
||||
let mut cur1: *mut clistiter = (*(*header).fld_list).first;
|
||||
while !cur1.is_null() {
|
||||
let field: *mut mailimf_field = (if !cur1.is_null() {
|
||||
(*cur1).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut mailimf_field;
|
||||
if !field.is_null() {
|
||||
if unsafe { (*field).fld_type } == wanted_fld_type {
|
||||
if (*field).fld_type == wanted_fld_type {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
cur1 = if !cur1.is_null() {
|
||||
(*cur1).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
/*the result is a pointer to mime, must not be freed*/
|
||||
pub unsafe fn mailmime_find_mailimf_fields(mime: *mut Mailmime) -> *mut mailimf_fields {
|
||||
pub unsafe fn mailmime_find_mailimf_fields(mime: *mut mailmime) -> *mut mailimf_fields {
|
||||
if mime.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
@@ -1368,7 +1353,7 @@ mod tests {
|
||||
unsafe {
|
||||
let txt: *const libc::c_char =
|
||||
b"FieldA: ValueA\nFieldB: ValueB\n\x00" as *const u8 as *const libc::c_char;
|
||||
let mut mime: *mut Mailmime = ptr::null_mut();
|
||||
let mut mime: *mut mailmime = ptr::null_mut();
|
||||
let mut dummy = 0;
|
||||
let res = mailmime_parse(txt, strlen(txt), &mut dummy, &mut mime);
|
||||
|
||||
@@ -1441,7 +1426,7 @@ mod tests {
|
||||
let context = dummy_context();
|
||||
let raw = include_bytes!("../test-data/message/issue_523.txt");
|
||||
let mut mimeparser = MimeParser::new(&context.ctx);
|
||||
unsafe { mimeparser.parse(&raw[..]).unwrap() };
|
||||
unsafe { mimeparser.parse(&raw[..]) };
|
||||
assert_eq!(mimeparser.subject, None);
|
||||
assert_eq!(mimeparser.parts.len(), 1);
|
||||
}
|
||||
@@ -1451,7 +1436,7 @@ mod tests {
|
||||
fn test_dc_mailmime_parse_crash_fuzzy(data in "[!-~\t ]{2000,}") {
|
||||
let context = dummy_context();
|
||||
let mut mimeparser = MimeParser::new(&context.ctx);
|
||||
unsafe { mimeparser.parse(data.as_bytes()).unwrap() };
|
||||
unsafe { mimeparser.parse(data.as_bytes()) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1460,7 +1445,7 @@ mod tests {
|
||||
let context = dummy_context();
|
||||
let raw = include_bytes!("../test-data/message/mail_with_message_id.txt");
|
||||
let mut mimeparser = MimeParser::new(&context.ctx);
|
||||
unsafe { mimeparser.parse(&raw[..]).unwrap() };
|
||||
unsafe { mimeparser.parse(&raw[..]) };
|
||||
assert_eq!(
|
||||
mimeparser.get_rfc724_mid(),
|
||||
Some("2dfdbde7@example.org".into())
|
||||
@@ -1472,7 +1457,7 @@ mod tests {
|
||||
let context = dummy_context();
|
||||
let raw = include_bytes!("../test-data/message/issue_523.txt");
|
||||
let mut mimeparser = MimeParser::new(&context.ctx);
|
||||
unsafe { mimeparser.parse(&raw[..]).unwrap() };
|
||||
unsafe { mimeparser.parse(&raw[..]) };
|
||||
assert_eq!(mimeparser.get_rfc724_mid(), None);
|
||||
}
|
||||
|
||||
@@ -1482,7 +1467,7 @@ mod tests {
|
||||
let context = dummy_context();
|
||||
let raw = b"Content-Type: multipart/mixed; boundary=\"==break==\";\nSubject: outer-subject\nX-Special-A: special-a\nFoo: Bar\nChat-Version: 0.0\n\n--==break==\nContent-Type: text/plain; protected-headers=\"v1\";\nSubject: inner-subject\nX-Special-B: special-b\nFoo: Xy\nChat-Version: 1.0\n\ntest1\n\n--==break==--\n\n\x00";
|
||||
let mut mimeparser = MimeParser::new(&context.ctx);
|
||||
mimeparser.parse(&raw[..]).unwrap();
|
||||
mimeparser.parse(&raw[..]);
|
||||
|
||||
assert_eq!(mimeparser.subject, Some("inner-subject".into()));
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ use std::ptr;
|
||||
use itertools::join;
|
||||
use libc::{free, strcmp, strlen};
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf::types::*;
|
||||
use mmime::mailimf::*;
|
||||
use mmime::mailmime::content::*;
|
||||
use mmime::mailmime::types::*;
|
||||
use mmime::mailimf_types::*;
|
||||
use mmime::mailmime::*;
|
||||
use mmime::mailmime_content::*;
|
||||
use mmime::mailmime_types::*;
|
||||
use mmime::other::*;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
@@ -39,7 +39,8 @@ enum CreateEvent {
|
||||
/// Receive a message and add it to the database.
|
||||
pub unsafe fn dc_receive_imf(
|
||||
context: &Context,
|
||||
imf_raw: &[u8],
|
||||
imf_raw_not_terminated: *const libc::c_char,
|
||||
imf_raw_bytes: libc::size_t,
|
||||
server_folder: impl AsRef<str>,
|
||||
server_uid: u32,
|
||||
flags: u32,
|
||||
@@ -60,10 +61,9 @@ pub unsafe fn dc_receive_imf(
|
||||
// we use mailmime_parse() through dc_mimeparser (both call mailimf_struct_multiple_parse()
|
||||
// somewhen, I did not found out anything that speaks against this approach yet)
|
||||
|
||||
let body = std::slice::from_raw_parts(imf_raw_not_terminated as *const u8, imf_raw_bytes);
|
||||
let mut mime_parser = MimeParser::new(context);
|
||||
if let Err(err) = mime_parser.parse(imf_raw) {
|
||||
error!(context, "dc_receive_imf parse error: {}", err);
|
||||
};
|
||||
mime_parser.parse(body);
|
||||
|
||||
if mime_parser.header.is_empty() {
|
||||
// Error - even adding an empty record won't help as we do not know the message ID
|
||||
@@ -204,7 +204,8 @@ pub unsafe fn dc_receive_imf(
|
||||
if let Err(err) = add_parts(
|
||||
context,
|
||||
&mut mime_parser,
|
||||
imf_raw,
|
||||
imf_raw_not_terminated,
|
||||
imf_raw_bytes,
|
||||
incoming,
|
||||
&mut incoming_origin,
|
||||
server_folder.as_ref(),
|
||||
@@ -291,7 +292,8 @@ pub unsafe fn dc_receive_imf(
|
||||
unsafe fn add_parts(
|
||||
context: &Context,
|
||||
mut mime_parser: &mut MimeParser,
|
||||
imf_raw: &[u8],
|
||||
imf_raw_not_terminated: *const libc::c_char,
|
||||
imf_raw_bytes: libc::size_t,
|
||||
incoming: i32,
|
||||
incoming_origin: &mut Origin,
|
||||
server_folder: impl AsRef<str>,
|
||||
@@ -610,7 +612,7 @@ unsafe fn add_parts(
|
||||
let icnt = mime_parser.parts.len();
|
||||
let mut txt_raw = None;
|
||||
|
||||
context
|
||||
let is_ok = context
|
||||
.sql
|
||||
.prepare(
|
||||
"INSERT INTO msgs \
|
||||
@@ -681,7 +683,10 @@ unsafe fn add_parts(
|
||||
part.bytes,
|
||||
*hidden,
|
||||
if save_mime_headers {
|
||||
Some(String::from_utf8_lossy(imf_raw))
|
||||
Some(String::from_utf8_lossy(std::slice::from_raw_parts(
|
||||
imf_raw_not_terminated as *const u8,
|
||||
imf_raw_bytes,
|
||||
)))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
@@ -697,10 +702,13 @@ unsafe fn add_parts(
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.map_err(|err| {
|
||||
cleanup(mime_in_reply_to, mime_references);
|
||||
err
|
||||
})?;
|
||||
.is_ok();
|
||||
|
||||
if !is_ok {
|
||||
// i/o error - there is nothing more we can do - in other cases, we try to write at least an empty record
|
||||
cleanup(mime_in_reply_to, mime_references);
|
||||
bail!("Cannot write DB.");
|
||||
}
|
||||
|
||||
info!(
|
||||
context,
|
||||
@@ -780,7 +788,7 @@ unsafe fn handle_reports(
|
||||
.data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}) as *mut Mailmime;
|
||||
}) as *mut mailmime;
|
||||
|
||||
if !report_data.is_null()
|
||||
&& (*(*(*report_data).mm_content_type).ct_type).tp_type
|
||||
@@ -1147,15 +1155,21 @@ unsafe fn create_or_lookup_group(
|
||||
// check, if we have a chat with this group ID
|
||||
let (mut chat_id, chat_id_verified, _blocked) = chat::get_chat_id_by_grpid(context, &grpid);
|
||||
if chat_id != 0 {
|
||||
if chat_id_verified {
|
||||
if let Err(err) =
|
||||
check_verified_properties(context, mime_parser, from_id as u32, to_ids)
|
||||
{
|
||||
warn!(context, "verification problem: {}", err);
|
||||
let s = format!("{}. See 'Info' for more details", err);
|
||||
mime_parser.repl_msg_by_error(s);
|
||||
}
|
||||
let mut failure_reason = std::ptr::null_mut();
|
||||
|
||||
if chat_id_verified
|
||||
&& 0 == check_verified_properties(
|
||||
context,
|
||||
mime_parser,
|
||||
from_id as u32,
|
||||
to_ids,
|
||||
&mut failure_reason,
|
||||
)
|
||||
{
|
||||
mime_parser.repl_msg_by_error(to_string(failure_reason));
|
||||
}
|
||||
|
||||
free(failure_reason.cast());
|
||||
}
|
||||
|
||||
// check if the sender is a member of the existing group -
|
||||
@@ -1184,14 +1198,18 @@ unsafe fn create_or_lookup_group(
|
||||
let mut create_verified = VerifiedStatus::Unverified;
|
||||
if mime_parser.lookup_field("Chat-Verified").is_some() {
|
||||
create_verified = VerifiedStatus::Verified;
|
||||
let mut failure_reason = std::ptr::null_mut();
|
||||
|
||||
if let Err(err) =
|
||||
check_verified_properties(context, mime_parser, from_id as u32, to_ids)
|
||||
{
|
||||
warn!(context, "verification problem: {}", err);
|
||||
let s = format!("{}. See 'Info' for more details", err);
|
||||
mime_parser.repl_msg_by_error(&s);
|
||||
if 0 == check_verified_properties(
|
||||
context,
|
||||
mime_parser,
|
||||
from_id as u32,
|
||||
to_ids,
|
||||
&mut failure_reason,
|
||||
) {
|
||||
mime_parser.repl_msg_by_error(to_string(failure_reason));
|
||||
}
|
||||
free(failure_reason.cast());
|
||||
}
|
||||
if 0 == allow_creation {
|
||||
cleanup(ret_chat_id, ret_chat_id_blocked, chat_id, chat_id_blocked);
|
||||
@@ -1598,38 +1616,51 @@ fn search_chat_ids_by_contact_ids(context: &Context, unsorted_contact_ids: &Vec<
|
||||
chat_ids
|
||||
}
|
||||
|
||||
fn check_verified_properties(
|
||||
unsafe fn check_verified_properties(
|
||||
context: &Context,
|
||||
mimeparser: &MimeParser,
|
||||
from_id: u32,
|
||||
to_ids: &Vec<u32>,
|
||||
) -> Result<()> {
|
||||
let contact = Contact::load_from_db(context, from_id)?;
|
||||
failure_reason: *mut *mut libc::c_char,
|
||||
) -> libc::c_int {
|
||||
let verify_fail = |reason: String| {
|
||||
*failure_reason = format!("{}. See \"Info\" for details.", reason).strdup();
|
||||
warn!(context, "{}", reason);
|
||||
};
|
||||
|
||||
ensure!(mimeparser.encrypted, "This message is not encrypted.");
|
||||
let contact = match Contact::load_from_db(context, from_id) {
|
||||
Ok(contact) => contact,
|
||||
Err(_err) => {
|
||||
verify_fail("Internal Error; cannot load contact".into());
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
if !mimeparser.e2ee_helper.encrypted {
|
||||
verify_fail("This message is not encrypted".into());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ensure, the contact is verified
|
||||
// and the message is signed with a verified key of the sender.
|
||||
// this check is skipped for SELF as there is no proper SELF-peerstate
|
||||
// and results in group-splits otherwise.
|
||||
if from_id != DC_CONTACT_ID_SELF {
|
||||
if from_id != 1 {
|
||||
let peerstate = Peerstate::from_addr(context, &context.sql, contact.get_addr());
|
||||
|
||||
if peerstate.is_none()
|
||||
|| contact.is_verified_ex(context, peerstate.as_ref())
|
||||
!= VerifiedStatus::BidirectVerified
|
||||
{
|
||||
bail!(
|
||||
"Sender of this message is not verified: {}",
|
||||
contact.get_addr()
|
||||
);
|
||||
verify_fail("The sender of this message is not verified.".into());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if let Some(peerstate) = peerstate {
|
||||
ensure!(
|
||||
peerstate.has_verified_key(&mimeparser.signatures),
|
||||
"The message was sent with non-verified encryption."
|
||||
);
|
||||
if !peerstate.has_verified_key(&mimeparser.e2ee_helper.signatures) {
|
||||
verify_fail("The message was sent with non-verified encryption.".into());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1642,19 +1673,19 @@ fn check_verified_properties(
|
||||
to_ids_str,
|
||||
),
|
||||
params![],
|
||||
|row| Ok((row.get::<_, String>(0)?, row.get::<_, i32>(1).unwrap_or(0))),
|
||||
|row| Ok((row.get::<_, String>(0)?, row.get::<_, i32>(1)?)),
|
||||
|rows| {
|
||||
rows.collect::<std::result::Result<Vec<_>, _>>()
|
||||
.map_err(Into::into)
|
||||
},
|
||||
)?;
|
||||
);
|
||||
|
||||
for (to_addr, _is_verified) in rows.into_iter() {
|
||||
let mut is_verified = _is_verified != 0;
|
||||
if rows.is_err() {
|
||||
return 0;
|
||||
}
|
||||
for (to_addr, mut is_verified) in rows.unwrap().into_iter() {
|
||||
let mut peerstate = Peerstate::from_addr(context, &context.sql, &to_addr);
|
||||
|
||||
// mark gossiped keys (if any) as verified
|
||||
if mimeparser.gossipped_addr.contains(&to_addr) && peerstate.is_some() {
|
||||
if mimeparser.e2ee_helper.gossipped_addr.contains(&to_addr) && peerstate.is_some() {
|
||||
let peerstate = peerstate.as_mut().unwrap();
|
||||
|
||||
// if we're here, we know the gossip key is verified:
|
||||
@@ -1662,27 +1693,29 @@ fn check_verified_properties(
|
||||
// - OR if the verified-key does not match public-key or gossip-key
|
||||
// (otherwise a verified key can _only_ be updated through QR scan which might be annoying,
|
||||
// see https://github.com/nextleap-project/countermitm/issues/46 for a discussion about this point)
|
||||
if !is_verified
|
||||
if 0 == is_verified
|
||||
|| peerstate.verified_key_fingerprint != peerstate.public_key_fingerprint
|
||||
&& peerstate.verified_key_fingerprint != peerstate.gossip_key_fingerprint
|
||||
{
|
||||
info!(context, "{} has verified {}.", contact.get_addr(), to_addr,);
|
||||
info!(context, "{} has verfied {}.", contact.get_addr(), to_addr,);
|
||||
let fp = peerstate.gossip_key_fingerprint.clone();
|
||||
if let Some(fp) = fp {
|
||||
peerstate.set_verified(0, &fp, 2);
|
||||
peerstate.save_to_db(&context.sql, false).unwrap();
|
||||
is_verified = true;
|
||||
peerstate.save_to_db(&context.sql, false);
|
||||
is_verified = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if !is_verified {
|
||||
bail!(
|
||||
if 0 == is_verified {
|
||||
verify_fail(format!(
|
||||
"{} is not a member of this verified group",
|
||||
to_addr.to_string()
|
||||
);
|
||||
to_addr
|
||||
));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
fn set_better_msg(mime_parser: &mut MimeParser, better_msg: impl AsRef<str>) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use itertools::Itertools;
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
use charset::Charset;
|
||||
use libc::{free, strlen};
|
||||
use mmime::mailmime::decode::mailmime_encoded_phrase_parse;
|
||||
use mmime::mailmime_decode::*;
|
||||
use mmime::mmapstring::*;
|
||||
use mmime::other::*;
|
||||
use percent_encoding::{percent_decode, utf8_percent_encode, AsciiSet, CONTROLS};
|
||||
|
||||
@@ -25,49 +25,195 @@ use crate::dc_tools::*;
|
||||
* @return Returns the encoded string which must be free()'d when no longed needed.
|
||||
* On errors, NULL is returned.
|
||||
*/
|
||||
pub fn dc_encode_header_words(input: impl AsRef<str>) -> String {
|
||||
let mut result = String::default();
|
||||
for (_, group) in &input.as_ref().chars().group_by(|c| c.is_whitespace()) {
|
||||
let word: String = group.collect();
|
||||
result.push_str("e_word(&word.as_bytes()));
|
||||
pub unsafe fn dc_encode_header_words(to_encode_r: impl AsRef<str>) -> String {
|
||||
let to_encode =
|
||||
CString::new(to_encode_r.as_ref().as_bytes()).expect("invalid cstring to_encode");
|
||||
|
||||
let mut ok_to_continue = true;
|
||||
let mut ret_str: *mut libc::c_char = ptr::null_mut();
|
||||
let mut cur: *const libc::c_char = to_encode.as_ptr();
|
||||
let mmapstr: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
||||
if mmapstr.is_null() {
|
||||
ok_to_continue = false;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn must_encode(byte: u8) -> bool {
|
||||
static SPECIALS: &[u8] = b",:!\"#$@[\\]^`{|}~=?_";
|
||||
|
||||
SPECIALS.into_iter().any(|b| *b == byte)
|
||||
}
|
||||
|
||||
fn quote_word(word: &[u8]) -> String {
|
||||
let mut result = String::default();
|
||||
let mut encoded = false;
|
||||
|
||||
for byte in word {
|
||||
let byte = *byte;
|
||||
if byte >= 128 || must_encode(byte) {
|
||||
result.push_str(&format!("={:2X}", byte));
|
||||
encoded = true;
|
||||
} else if byte == b' ' {
|
||||
result.push('_');
|
||||
encoded = true;
|
||||
loop {
|
||||
if !ok_to_continue {
|
||||
if !mmapstr.is_null() {
|
||||
mmap_string_free(mmapstr);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
result.push(byte as _);
|
||||
if *cur as libc::c_int != '\u{0}' as i32 {
|
||||
let begin: *const libc::c_char;
|
||||
let mut end: *const libc::c_char;
|
||||
let mut do_quote: bool;
|
||||
let mut quote_words: libc::c_int;
|
||||
begin = cur;
|
||||
end = begin;
|
||||
quote_words = 0i32;
|
||||
do_quote = true;
|
||||
while *cur as libc::c_int != '\u{0}' as i32 {
|
||||
get_word(cur, &mut cur, &mut do_quote);
|
||||
if !do_quote {
|
||||
break;
|
||||
}
|
||||
quote_words = 1i32;
|
||||
end = cur;
|
||||
if *cur as libc::c_int != '\u{0}' as i32 {
|
||||
cur = cur.offset(1isize)
|
||||
}
|
||||
}
|
||||
if 0 != quote_words {
|
||||
if !quote_word(
|
||||
mmapstr,
|
||||
begin,
|
||||
end.wrapping_offset_from(begin) as libc::size_t,
|
||||
) {
|
||||
ok_to_continue = false;
|
||||
continue;
|
||||
}
|
||||
if *end as libc::c_int == ' ' as i32 || *end as libc::c_int == '\t' as i32 {
|
||||
if mmap_string_append_c(mmapstr, *end).is_null() {
|
||||
ok_to_continue = false;
|
||||
continue;
|
||||
}
|
||||
end = end.offset(1isize)
|
||||
}
|
||||
if *end as libc::c_int != '\u{0}' as i32 {
|
||||
if mmap_string_append_len(
|
||||
mmapstr,
|
||||
end,
|
||||
cur.wrapping_offset_from(end) as libc::size_t,
|
||||
)
|
||||
.is_null()
|
||||
{
|
||||
ok_to_continue = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if mmap_string_append_len(
|
||||
mmapstr,
|
||||
begin,
|
||||
cur.wrapping_offset_from(begin) as libc::size_t,
|
||||
)
|
||||
.is_null()
|
||||
{
|
||||
ok_to_continue = false;
|
||||
continue;
|
||||
}
|
||||
if !(*cur as libc::c_int == ' ' as i32 || *cur as libc::c_int == '\t' as i32) {
|
||||
continue;
|
||||
}
|
||||
if mmap_string_append_c(mmapstr, *cur).is_null() {
|
||||
ok_to_continue = false;
|
||||
continue;
|
||||
}
|
||||
cur = cur.offset(1isize);
|
||||
} else {
|
||||
ret_str = strdup((*mmapstr).str_0);
|
||||
ok_to_continue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if encoded {
|
||||
result = format!("=?utf-8?Q?{}?=", &result);
|
||||
let s = to_string(ret_str);
|
||||
free(ret_str.cast());
|
||||
s
|
||||
}
|
||||
|
||||
unsafe fn quote_word(
|
||||
mmapstr: *mut MMAPString,
|
||||
word: *const libc::c_char,
|
||||
size: libc::size_t,
|
||||
) -> bool {
|
||||
let mut cur: *const libc::c_char;
|
||||
let mut i = 0;
|
||||
let mut hex: [libc::c_char; 4] = [0; 4];
|
||||
// let mut col: libc::c_int = 0i32;
|
||||
if mmap_string_append(mmapstr, b"=?utf-8?Q?\x00".as_ptr().cast()).is_null() {
|
||||
return false;
|
||||
}
|
||||
result
|
||||
|
||||
// col = (*mmapstr).len as libc::c_int;
|
||||
cur = word;
|
||||
while i < size {
|
||||
let mut do_quote_char = false;
|
||||
match *cur as u8 as char {
|
||||
',' | ':' | '!' | '"' | '#' | '$' | '@' | '[' | '\\' | ']' | '^' | '`' | '{' | '|'
|
||||
| '}' | '~' | '=' | '?' | '_' => do_quote_char = true,
|
||||
_ => {
|
||||
if *cur as u8 >= 128 {
|
||||
do_quote_char = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if do_quote_char {
|
||||
print_hex(hex.as_mut_ptr(), cur);
|
||||
if mmap_string_append(mmapstr, hex.as_mut_ptr()).is_null() {
|
||||
return false;
|
||||
}
|
||||
// col += 3i32
|
||||
} else {
|
||||
if *cur as libc::c_int == ' ' as i32 {
|
||||
if mmap_string_append_c(mmapstr, '_' as i32 as libc::c_char).is_null() {
|
||||
return false;
|
||||
}
|
||||
} else if mmap_string_append_c(mmapstr, *cur).is_null() {
|
||||
return false;
|
||||
}
|
||||
// col += 3i32
|
||||
}
|
||||
cur = cur.offset(1isize);
|
||||
i = i.wrapping_add(1)
|
||||
}
|
||||
if mmap_string_append(mmapstr, b"?=\x00" as *const u8 as *const libc::c_char).is_null() {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn get_word(
|
||||
begin: *const libc::c_char,
|
||||
pend: *mut *const libc::c_char,
|
||||
pto_be_quoted: *mut bool,
|
||||
) {
|
||||
let mut cur: *const libc::c_char = begin;
|
||||
while *cur as libc::c_int != ' ' as i32
|
||||
&& *cur as libc::c_int != '\t' as i32
|
||||
&& *cur as libc::c_int != '\u{0}' as i32
|
||||
{
|
||||
cur = cur.offset(1isize)
|
||||
}
|
||||
*pto_be_quoted = to_be_quoted(begin, cur.wrapping_offset_from(begin) as libc::size_t);
|
||||
*pend = cur;
|
||||
}
|
||||
|
||||
/* ******************************************************************************
|
||||
* Encode/decode header words, RFC 2047
|
||||
******************************************************************************/
|
||||
|
||||
/* see comment below */
|
||||
unsafe fn to_be_quoted(word: *const libc::c_char, size: libc::size_t) -> bool {
|
||||
let mut cur: *const libc::c_char = word;
|
||||
let mut i = 0;
|
||||
while i < size {
|
||||
match *cur as libc::c_int {
|
||||
44 | 58 | 33 | 34 | 35 | 36 | 64 | 91 | 92 | 93 | 94 | 96 | 123 | 124 | 125 | 126
|
||||
| 61 | 63 | 95 => return true,
|
||||
_ => {
|
||||
if *cur as libc::c_uchar as libc::c_int >= 128i32 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
cur = cur.offset(1isize);
|
||||
i = i.wrapping_add(1)
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub unsafe fn dc_decode_header_words(in_0: *const libc::c_char) -> *mut libc::c_char {
|
||||
if in_0.is_null() {
|
||||
return ptr::null_mut();
|
||||
@@ -173,6 +319,15 @@ pub fn dc_decode_ext_header(to_decode: &[u8]) -> Cow<str> {
|
||||
String::from_utf8_lossy(to_decode)
|
||||
}
|
||||
|
||||
unsafe fn print_hex(target: *mut libc::c_char, cur: *const libc::c_char) {
|
||||
assert!(!target.is_null());
|
||||
assert!(!cur.is_null());
|
||||
|
||||
let bytes = std::slice::from_raw_parts(cur as *const _, strlen(cur));
|
||||
let raw = CString::yolo(format!("={}", &hex::encode_upper(bytes)[..2]));
|
||||
libc::memcpy(target as *mut _, raw.as_ptr() as *const _, 4);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -274,6 +429,18 @@ mod tests {
|
||||
assert_eq!(dc_needs_ext_header("a b"), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_print_hex() {
|
||||
let mut hex: [libc::c_char; 4] = [0; 4];
|
||||
let cur = b"helloworld" as *const u8 as *const libc::c_char;
|
||||
unsafe { print_hex(hex.as_mut_ptr(), cur) };
|
||||
assert_eq!(to_string(hex.as_ptr() as *const _), "=68");
|
||||
|
||||
let cur = b":" as *const u8 as *const libc::c_char;
|
||||
unsafe { print_hex(hex.as_mut_ptr(), cur) };
|
||||
assert_eq!(to_string(hex.as_ptr() as *const _), "=3A");
|
||||
}
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
proptest! {
|
||||
@@ -289,13 +456,5 @@ mod tests {
|
||||
// make sure this never panics
|
||||
let _decoded = dc_decode_ext_header(&buf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dc_header_roundtrip(input: String) {
|
||||
let encoded = dc_encode_header_words(&input);
|
||||
let decoded = dc_decode_header_words_safe(&encoded);
|
||||
|
||||
assert_eq!(input, decoded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ use std::time::SystemTime;
|
||||
use std::{fmt, fs, ptr};
|
||||
|
||||
use chrono::{Local, TimeZone};
|
||||
use libc::{memcpy, strlen};
|
||||
use libc::{memcpy, strcpy, strlen, uintptr_t};
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf::types::*;
|
||||
use mmime::mailimf_types::*;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::context::Context;
|
||||
@@ -149,6 +149,66 @@ pub(crate) fn dc_truncate(buf: &str, approx_chars: usize, do_unwrap: bool) -> Co
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub(crate) unsafe fn dc_truncate_n_unwrap_str(
|
||||
buf: *mut libc::c_char,
|
||||
approx_characters: libc::c_int,
|
||||
do_unwrap: libc::c_int,
|
||||
) {
|
||||
/* Function unwraps the given string and removes unnecessary whitespace.
|
||||
Function stops processing after approx_characters are processed.
|
||||
(as we're using UTF-8, for simplicity, we cut the string only at whitespaces). */
|
||||
/* a single line is truncated `...` instead of `[...]` (the former is typically also used by the UI to fit strings in a rectangle) */
|
||||
let ellipse_utf8: *const libc::c_char = if 0 != do_unwrap {
|
||||
b" ...\x00" as *const u8 as *const libc::c_char
|
||||
} else {
|
||||
b" [...]\x00" as *const u8 as *const libc::c_char
|
||||
};
|
||||
let mut lastIsCharacter: libc::c_int = 0;
|
||||
/* force unsigned - otherwise the `> ' '` comparison will fail */
|
||||
let mut p1: *mut libc::c_uchar = buf as *mut libc::c_uchar;
|
||||
while 0 != *p1 {
|
||||
if *p1 as libc::c_int > ' ' as i32 {
|
||||
lastIsCharacter = 1
|
||||
} else if 0 != lastIsCharacter {
|
||||
let used_bytes = (p1 as uintptr_t).wrapping_sub(buf as uintptr_t) as libc::size_t;
|
||||
if dc_utf8_strnlen(buf, used_bytes) >= approx_characters as usize {
|
||||
let buf_bytes = strlen(buf);
|
||||
if buf_bytes.wrapping_sub(used_bytes) >= strlen(ellipse_utf8) {
|
||||
strcpy(p1 as *mut libc::c_char, ellipse_utf8);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
lastIsCharacter = 0;
|
||||
if 0 != do_unwrap {
|
||||
*p1 = ' ' as i32 as libc::c_uchar
|
||||
}
|
||||
}
|
||||
} else if 0 != do_unwrap {
|
||||
*p1 = '\r' as i32 as libc::c_uchar
|
||||
}
|
||||
p1 = p1.offset(1isize)
|
||||
}
|
||||
if 0 != do_unwrap {
|
||||
dc_remove_cr_chars(buf);
|
||||
};
|
||||
}
|
||||
|
||||
unsafe fn dc_utf8_strnlen(s: *const libc::c_char, n: libc::size_t) -> libc::size_t {
|
||||
if s.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut j: libc::size_t = 0;
|
||||
for i in 0..n {
|
||||
if *s.add(i) as libc::c_int & 0xc0 != 0x80 {
|
||||
j = j.wrapping_add(1)
|
||||
}
|
||||
}
|
||||
|
||||
j
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn dc_str_from_clist(
|
||||
list: *const clist,
|
||||
delimiter: *const libc::c_char,
|
||||
@@ -217,26 +277,26 @@ pub(crate) fn dc_str_to_color(s: impl AsRef<str>) -> u32 {
|
||||
|
||||
/* date/time tools */
|
||||
/* the result is UTC or DC_INVALID_TIMESTAMP */
|
||||
pub(crate) fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 {
|
||||
assert!(!date_time.is_null());
|
||||
let dt = unsafe { *date_time };
|
||||
|
||||
let sec = dt.dt_sec;
|
||||
let min = dt.dt_min;
|
||||
let hour = dt.dt_hour;
|
||||
let day = dt.dt_day;
|
||||
let month = dt.dt_month;
|
||||
let year = dt.dt_year;
|
||||
pub(crate) unsafe fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 {
|
||||
let sec = (*date_time).dt_sec;
|
||||
let min = (*date_time).dt_min;
|
||||
let hour = (*date_time).dt_hour;
|
||||
let day = (*date_time).dt_day;
|
||||
let month = (*date_time).dt_month;
|
||||
let year = (*date_time).dt_year;
|
||||
|
||||
let ts = chrono::NaiveDateTime::new(
|
||||
chrono::NaiveDate::from_ymd(year, month as u32, day as u32),
|
||||
chrono::NaiveTime::from_hms(hour as u32, min as u32, sec as u32),
|
||||
);
|
||||
|
||||
let (zone_hour, zone_min) = if dt.dt_zone >= 0 {
|
||||
(dt.dt_zone / 100, dt.dt_zone % 100)
|
||||
let (zone_hour, zone_min) = if (*date_time).dt_zone >= 0 {
|
||||
((*date_time).dt_zone / 100, (*date_time).dt_zone % 100)
|
||||
} else {
|
||||
(-(-dt.dt_zone / 100), -(-dt.dt_zone % 100))
|
||||
(
|
||||
-(-(*date_time).dt_zone / 100),
|
||||
-(-(*date_time).dt_zone % 100),
|
||||
)
|
||||
};
|
||||
|
||||
ts.timestamp() - (zone_hour * 3600 + zone_min * 60) as i64
|
||||
@@ -470,13 +530,10 @@ pub(crate) fn dc_get_filebytes(context: &Context, path: impl AsRef<std::path::Pa
|
||||
|
||||
pub(crate) fn dc_delete_file(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
|
||||
let path_abs = dc_get_abs_path(context, &path);
|
||||
if !path_abs.exists() {
|
||||
return false;
|
||||
}
|
||||
if !path_abs.is_file() {
|
||||
warn!(
|
||||
context,
|
||||
"refusing to delete non-file \"{}\".",
|
||||
"Will not delete directory \"{}\".",
|
||||
path.as_ref().display()
|
||||
);
|
||||
return false;
|
||||
@@ -1442,7 +1499,6 @@ mod tests {
|
||||
let t = dummy_context();
|
||||
let context = &t.ctx;
|
||||
|
||||
assert!(!dc_delete_file(context, "$BLOBDIR/lkqwjelqkwlje"));
|
||||
if dc_file_exist(context, "$BLOBDIR/foobar")
|
||||
|| dc_file_exist(context, "$BLOBDIR/dada")
|
||||
|| dc_file_exist(context, "$BLOBDIR/foobar.dadada")
|
||||
@@ -1465,7 +1521,6 @@ mod tests {
|
||||
.to_string();
|
||||
|
||||
assert!(dc_is_blobdir_path(context, &abs_path));
|
||||
|
||||
assert!(dc_is_blobdir_path(context, "$BLOBDIR/fofo",));
|
||||
assert!(!dc_is_blobdir_path(context, "/BLOBDIR/fofo",));
|
||||
assert!(dc_file_exist(context, &abs_path));
|
||||
|
||||
866
src/e2ee.rs
866
src/e2ee.rs
File diff suppressed because it is too large
Load Diff
16
src/error.rs
16
src/error.rs
@@ -26,10 +26,6 @@ pub enum Error {
|
||||
CStringError(crate::dc_tools::CStringError),
|
||||
#[fail(display = "PGP: {:?}", _0)]
|
||||
Pgp(pgp::errors::Error),
|
||||
#[fail(display = "Base64Decode: {:?}", _0)]
|
||||
Base64Decode(base64::DecodeError),
|
||||
#[fail(display = "{:?}", _0)]
|
||||
FromUtf8(std::string::FromUtf8Error),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
@@ -40,12 +36,6 @@ impl From<rusqlite::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<base64::DecodeError> for Error {
|
||||
fn from(err: base64::DecodeError) -> Error {
|
||||
Error::Base64Decode(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<failure::Error> for Error {
|
||||
fn from(err: failure::Error) -> Error {
|
||||
Error::Failure(err)
|
||||
@@ -70,12 +60,6 @@ impl From<std::str::Utf8Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::string::FromUtf8Error> for Error {
|
||||
fn from(err: std::string::FromUtf8Error) -> Error {
|
||||
Error::FromUtf8(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<image_meta::ImageError> for Error {
|
||||
fn from(err: image_meta::ImageError) -> Error {
|
||||
Error::Image(err)
|
||||
|
||||
@@ -167,7 +167,7 @@ pub enum Event {
|
||||
#[strum(props(id = "2041"))]
|
||||
ConfigureProgress(usize),
|
||||
|
||||
/// Inform about the import/export progress started by imex().
|
||||
/// Inform about the import/export progress started by dc_imex().
|
||||
///
|
||||
/// @param data1 (usize) 0=error, 1-999=progress in permille, 1000=success and done
|
||||
/// @param data2 0
|
||||
@@ -175,8 +175,8 @@ pub enum Event {
|
||||
#[strum(props(id = "2051"))]
|
||||
ImexProgress(usize),
|
||||
|
||||
/// A file has been exported. A file has been written by imex().
|
||||
/// This event may be sent multiple times by a single call to imex().
|
||||
/// A file has been exported. A file has been written by dc_imex().
|
||||
/// This event may be sent multiple times by a single call to dc_imex().
|
||||
///
|
||||
/// A typical purpose for a handler of this event may be to make the file public to some system
|
||||
/// services.
|
||||
|
||||
11
src/imap.rs
11
src/imap.rs
@@ -110,8 +110,6 @@ impl Client {
|
||||
) -> imap::error::Result<Self> {
|
||||
let stream = net::TcpStream::connect(addr)?;
|
||||
let tls = native_tls::TlsConnector::builder()
|
||||
// see also: https://github.com/deltachat/deltachat-core-rust/issues/203
|
||||
.danger_accept_invalid_certs(true)
|
||||
.danger_accept_invalid_hostnames(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
@@ -955,7 +953,14 @@ impl Imap {
|
||||
if !is_deleted && msg.body().is_some() {
|
||||
let body = msg.body().unwrap();
|
||||
unsafe {
|
||||
dc_receive_imf(context, &body, folder.as_ref(), server_uid, flags as u32);
|
||||
dc_receive_imf(
|
||||
context,
|
||||
body.as_ptr() as *const libc::c_char,
|
||||
body.len(),
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
flags as u32,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
216
src/job.rs
216
src/job.rs
@@ -7,14 +7,14 @@ use crate::chat;
|
||||
use crate::configure::*;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_imex::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::events::Event;
|
||||
use crate::imap::*;
|
||||
use crate::imex::*;
|
||||
use crate::location;
|
||||
use crate::login_param::LoginParam;
|
||||
use crate::message::{self, Message, MessageState};
|
||||
use crate::mimefactory::{vec_contains_lowercase, Loaded, MimeFactory};
|
||||
use crate::mimefactory::*;
|
||||
use crate::param::*;
|
||||
use crate::sql;
|
||||
|
||||
@@ -206,49 +206,57 @@ impl Job {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn do_DC_JOB_MOVE_MSG(&mut self, context: &Context) {
|
||||
let ok_to_continue;
|
||||
let mut dest_uid = 0;
|
||||
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
self.try_again_later(3, None);
|
||||
return;
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
if let Ok(msg) = Message::load_from_db(context, self.foreign_id) {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
inbox.configure_folders(context, 0x1i32);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
if ok_to_continue {
|
||||
if let Ok(msg) = Message::load_from_db(context, self.foreign_id) {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
inbox.configure_folders(context, 0x1i32);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
let mut dest_uid = 0;
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
|
||||
match inbox.mv(
|
||||
context,
|
||||
server_folder,
|
||||
msg.server_uid,
|
||||
&dest_folder,
|
||||
&mut dest_uid,
|
||||
) {
|
||||
ImapResult::RetryLater => {
|
||||
self.try_again_later(3i32, None);
|
||||
match inbox.mv(
|
||||
context,
|
||||
server_folder,
|
||||
msg.server_uid,
|
||||
&dest_folder,
|
||||
&mut dest_uid,
|
||||
) {
|
||||
ImapResult::RetryLater => {
|
||||
self.try_again_later(3i32, None);
|
||||
}
|
||||
ImapResult::Success => {
|
||||
message::update_server_uid(
|
||||
context,
|
||||
&msg.rfc724_mid,
|
||||
&dest_folder,
|
||||
dest_uid,
|
||||
);
|
||||
}
|
||||
ImapResult::Failed | ImapResult::AlreadyDone => {}
|
||||
}
|
||||
ImapResult::Success => {
|
||||
message::update_server_uid(
|
||||
context,
|
||||
&msg.rfc724_mid,
|
||||
&dest_folder,
|
||||
dest_uid,
|
||||
);
|
||||
}
|
||||
ImapResult::Failed | ImapResult::AlreadyDone => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,75 +264,99 @@ impl Job {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn do_DC_JOB_DELETE_MSG_ON_IMAP(&mut self, context: &Context) {
|
||||
let mut delete_from_server = 1;
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
|
||||
if let Ok(mut msg) = Message::load_from_db(context, self.foreign_id) {
|
||||
if !msg.rfc724_mid.is_empty() {
|
||||
let ok_to_continue1;
|
||||
/* eg. device messages have no Message-ID */
|
||||
let mut delete_from_server = true;
|
||||
if message::rfc724_mid_cnt(context, &msg.rfc724_mid) != 1 {
|
||||
info!(
|
||||
context,
|
||||
"The message is deleted from the server when all parts are deleted.",
|
||||
);
|
||||
delete_from_server = false;
|
||||
delete_from_server = 0i32
|
||||
}
|
||||
/* if this is the last existing part of the message, we delete the message from the server */
|
||||
if delete_from_server {
|
||||
if 0 != delete_from_server {
|
||||
let ok_to_continue;
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
self.try_again_later(3i32, None);
|
||||
return;
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
let mid = msg.rfc724_mid;
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
if 0 == inbox.delete_msg(context, &mid, server_folder, &mut msg.server_uid) {
|
||||
self.try_again_later(-1i32, None);
|
||||
return;
|
||||
if ok_to_continue {
|
||||
let mid = msg.rfc724_mid;
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
if 0 == inbox.delete_msg(context, &mid, server_folder, &mut msg.server_uid)
|
||||
{
|
||||
self.try_again_later(-1i32, None);
|
||||
ok_to_continue1 = false;
|
||||
} else {
|
||||
ok_to_continue1 = true;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue1 = false;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue1 = true;
|
||||
}
|
||||
if ok_to_continue1 {
|
||||
Message::delete_from_db(context, msg.id);
|
||||
}
|
||||
Message::delete_from_db(context, msg.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn do_DC_JOB_MARKSEEN_MSG_ON_IMAP(&mut self, context: &Context) {
|
||||
let ok_to_continue;
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
self.try_again_later(3i32, None);
|
||||
return;
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
if let Ok(msg) = Message::load_from_db(context, self.foreign_id) {
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
match inbox.set_seen(context, server_folder, msg.server_uid) {
|
||||
ImapResult::Failed => {}
|
||||
ImapResult::RetryLater => {
|
||||
self.try_again_later(3i32, None);
|
||||
}
|
||||
_ => {
|
||||
if 0 != msg.param.get_int(Param::WantsMdn).unwrap_or_default()
|
||||
&& 0 != context
|
||||
.sql
|
||||
.get_config_int(context, "mdns_enabled")
|
||||
.unwrap_or_else(|| 1)
|
||||
{
|
||||
let folder = msg.server_folder.as_ref().unwrap();
|
||||
if ok_to_continue {
|
||||
if let Ok(msg) = Message::load_from_db(context, self.foreign_id) {
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
match inbox.set_seen(context, server_folder, msg.server_uid) {
|
||||
ImapResult::Failed => {}
|
||||
ImapResult::RetryLater => {
|
||||
self.try_again_later(3i32, None);
|
||||
}
|
||||
_ => {
|
||||
if 0 != msg.param.get_int(Param::WantsMdn).unwrap_or_default()
|
||||
&& 0 != context
|
||||
.sql
|
||||
.get_config_int(context, "mdns_enabled")
|
||||
.unwrap_or_else(|| 1)
|
||||
{
|
||||
let folder = msg.server_folder.as_ref().unwrap();
|
||||
|
||||
match inbox.set_mdnsent(context, folder, msg.server_uid) {
|
||||
ImapResult::RetryLater => {
|
||||
self.try_again_later(3i32, None);
|
||||
match inbox.set_mdnsent(context, folder, msg.server_uid) {
|
||||
ImapResult::RetryLater => {
|
||||
self.try_again_later(3i32, None);
|
||||
}
|
||||
ImapResult::Success => {
|
||||
send_mdn(context, msg.id);
|
||||
}
|
||||
ImapResult::Failed | ImapResult::AlreadyDone => {}
|
||||
}
|
||||
ImapResult::Success => {
|
||||
send_mdn(context, msg.id);
|
||||
}
|
||||
ImapResult::Failed | ImapResult::AlreadyDone => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,40 +366,47 @@ impl Job {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn do_DC_JOB_MARKSEEN_MDN_ON_IMAP(&mut self, context: &Context) {
|
||||
let ok_to_continue;
|
||||
let folder = self
|
||||
.param
|
||||
.get(Param::ServerFolder)
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let uid = self.param.get_int(Param::ServerUid).unwrap_or_default() as u32;
|
||||
let mut dest_uid = 0;
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
self.try_again_later(3, None);
|
||||
return;
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
if inbox.set_seen(context, &folder, uid) == ImapResult::Failed {
|
||||
self.try_again_later(3i32, None);
|
||||
}
|
||||
if 0 != self.param.get_int(Param::AlsoMove).unwrap_or_default() {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
inbox.configure_folders(context, 0x1i32);
|
||||
if ok_to_continue {
|
||||
if inbox.set_seen(context, &folder, uid) == ImapResult::Failed {
|
||||
self.try_again_later(3i32, None);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
let mut dest_uid = 0;
|
||||
if ImapResult::RetryLater
|
||||
== inbox.mv(context, folder, uid, dest_folder, &mut dest_uid)
|
||||
if 0 != self.param.get_int(Param::AlsoMove).unwrap_or_default() {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
self.try_again_later(3, None);
|
||||
inbox.configure_folders(context, 0x1i32);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
if ImapResult::RetryLater
|
||||
== inbox.mv(context, folder, uid, dest_folder, &mut dest_uid)
|
||||
{
|
||||
self.try_again_later(3, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -824,12 +863,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||
Action::MoveMsg => job.do_DC_JOB_MOVE_MSG(context),
|
||||
Action::SendMdn => job.do_DC_JOB_SEND(context),
|
||||
Action::ConfigureImap => unsafe { dc_job_do_DC_JOB_CONFIGURE_IMAP(context) },
|
||||
Action::ImexImap => match job_do_DC_JOB_IMEX_IMAP(context, &job) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
error!(context, "{}", err);
|
||||
}
|
||||
},
|
||||
Action::ImexImap => unsafe { dc_job_do_DC_JOB_IMEX_IMAP(context, &job) },
|
||||
Action::MaybeSendLocations => {
|
||||
location::job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context, &job)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::collections::BTreeMap;
|
||||
use std::io::Cursor;
|
||||
use std::path::Path;
|
||||
|
||||
use libc;
|
||||
use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey};
|
||||
use pgp::ser::Serialize;
|
||||
use pgp::types::{KeyTrait, SecretKeyTrait};
|
||||
@@ -253,14 +254,14 @@ pub fn dc_key_save_self_keypair(
|
||||
public_key: &Key,
|
||||
private_key: &Key,
|
||||
addr: impl AsRef<str>,
|
||||
is_default: bool,
|
||||
is_default: libc::c_int,
|
||||
sql: &Sql,
|
||||
) -> bool {
|
||||
sql::execute(
|
||||
context,
|
||||
sql,
|
||||
"INSERT INTO keypairs (addr, is_default, public_key, private_key, created) VALUES (?,?,?,?,?);",
|
||||
params![addr.as_ref(), is_default as i32, public_key.to_bytes(), private_key.to_bytes(), time()],
|
||||
params![addr.as_ref(), is_default, public_key.to_bytes(), private_key.to_bytes(), time()],
|
||||
).is_ok()
|
||||
}
|
||||
|
||||
|
||||
14
src/lib.rs
14
src/lib.rs
@@ -39,36 +39,36 @@ pub mod contact;
|
||||
pub mod context;
|
||||
mod e2ee;
|
||||
mod imap;
|
||||
pub mod imex;
|
||||
pub mod job;
|
||||
mod job_thread;
|
||||
pub mod key;
|
||||
pub mod keyring;
|
||||
pub mod location;
|
||||
mod login_param;
|
||||
pub mod lot;
|
||||
pub mod message;
|
||||
mod mimefactory;
|
||||
pub mod oauth2;
|
||||
mod param;
|
||||
pub mod peerstate;
|
||||
pub mod pgp;
|
||||
pub mod qr;
|
||||
pub mod securejoin;
|
||||
mod smtp;
|
||||
pub mod sql;
|
||||
mod stock;
|
||||
mod token;
|
||||
#[macro_use]
|
||||
mod wrapmime;
|
||||
|
||||
pub mod dc_array;
|
||||
mod dc_dehtml;
|
||||
pub mod dc_imex;
|
||||
pub mod dc_mimeparser;
|
||||
pub mod dc_receive_imf;
|
||||
mod dc_simplify;
|
||||
mod dc_strencode;
|
||||
pub mod dc_tools;
|
||||
mod login_param;
|
||||
mod mimefactory;
|
||||
pub mod securejoin;
|
||||
mod token;
|
||||
#[macro_use]
|
||||
mod wrapmime;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_utils;
|
||||
|
||||
@@ -2,6 +2,8 @@ use std::path::{Path, PathBuf};
|
||||
use std::ptr;
|
||||
|
||||
use deltachat_derive::{FromSql, ToSql};
|
||||
use libc::{free, strcmp};
|
||||
use phf::phf_map;
|
||||
|
||||
use crate::chat::{self, Chat};
|
||||
use crate::constants::*;
|
||||
@@ -107,6 +109,18 @@ impl Message {
|
||||
msg.hidden = row.get(18)?;
|
||||
msg.location_id = row.get(19)?;
|
||||
msg.chat_blocked = row.get::<_, Option<Blocked>>(20)?.unwrap_or_default();
|
||||
if msg.chat_blocked == Blocked::Deaddrop {
|
||||
if let Some(ref text) = msg.text {
|
||||
unsafe {
|
||||
let ptr = text.strdup();
|
||||
|
||||
dc_truncate_n_unwrap_str(ptr, 256, 0);
|
||||
|
||||
msg.text = Some(to_string(ptr));
|
||||
free(ptr.cast());
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(msg)
|
||||
})
|
||||
}
|
||||
@@ -130,18 +144,16 @@ impl Message {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_filemime(&self) -> Option<String> {
|
||||
pub fn get_filemime(&self) -> String {
|
||||
if let Some(m) = self.param.get(Param::MimeType) {
|
||||
return Some(m.to_string());
|
||||
return m.to_string();
|
||||
} else if let Some(file) = self.param.get(Param::File) {
|
||||
if let Some((_, mime)) = guess_msgtype_from_suffix(Path::new(file)) {
|
||||
return Some(mime.to_string());
|
||||
return mime.to_string();
|
||||
}
|
||||
// we have a file but no mimetype, let's use a generic one
|
||||
return Some("application/octet-stream".to_string());
|
||||
}
|
||||
// no mimetype and no file
|
||||
None
|
||||
|
||||
"application/octet-stream".to_string()
|
||||
}
|
||||
|
||||
pub fn get_file(&self, context: &Context) -> Option<PathBuf> {
|
||||
@@ -334,7 +346,7 @@ impl Message {
|
||||
}
|
||||
|
||||
pub fn get_setupcodebegin(&self, context: &Context) -> Option<String> {
|
||||
if !self.is_setupmessage() {
|
||||
if self.is_setupmessage() {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -342,7 +354,7 @@ impl Message {
|
||||
if let Ok(mut buf) = dc_read_file(context, filename) {
|
||||
unsafe {
|
||||
// just a pointer inside buf, MUST NOT be free()'d
|
||||
let mut buf_headerline = String::default();
|
||||
let mut buf_headerline = ptr::null();
|
||||
// just a pointer inside buf, MUST NOT be free()'d
|
||||
let mut buf_setupcodebegin = ptr::null();
|
||||
|
||||
@@ -352,7 +364,10 @@ impl Message {
|
||||
&mut buf_setupcodebegin,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
) && buf_headerline == "-----BEGIN PGP MESSAGE-----"
|
||||
) && strcmp(
|
||||
buf_headerline,
|
||||
b"-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
&& !buf_setupcodebegin.is_null()
|
||||
{
|
||||
return Some(to_string(buf_setupcodebegin));
|
||||
@@ -632,7 +647,7 @@ pub fn get_msg_info(context: &Context, msg_id: u32) -> String {
|
||||
ret += "Type: ";
|
||||
ret += &format!("{}", msg.type_0);
|
||||
ret += "\n";
|
||||
ret += &format!("Mimetype: {}\n", &msg.get_filemime().unwrap_or_default());
|
||||
ret += &format!("Mimetype: {}\n", &msg.get_filemime());
|
||||
}
|
||||
let w = msg.param.get_int(Param::Width).unwrap_or_default();
|
||||
let h = msg.param.get_int(Param::Height).unwrap_or_default();
|
||||
@@ -659,24 +674,22 @@ pub fn get_msg_info(context: &Context, msg_id: u32) -> String {
|
||||
}
|
||||
|
||||
pub fn guess_msgtype_from_suffix(path: &Path) -> Option<(Viewtype, &str)> {
|
||||
let extension: &str = &path.extension()?.to_str()?.to_lowercase();
|
||||
let info = match extension {
|
||||
"mp3" => (Viewtype::Audio, "audio/mpeg"),
|
||||
"aac" => (Viewtype::Audio, "audio/aac"),
|
||||
"mp4" => (Viewtype::Video, "video/mp4"),
|
||||
"jpg" => (Viewtype::Image, "image/jpeg"),
|
||||
"jpeg" => (Viewtype::Image, "image/jpeg"),
|
||||
"jpe" => (Viewtype::Image, "image/jpeg"),
|
||||
"png" => (Viewtype::Image, "image/png"),
|
||||
"webp" => (Viewtype::Image, "image/webp"),
|
||||
"gif" => (Viewtype::Gif, "image/gif"),
|
||||
"vcf" => (Viewtype::File, "text/vcard"),
|
||||
"vcard" => (Viewtype::File, "text/vcard"),
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
static KNOWN: phf::Map<&'static str, (Viewtype, &'static str)> = phf_map! {
|
||||
"mp3" => (Viewtype::Audio, "audio/mpeg"),
|
||||
"aac" => (Viewtype::Audio, "audio/aac"),
|
||||
"mp4" => (Viewtype::Video, "video/mp4"),
|
||||
"jpg" => (Viewtype::Image, "image/jpeg"),
|
||||
"jpeg" => (Viewtype::Image, "image/jpeg"),
|
||||
"jpe" => (Viewtype::Image, "image/jpeg"),
|
||||
"png" => (Viewtype::Image, "image/png"),
|
||||
"webp" => (Viewtype::Image, "image/webp"),
|
||||
"gif" => (Viewtype::Gif, "image/gif"),
|
||||
"vcf" => (Viewtype::File, "text/vcard"),
|
||||
"vcard" => (Viewtype::File, "text/vcard"),
|
||||
};
|
||||
Some(info)
|
||||
let extension: &str = &path.extension()?.to_str()?.to_lowercase();
|
||||
|
||||
KNOWN.get(extension).map(|x| *x)
|
||||
}
|
||||
|
||||
pub fn get_mime_headers(context: &Context, msg_id: u32) -> Option<String> {
|
||||
@@ -1143,6 +1156,5 @@ mod tests {
|
||||
let msg_id = chat::prepare_msg(ctx, chat, &mut msg).unwrap();
|
||||
|
||||
let _msg2 = Message::load_from_db(ctx, msg_id).unwrap();
|
||||
assert_eq!(_msg2.get_filemime(), None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ use std::ptr;
|
||||
|
||||
use chrono::TimeZone;
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf::types::*;
|
||||
use mmime::mailimf::types_helper::*;
|
||||
use mmime::mailmime::disposition::*;
|
||||
use mmime::mailmime::types::*;
|
||||
use mmime::mailmime::types_helper::*;
|
||||
use mmime::mailmime::write_mem::*;
|
||||
use mmime::mailimf_types::*;
|
||||
use mmime::mailimf_types_helper::*;
|
||||
use mmime::mailmime_disposition::*;
|
||||
use mmime::mailmime_types::*;
|
||||
use mmime::mailmime_types_helper::*;
|
||||
use mmime::mailmime_write_mem::*;
|
||||
use mmime::mmapstring::*;
|
||||
use mmime::other::*;
|
||||
|
||||
@@ -86,7 +86,7 @@ impl<'a> MimeFactory<'a> {
|
||||
|
||||
pub fn finalize_mime_message(
|
||||
&mut self,
|
||||
message: *mut Mailmime,
|
||||
message: *mut mailmime,
|
||||
encrypted: bool,
|
||||
gossiped: bool,
|
||||
) -> Result<(), Error> {
|
||||
@@ -236,12 +236,12 @@ impl<'a> MimeFactory<'a> {
|
||||
);
|
||||
}
|
||||
|
||||
let cleanup = |message: *mut Mailmime| {
|
||||
let cleanup = |message: *mut mailmime| {
|
||||
if !message.is_null() {
|
||||
mailmime_free(message);
|
||||
}
|
||||
};
|
||||
let message = mailmime_new_message_data(0 as *mut Mailmime);
|
||||
let message = mailmime_new_message_data(0 as *mut mailmime);
|
||||
ensure!(!message.is_null(), "could not create mime message data");
|
||||
|
||||
mailmime_set_imf_fields(message, imf_fields);
|
||||
@@ -257,7 +257,7 @@ impl<'a> MimeFactory<'a> {
|
||||
/* Render a normal message
|
||||
*********************************************************************/
|
||||
let chat = self.chat.as_ref().unwrap();
|
||||
let mut meta_part: *mut Mailmime = ptr::null_mut();
|
||||
let mut meta_part: *mut mailmime = ptr::null_mut();
|
||||
let mut placeholdertext = None;
|
||||
|
||||
if chat.typ == Chattype::VerifiedGroup {
|
||||
@@ -589,7 +589,7 @@ impl<'a> MimeFactory<'a> {
|
||||
wrapmime::new_content_type("message/disposition-notification")?;
|
||||
let mime_fields_0: *mut mailmime_fields =
|
||||
mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int);
|
||||
let mach_mime_part: *mut Mailmime =
|
||||
let mach_mime_part: *mut mailmime =
|
||||
mailmime_new_empty(content_type_0, mime_fields_0);
|
||||
wrapmime::set_body_text(mach_mime_part, &message_text2)?;
|
||||
mailmime_add_part(multipart, mach_mime_part);
|
||||
@@ -821,7 +821,7 @@ fn build_body_file(
|
||||
context: &Context,
|
||||
msg: &Message,
|
||||
base_name: &str,
|
||||
) -> Result<(*mut Mailmime, String), Error> {
|
||||
) -> Result<(*mut mailmime, String), Error> {
|
||||
let path_filename = match msg.param.get(Param::File) {
|
||||
None => {
|
||||
bail!("msg has no filename");
|
||||
|
||||
100
src/peerstate.rs
100
src/peerstate.rs
@@ -7,7 +7,6 @@ use crate::aheader::*;
|
||||
use crate::chat::*;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::error::*;
|
||||
use crate::key::*;
|
||||
use crate::sql::{self, Sql};
|
||||
|
||||
@@ -23,7 +22,7 @@ pub struct Peerstate<'a> {
|
||||
pub gossip_key: Option<Key>,
|
||||
pub gossip_timestamp: i64,
|
||||
pub gossip_key_fingerprint: Option<String>,
|
||||
pub verified_key: Option<Key>,
|
||||
verified_key: VerifiedKey,
|
||||
pub verified_key_fingerprint: Option<String>,
|
||||
pub to_save: Option<ToSave>,
|
||||
pub degrade_event: Option<DegradeEvent>,
|
||||
@@ -85,6 +84,32 @@ pub enum DegradeEvent {
|
||||
FingerprintChanged = 0x02,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum VerifiedKey {
|
||||
Gossip,
|
||||
Public,
|
||||
None,
|
||||
}
|
||||
|
||||
impl Default for VerifiedKey {
|
||||
fn default() -> Self {
|
||||
VerifiedKey::None
|
||||
}
|
||||
}
|
||||
|
||||
impl VerifiedKey {
|
||||
pub fn is_none(&self) -> bool {
|
||||
match self {
|
||||
VerifiedKey::None => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_some(&self) -> bool {
|
||||
!self.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Peerstate<'a> {
|
||||
pub fn new(context: &'a Context) -> Self {
|
||||
Peerstate {
|
||||
@@ -98,13 +123,21 @@ impl<'a> Peerstate<'a> {
|
||||
gossip_key: None,
|
||||
gossip_key_fingerprint: None,
|
||||
gossip_timestamp: 0,
|
||||
verified_key: None,
|
||||
verified_key: Default::default(),
|
||||
verified_key_fingerprint: None,
|
||||
to_save: None,
|
||||
degrade_event: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verified_key(&self) -> Option<&Key> {
|
||||
match self.verified_key {
|
||||
VerifiedKey::Public => self.public_key.as_ref(),
|
||||
VerifiedKey::Gossip => self.gossip_key.as_ref(),
|
||||
VerifiedKey::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_header(context: &'a Context, header: &Aheader, message_time: i64) -> Self {
|
||||
let mut res = Self::new(context);
|
||||
|
||||
@@ -208,11 +241,19 @@ impl<'a> Peerstate<'a> {
|
||||
.get(6)
|
||||
.ok()
|
||||
.and_then(|blob: Vec<u8>| Key::from_slice(&blob, KeyType::Public));
|
||||
res.verified_key = row
|
||||
let vk = row
|
||||
.get(9)
|
||||
.ok()
|
||||
.and_then(|blob: Vec<u8>| Key::from_slice(&blob, KeyType::Public));
|
||||
|
||||
res.verified_key = if vk == res.gossip_key && res.gossip_key.is_some() {
|
||||
VerifiedKey::Gossip
|
||||
} else if vk == res.public_key {
|
||||
VerifiedKey::Public
|
||||
} else {
|
||||
VerifiedKey::None
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
})
|
||||
.ok()
|
||||
@@ -332,7 +373,7 @@ impl<'a> Peerstate<'a> {
|
||||
}
|
||||
|
||||
if 0 != min_verified {
|
||||
return self.verified_key.as_ref();
|
||||
return self.verified_key();
|
||||
}
|
||||
if self.public_key.is_some() {
|
||||
return self.public_key.as_ref();
|
||||
@@ -349,7 +390,7 @@ impl<'a> Peerstate<'a> {
|
||||
&& self.public_key_fingerprint.as_ref().unwrap() == fingerprint
|
||||
{
|
||||
self.to_save = Some(ToSave::All);
|
||||
self.verified_key = self.public_key.clone();
|
||||
self.verified_key = VerifiedKey::Public;
|
||||
self.verified_key_fingerprint = self.public_key_fingerprint.clone();
|
||||
success = true;
|
||||
}
|
||||
@@ -358,7 +399,7 @@ impl<'a> Peerstate<'a> {
|
||||
&& self.gossip_key_fingerprint.as_ref().unwrap() == fingerprint
|
||||
{
|
||||
self.to_save = Some(ToSave::All);
|
||||
self.verified_key = self.gossip_key.clone();
|
||||
self.verified_key = VerifiedKey::Gossip;
|
||||
self.verified_key_fingerprint = self.gossip_key_fingerprint.clone();
|
||||
success = true;
|
||||
}
|
||||
@@ -367,19 +408,28 @@ impl<'a> Peerstate<'a> {
|
||||
success
|
||||
}
|
||||
|
||||
pub fn save_to_db(&self, sql: &Sql, create: bool) -> Result<()> {
|
||||
ensure!(!self.addr.is_none(), "self.addr is not configured");
|
||||
pub fn save_to_db(&self, sql: &Sql, create: bool) -> bool {
|
||||
let mut success = false;
|
||||
|
||||
if self.addr.is_none() {
|
||||
return success;
|
||||
}
|
||||
|
||||
if create {
|
||||
sql::execute(
|
||||
if sql::execute(
|
||||
self.context,
|
||||
sql,
|
||||
"INSERT INTO acpeerstates (addr) VALUES(?);",
|
||||
params![self.addr.as_ref().unwrap()],
|
||||
)?;
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if self.to_save == Some(ToSave::All) || create {
|
||||
sql::execute(
|
||||
success = sql::execute(
|
||||
self.context,
|
||||
sql,
|
||||
"UPDATE acpeerstates \
|
||||
@@ -396,13 +446,14 @@ impl<'a> Peerstate<'a> {
|
||||
self.gossip_key.as_ref().map(|k| k.to_bytes()),
|
||||
&self.public_key_fingerprint,
|
||||
&self.gossip_key_fingerprint,
|
||||
self.verified_key.as_ref().map(|k| k.to_bytes()),
|
||||
self.verified_key().map(|k| k.to_bytes()),
|
||||
&self.verified_key_fingerprint,
|
||||
&self.addr,
|
||||
],
|
||||
)?
|
||||
).is_ok();
|
||||
assert_eq!(success, true);
|
||||
} else if self.to_save == Some(ToSave::Timestamps) {
|
||||
sql::execute(
|
||||
success = sql::execute(
|
||||
self.context,
|
||||
sql,
|
||||
"UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, gossip_timestamp=? \
|
||||
@@ -413,14 +464,15 @@ impl<'a> Peerstate<'a> {
|
||||
self.gossip_timestamp,
|
||||
&self.addr
|
||||
],
|
||||
)?;
|
||||
)
|
||||
.is_ok();
|
||||
}
|
||||
|
||||
if self.to_save == Some(ToSave::All) || create {
|
||||
reset_gossiped_timestamp(self.context, 0);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
success
|
||||
}
|
||||
|
||||
pub fn has_verified_key(&self, fingerprints: &HashSet<String>) -> bool {
|
||||
@@ -464,16 +516,13 @@ mod tests {
|
||||
gossip_key: Some(pub_key.clone()),
|
||||
gossip_timestamp: 12,
|
||||
gossip_key_fingerprint: Some(pub_key.fingerprint()),
|
||||
verified_key: Some(pub_key.clone()),
|
||||
verified_key: VerifiedKey::Gossip,
|
||||
verified_key_fingerprint: Some(pub_key.fingerprint()),
|
||||
to_save: Some(ToSave::All),
|
||||
degrade_event: None,
|
||||
};
|
||||
|
||||
assert!(
|
||||
peerstate.save_to_db(&ctx.ctx.sql, true).is_ok(),
|
||||
"failed to save to db"
|
||||
);
|
||||
assert!(peerstate.save_to_db(&ctx.ctx.sql, true), "failed to save");
|
||||
|
||||
let peerstate_new = Peerstate::from_addr(&ctx.ctx, &ctx.ctx.sql, addr.into())
|
||||
.expect("failed to load peerstate from db");
|
||||
@@ -509,16 +558,13 @@ mod tests {
|
||||
gossip_key: None,
|
||||
gossip_timestamp: 12,
|
||||
gossip_key_fingerprint: None,
|
||||
verified_key: None,
|
||||
verified_key: VerifiedKey::None,
|
||||
verified_key_fingerprint: None,
|
||||
to_save: Some(ToSave::All),
|
||||
degrade_event: None,
|
||||
};
|
||||
|
||||
assert!(
|
||||
peerstate.save_to_db(&ctx.ctx.sql, true).is_ok(),
|
||||
"failed to save"
|
||||
);
|
||||
assert!(peerstate.save_to_db(&ctx.ctx.sql, true), "failed to save");
|
||||
|
||||
let peerstate_new = Peerstate::from_addr(&ctx.ctx, &ctx.ctx.sql, addr.into())
|
||||
.expect("failed to load peerstate from db");
|
||||
|
||||
11
src/pgp.rs
11
src/pgp.rs
@@ -19,7 +19,7 @@ use crate::keyring::*;
|
||||
|
||||
pub unsafe fn dc_split_armored_data(
|
||||
buf: *mut libc::c_char,
|
||||
ret_headerline: *mut String,
|
||||
ret_headerline: *mut *const libc::c_char,
|
||||
ret_setupcodebegin: *mut *const libc::c_char,
|
||||
ret_preferencrypt: *mut *const libc::c_char,
|
||||
ret_base64: *mut *const libc::c_char,
|
||||
@@ -31,6 +31,9 @@ pub unsafe fn dc_split_armored_data(
|
||||
let mut p2: *mut libc::c_char;
|
||||
let mut headerline: *mut libc::c_char = ptr::null_mut();
|
||||
let mut base64: *mut libc::c_char = ptr::null_mut();
|
||||
if !ret_headerline.is_null() {
|
||||
*ret_headerline = ptr::null()
|
||||
}
|
||||
if !ret_setupcodebegin.is_null() {
|
||||
*ret_setupcodebegin = ptr::null_mut();
|
||||
}
|
||||
@@ -40,7 +43,7 @@ pub unsafe fn dc_split_armored_data(
|
||||
if !ret_base64.is_null() {
|
||||
*ret_base64 = ptr::null();
|
||||
}
|
||||
if !buf.is_null() {
|
||||
if !(buf.is_null() || ret_headerline.is_null()) {
|
||||
dc_remove_cr_chars(buf);
|
||||
while 0 != *p1 {
|
||||
if *p1 as libc::c_int == '\n' as i32 {
|
||||
@@ -59,7 +62,9 @@ pub unsafe fn dc_split_armored_data(
|
||||
) == 0i32
|
||||
{
|
||||
headerline = line;
|
||||
*ret_headerline = as_str(headerline).to_string();
|
||||
if !ret_headerline.is_null() {
|
||||
*ret_headerline = headerline
|
||||
}
|
||||
}
|
||||
} else if strspn(line, b"\t\r\n \x00" as *const u8 as *const libc::c_char)
|
||||
== strlen(line)
|
||||
|
||||
@@ -413,7 +413,7 @@ pub fn handle_securejoin_handshake(
|
||||
could_not_establish_secure_connection(
|
||||
context,
|
||||
contact_chat_id,
|
||||
if mimeparser.encrypted {
|
||||
if mimeparser.e2ee_helper.encrypted {
|
||||
"No valid signature."
|
||||
} else {
|
||||
"Not encrypted."
|
||||
@@ -522,9 +522,7 @@ pub fn handle_securejoin_handshake(
|
||||
error!(context, "Chat {} not found.", &field_grpid);
|
||||
return ret;
|
||||
} else {
|
||||
if let Err(err) =
|
||||
chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, true)
|
||||
{
|
||||
if let Err(err) = chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, true) {
|
||||
error!(context, "failed to add contact: {}", err);
|
||||
}
|
||||
}
|
||||
@@ -678,7 +676,7 @@ fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Res
|
||||
if peerstate.set_verified(1, fingerprint.as_ref(), 2) {
|
||||
peerstate.prefer_encrypt = EncryptPreference::Mutual;
|
||||
peerstate.to_save = Some(ToSave::All);
|
||||
peerstate.save_to_db(&context.sql, false).unwrap();
|
||||
peerstate.save_to_db(&context.sql, false);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@@ -693,16 +691,17 @@ fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Res
|
||||
******************************************************************************/
|
||||
|
||||
fn encrypted_and_signed(mimeparser: &MimeParser, expected_fingerprint: impl AsRef<str>) -> bool {
|
||||
if !mimeparser.encrypted {
|
||||
if !mimeparser.e2ee_helper.encrypted {
|
||||
warn!(mimeparser.context, "Message not encrypted.",);
|
||||
false
|
||||
} else if mimeparser.signatures.len() <= 0 {
|
||||
} else if mimeparser.e2ee_helper.signatures.len() <= 0 {
|
||||
warn!(mimeparser.context, "Message not signed.",);
|
||||
false
|
||||
} else if expected_fingerprint.as_ref().is_empty() {
|
||||
warn!(mimeparser.context, "Fingerprint for comparison missing.",);
|
||||
false
|
||||
} else if !mimeparser
|
||||
.e2ee_helper
|
||||
.signatures
|
||||
.contains(expected_fingerprint.as_ref())
|
||||
{
|
||||
@@ -717,24 +716,21 @@ fn encrypted_and_signed(mimeparser: &MimeParser, expected_fingerprint: impl AsRe
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_degrade_event(context: &Context, peerstate: &Peerstate) -> Result<(), Error> {
|
||||
pub fn handle_degrade_event(context: &Context, peerstate: &Peerstate) {
|
||||
// - we do not issue an warning for DC_DE_ENCRYPTION_PAUSED as this is quite normal
|
||||
// - currently, we do not issue an extra warning for DC_DE_VERIFICATION_LOST - this always comes
|
||||
// together with DC_DE_FINGERPRINT_CHANGED which is logged, the idea is not to bother
|
||||
// with things they cannot fix, so the user is just kicked from the verified group
|
||||
// (and he will know this and can fix this)
|
||||
if Some(DegradeEvent::FingerprintChanged) == peerstate.degrade_event {
|
||||
let contact_id: i32 = match context.sql.query_get_value(
|
||||
context,
|
||||
"SELECT id FROM contacts WHERE addr=?;",
|
||||
params![&peerstate.addr],
|
||||
) {
|
||||
None => bail!(
|
||||
"contact with peerstate.addr {:?} not found",
|
||||
&peerstate.addr
|
||||
),
|
||||
Some(contact_id) => contact_id,
|
||||
};
|
||||
let contact_id: i32 = context
|
||||
.sql
|
||||
.query_get_value(
|
||||
context,
|
||||
"SELECT id FROM contacts WHERE addr=?;",
|
||||
params![&peerstate.addr],
|
||||
)
|
||||
.unwrap_or_default();
|
||||
if contact_id > 0 {
|
||||
let (contact_chat_id, _) =
|
||||
chat::create_or_lookup_by_contact_id(context, contact_id as u32, Blocked::Deaddrop)
|
||||
@@ -750,5 +746,4 @@ pub fn handle_degrade_event(context: &Context, peerstate: &Peerstate) -> Result<
|
||||
emit_event!(context, Event::ChatModified(contact_chat_id));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -70,9 +70,8 @@ impl Smtp {
|
||||
let port = lp.send_port as u16;
|
||||
|
||||
let tls = native_tls::TlsConnector::builder()
|
||||
// see also: https://github.com/deltachat/deltachat-core-rust/issues/203
|
||||
// FIXME: unfortunately this is needed to make things work on macos + testrun.org
|
||||
.danger_accept_invalid_hostnames(true)
|
||||
.danger_accept_invalid_certs(true)
|
||||
.min_protocol_version(Some(DEFAULT_TLS_PROTOCOLS[0]))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
@@ -777,7 +777,7 @@ fn open(
|
||||
if let Some(ref mut peerstate) = Peerstate::from_addr(context, sql, &addr?)
|
||||
{
|
||||
peerstate.recalc_fingerprint();
|
||||
peerstate.save_to_db(sql, false).unwrap();
|
||||
peerstate.save_to_db(sql, false);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -76,7 +76,7 @@ pub fn configure_alice_keypair(ctx: &Context) -> String {
|
||||
KeyType::Private,
|
||||
)
|
||||
.unwrap();
|
||||
let saved = key::dc_key_save_self_keypair(&ctx, &public, &private, &addr, true, &ctx.sql);
|
||||
let saved = key::dc_key_save_self_keypair(&ctx, &public, &private, &addr, 1, &ctx.sql);
|
||||
assert_eq!(saved, true, "Failed to save Alice's key");
|
||||
addr
|
||||
}
|
||||
|
||||
149
src/wrapmime.rs
149
src/wrapmime.rs
@@ -1,16 +1,14 @@
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::Error;
|
||||
use mmime::clist::*;
|
||||
use mmime::mailimf::types::*;
|
||||
use mmime::mailimf::types_helper::*;
|
||||
use mmime::mailmime::content::*;
|
||||
use mmime::mailmime::disposition::*;
|
||||
use mmime::mailmime::types::*;
|
||||
use mmime::mailmime::types_helper::*;
|
||||
use mmime::mailimf_types::*;
|
||||
use mmime::mailimf_types_helper::*;
|
||||
use mmime::mailmime::*;
|
||||
use mmime::mailmime_disposition::*;
|
||||
use mmime::mailmime_types::*;
|
||||
use mmime::mailmime_types_helper::*;
|
||||
use mmime::other::*;
|
||||
|
||||
#[macro_export]
|
||||
@@ -27,137 +25,8 @@ macro_rules! clist_append {
|
||||
};
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* mime parsing API
|
||||
**************************************/
|
||||
|
||||
pub fn get_ct_subtype(mime: *mut Mailmime) -> Option<String> {
|
||||
unsafe {
|
||||
let ct: *mut mailmime_content = (*mime).mm_content_type;
|
||||
|
||||
if !ct.is_null() && !(*ct).ct_subtype.is_null() {
|
||||
Some(to_string((*ct).ct_subtype))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_autocrypt_mime(
|
||||
mime_undetermined: *mut Mailmime,
|
||||
) -> Result<(*mut Mailmime, *mut Mailmime), Error> {
|
||||
/* return Result with two mime pointers:
|
||||
|
||||
First mime pointer is to the multipart-mime message
|
||||
(which is replaced with a decrypted version later)
|
||||
|
||||
Second one is to the encrypted payload.
|
||||
For non-autocrypt message an Error is returned.
|
||||
*/
|
||||
unsafe {
|
||||
ensure!(
|
||||
(*mime_undetermined).mm_type == MAILMIME_MESSAGE as libc::c_int,
|
||||
"Not a root mime message"
|
||||
);
|
||||
let mime = (*mime_undetermined).mm_data.mm_message.mm_msg_mime;
|
||||
|
||||
ensure!(
|
||||
(*mime).mm_type == MAILMIME_MULTIPLE as libc::c_int
|
||||
&& "encrypted" == get_ct_subtype(mime).unwrap_or_default(),
|
||||
"Not a multipart/encrypted message"
|
||||
);
|
||||
let parts: Vec<_> = (*(*mime).mm_data.mm_multipart.mm_mp_list)
|
||||
.into_iter()
|
||||
.map(|c| c as *mut Mailmime)
|
||||
.collect();
|
||||
ensure!(parts.len() == 2, "Invalid Autocrypt Level 1 Mime Parts");
|
||||
// XXX ensure protocol-parameter "application/pgp-encrypted")
|
||||
// XXX ensure wrapmime::get_content_type(parts[1])) == "application/octetstream"
|
||||
// a proper OpenPGP multipart/encrypted Autocrypt Level 1 message
|
||||
// https://tools.ietf.org/html/rfc3156.html#section-4
|
||||
Ok((mime, parts[1]))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_decryptable_data(mime_data: *mut mailmime_data) -> bool {
|
||||
/* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */
|
||||
unsafe {
|
||||
(*mime_data).dt_type == MAILMIME_DATA_TEXT as libc::c_int
|
||||
&& !(*mime_data).dt_data.dt_text.dt_data.is_null()
|
||||
&& (*mime_data).dt_data.dt_text.dt_length > 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mime_transfer_encoding(mime: *mut Mailmime) -> Option<libc::c_int> {
|
||||
unsafe {
|
||||
let mm_mime_fields = (*mime).mm_mime_fields;
|
||||
if !mm_mime_fields.is_null() {
|
||||
for cur_data in (*(*mm_mime_fields).fld_list).into_iter() {
|
||||
let field: *mut mailmime_field = cur_data as *mut _;
|
||||
if (*field).fld_type == MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int
|
||||
&& !(*field).fld_data.fld_encoding.is_null()
|
||||
{
|
||||
return Some((*(*field).fld_data.fld_encoding).enc_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn decode_dt_data(
|
||||
mime_data: *mut mailmime_data,
|
||||
mime_transfer_encoding: libc::c_int,
|
||||
) -> Result<(*mut libc::c_char, libc::size_t), Error> {
|
||||
// Decode data according to mime_transfer_encoding
|
||||
// returns Ok with a (decoded_data,decoded_data_bytes) pointer
|
||||
// where the caller must make sure to free it.
|
||||
// It may return Ok(ptr::null_mut(), 0)
|
||||
|
||||
let mut transfer_decoding_buffer: *mut libc::c_char = ptr::null_mut();
|
||||
let decoded_data: *mut libc::c_char;
|
||||
let mut decoded_data_bytes: libc::size_t = 0;
|
||||
if mime_transfer_encoding == MAILMIME_MECHANISM_7BIT as libc::c_int
|
||||
|| mime_transfer_encoding == MAILMIME_MECHANISM_8BIT as libc::c_int
|
||||
|| mime_transfer_encoding == MAILMIME_MECHANISM_BINARY as libc::c_int
|
||||
{
|
||||
unsafe {
|
||||
decoded_data = (*mime_data).dt_data.dt_text.dt_data as *mut _;
|
||||
decoded_data_bytes = (*mime_data).dt_data.dt_text.dt_length;
|
||||
}
|
||||
ensure!(
|
||||
!decoded_data.is_null() && decoded_data_bytes > 0,
|
||||
"could not decode mime message"
|
||||
);
|
||||
} else {
|
||||
let mut current_index: libc::size_t = 0;
|
||||
unsafe {
|
||||
let r = mailmime_part_parse(
|
||||
(*mime_data).dt_data.dt_text.dt_data,
|
||||
(*mime_data).dt_data.dt_text.dt_length,
|
||||
&mut current_index,
|
||||
mime_transfer_encoding,
|
||||
&mut transfer_decoding_buffer,
|
||||
&mut decoded_data_bytes,
|
||||
);
|
||||
if r != MAILIMF_NO_ERROR as libc::c_int
|
||||
|| transfer_decoding_buffer.is_null()
|
||||
|| decoded_data_bytes <= 0
|
||||
{
|
||||
bail!("mailmime_part_parse returned error or invalid data");
|
||||
}
|
||||
decoded_data = transfer_decoding_buffer;
|
||||
}
|
||||
}
|
||||
Ok((decoded_data, decoded_data_bytes))
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* mime creation API
|
||||
**************************************/
|
||||
|
||||
pub fn add_filename_part(
|
||||
message: *mut Mailmime,
|
||||
message: *mut mailmime,
|
||||
basename: &str,
|
||||
mime_type: &str,
|
||||
file_content: &str,
|
||||
@@ -188,9 +57,9 @@ pub fn new_custom_field(fields: *mut mailimf_fields, name: &str, value: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_body_text(text: &str) -> Result<*mut Mailmime, Error> {
|
||||
pub fn build_body_text(text: &str) -> Result<*mut mailmime, Error> {
|
||||
let mime_fields: *mut mailmime_fields;
|
||||
let message_part: *mut Mailmime;
|
||||
let message_part: *mut mailmime;
|
||||
|
||||
let content = new_content_type("text/plain")?;
|
||||
append_ct_param(content, "charset", "utf-8")?;
|
||||
@@ -235,7 +104,7 @@ pub fn new_content_type(content_type: &str) -> Result<*mut mailmime_content, Err
|
||||
Ok(content)
|
||||
}
|
||||
|
||||
pub fn set_body_text(part: *mut Mailmime, text: &str) -> Result<(), Error> {
|
||||
pub fn set_body_text(part: *mut mailmime, text: &str) -> Result<(), Error> {
|
||||
use libc::strlen;
|
||||
unsafe {
|
||||
let text_c = text.strdup();
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
Passphrase-Format: numeric9x4
|
||||
Passphrase-Begin: 17
|
||||
|
||||
wy4ECQMI0jNRBQfVKHVg1+a2Yihd6JAjR9H0kk3oDVeX7nc4Oi+IjEtonUJt
|
||||
PQpO0tPWASWYuYvjZSuTz9r1yZYV+y4mu9bu9NEQoRlWg2wnbjoUoKk4emFF
|
||||
FweUj84iI6VWTCSRyMu5d5JS1RfOdX4CG/muLAegyIHezqYOEC0Z3b9Ci9rd
|
||||
DiSgqqN+/LDkUR/vr7L2CSLN5suBP9Hsz75AtaV8DJ2DYDywYX89yH1CfL1O
|
||||
WohyrJPdmGJZfdvQX0LI9mzN7MH0W6vUJeCaUpujc+UkLiOM6TDB74rmYF+V
|
||||
Z7K9BXbaN4V6dyxVZfgpXUoZlaNpvqPJXuLHJ68umkuIgIyQvzmMj3mFgZ8s
|
||||
akCt6Cf3o5O9n2PJvX89vuNnDGJrO5booEqGaBJfwUk0Rwb0gWsm5U0gceUz
|
||||
dce8KZK15CzX+bNv5OC+8jjjBw7mBHVt+2q8LI+G9fEy9NIREkp5/v2ZRN0G
|
||||
R6lpZwW+8TkMvJnriQeABqDpxsJVT6ENYAhkPG3AZCr/whGBU3EbDzPexXkz
|
||||
qt8Pdu5DrazLSFtjpjkekrjCh43vHjGl8IOiWxKQx0VfBkHJ7O9CsHmb0r1o
|
||||
F++fMh0bH1/aewmlg5wd0ixwZoP1o79he8Q4kfATZAjvB1xSLyMma+jxW5uu
|
||||
U3wYUOsUmYmzo46/QzizFCUpaTJ4ZQZY1/4sflidsl/XgZ0fD1NCrdkWBNA1
|
||||
0tQF949pEAeA4hSfHfQDNKAY8A7fk8lZblqWPkyu/0x8eV537QOhs89ZvhSB
|
||||
V87KEAwxWt60+Eolf8PvvkvB/AKlfWq4MYShgyldwwCfkED3rv2mvTsdqfvW
|
||||
WvqZNo4eRkJrnv9Be3LaXoFyY6a3z+ObBIkKI+u5azGJYge97O4E2DrUEKdQ
|
||||
cScq5upzXity0E+Yhm964jzBzxnA52S4RoXzkjTxH+AHjQ5+MHQxmRfMd2ly
|
||||
7skM106weVOR0JgOdkvfiOFDTHZLIVCzVyYVlOUJYYwPhmM1426zbegHNkaM
|
||||
M2WgvjMp5G+X9qfDWKecntQJTziyDFZKfd1UrUCPHrvl1Ac9cuqgcCXLtdUS
|
||||
jI+e1Y9fXvgyvHiMX0ztSz1yfvnRt34508G9j68fEQFQR/VIepULB5/SqKbq
|
||||
p2flgJL48kY32hEw2GRPri64Tv3vMPIWa//zvQDhQPmcd3S4TqnTIIKUoTAO
|
||||
NUo6GS9UAX12fdSFPZINcAkNIaB69+iwGyuJE4FLHKVkqNnNmDwF3fl0Oczo
|
||||
hbboWzA3GlpR2Ri6kfe0SocfGR0CHT5ZmqI6es8hWx+RN8hpXcsRxGS0BMi2
|
||||
mcJ7fPY+bKastnEeatP+b0XN/eaJAPZPZSF8PuPeQ0Uc735fylPrrgtWK9Gp
|
||||
Wq0DPaWV/+O94OB/JvWT5wq7d/EEVbTck5FPl4gdv3HHpaaQ6/8G89wVMEXA
|
||||
GUxB8WuvNeHAtQ7qXF7TkaZvUpF0rb1aV88uABOOPpsfAyWJo/PExCZacg8R
|
||||
GOQYI6inV5HcGUw06yDSqArHZmONveqjbDBApenearcskv6Uz7q+Bp60GGSA
|
||||
lvU3C3RyP/OUc1azOp72MIe0+JvP8S5DN9/Ltc/5ZyZHOjLoG+npIXnThYwV
|
||||
0kkrlsi/7loCzvhcWOac1vrSaGVCfifkYf+LUFQFrFVbxKLOQ6vTsYZWM0yM
|
||||
QsMMywW5A6CdROT5UB0UKRh/S1cwCwrN5UFTRt2UpDF3wSBAcChsHyy90RAL
|
||||
Xd4+ZIyf29GIFuwwQyzGBWnXQ2ytU4kg/D5XSqJbJJTya386UuyQpnFjI19R
|
||||
uuD0mvEfFvojCKDJDWguUNtWsHSg01NXDSrY26BhlOkMpUrzPfX5r0FQpgDS
|
||||
zOdY9SIG+y9MKG+4nwmYnFM6V5NxVL+6XZ7BQTvlLIcIIu+BujVNWteDnWNZ
|
||||
T1UukCGmFd8sNZpCc3wu4o/gLDQxih/545tWMf0dmeUfYhKcjSX9uucMRZHT
|
||||
1N0FINw04fDdp2LccL+WCGatFGnkZVPw3asid4d1od9RG9DbNRBJEp/QeNhc
|
||||
/peJCPLGYlA1NjTEq+MVB+DHdGNOuy//be3KhedBr6x4VVaDzL6jyHu/a7PR
|
||||
BWRVtI1CIVDxyrEXucHdGQoEm7p+0G2zouOe/oxbPFoEYrjaI+0e/FN3u/Y3
|
||||
aG0dlYWbxeHMqTh2F3lB/CFALReeGqqN6PwRyePWKaVctZYb6ydf9JVl6q1/
|
||||
aV9C5rf9eFGqqA+OIx/+XuAG1w0rwlznvtajHzCoUeA4QfbmuOV/t5drWN2N
|
||||
PCk2mJlcSmd7lx53rnOIgme1hggchjezc4TisL4PvSLxjJ7DxzktD2jv2I/Q
|
||||
OlSxTUaXnGfIVedsI0WjFomz5w9tZjC0B5O5TpSRRz6gfpe/OC3kV7qs1YCS
|
||||
lJTTxj1mTs6wqt0WjKkN/Ke0Cm5r7NQ79szDNlcC0AViEOQb3U1R88nNdiVx
|
||||
ymKT5Dl+yM6acv53lNX6O5BH+mpP2/pCpi3x+kYFyr4cUsNgVVGlhmkPWctZ
|
||||
trHvO7wcLrAsrLNqRxt1G3DLjQt9VY+w5qOPJv6s9qd5JBL/qtH5zqIXiXlM
|
||||
IWI9LLwHFFXqjk/f6G4LyOeHB9AqccGQ4IztgzTKmYEmFWVIpTO4UN6+E7yQ
|
||||
gtcYSIUEJo824ht5rL+ODqmCSAWsWIomEoTPvgn9QqO0YRwAEMpsFtE17klS
|
||||
qjbYyV7Y5A0jpCvqbnGmZPqCgzjjN/p5VKSNjSdM0vdwBRgpXlyooXg/EGoJ
|
||||
ZTZH8nLSuYMMu7AK8c7DKJ1AocTNYHRe9xFV8RzEiIm3zaezxa0r+Fo3nuTX
|
||||
UR9DOH0EHaDLrFQcfS5y1iRxY9CHg0N2ECaUzr/H7jck9mLZ7v9xisj3QDuv
|
||||
i0xQbC4BTxMEBGTK8fOcjHHOABOyhqotOreERqwOV2c1OOGUQE8QK18zJCUd
|
||||
BTmQZ709ttASD7VWK4TraOGczZXkZsKdZko5T6+6EkFy9H+gwENLUG9zk0x9
|
||||
2G5zicDr6PDoAGDuoB3B3VA8ertXTX7zEz30N6m+tcAtPWka0owokLy3f0o7
|
||||
ZdytBPkly8foTMWKF2vsJ8K4Xdn/57jJ2qFku32xmtiPIoa6s8wINO06AVB0
|
||||
0/AuttvxcPr+ycE+9wRZHx6JBujAqOZztU3zu8WZMaqVKb7gnmkWPiL+1XFp
|
||||
2+mr0AghScIvjzTDEjigDtLydURJrW01wXjaR0ByBT4z8ZjaNmQAxIPOIRFC
|
||||
bD0mviaoX61qgQLmSc6mzVlzzNZRCKtSvvGEK5NJ6CB6g2EeFau8+w0Zd+vv
|
||||
/iv6Img3pUBgvpMaIsxRXvGZwmo2R0tztJt+CqHRvyTWjQL+CjIAWyoHEdVH
|
||||
k7ne/q9zo3iIMsQUO7tVYtgURpRYc2OM1IVQtrgbmbYGEdOrhMjaWULg9C7o
|
||||
6oDM0EFlCAId3P8ykXQNMluFKlf9il5nr19B/qf/wh6C7DFLOmnjTWDXrEiP
|
||||
6wFEWTeUWLchGlbpiJFEu05MWPIRoRd3BHQvVpzLLgeBdxMVW7D6WCK+KJxI
|
||||
W1rOKhhLVvKU3BrFgr12A4uQm+6w1j33Feh68Y0JB7GLDBBGe11QtLCD6kz5
|
||||
RzFl+GbgiwpHi3nlCc5yiNwyPq/JRxU3GRb62YJcsSQBg+CD3Mk5FGiDcuvp
|
||||
kZXOcTE2FAnUDigjEs+oH2qkhD4/5CiHkrfFJTzv+wqw+jwxPor2jkZH2akN
|
||||
6PssXQYupXJE3NmcyaYT+b5E6qbkIyQj7CknkiqmrqrmxkOQxA+Ab2Vy9zrW
|
||||
u0+Wvf+C+SebWTo3qfJZQ3KcASZHa5AGoSHetWzH2fNLIHfULXac/T++1DWE
|
||||
nbeNvhXiFmAJ+BRsZj9p6RcnSamk4bjAbX1lg2G3Sq6MiA1fIRSMlSjuDLrQ
|
||||
8xfVFrg7gfBIIQPErJWv2GdAsz76sLxuSXQLKYpFnozvMT7xRs84+iRNWWh9
|
||||
SNibbEjlh0DcJlKw49Eis/bN22sDQWy4awHuRvvQetk/QCgp54epuqWnbxoE
|
||||
XZDgGBBkMc3or+6Cxr3q9x7J/oHLvPb+Q5yVP9fyz6ZiSVWluMefA9smjJ/A
|
||||
KMD84s7uO/8/4yug+swXGrcBjHSddTcy05vm+7X6o9IEZKZb5tz7VqAfEcuk
|
||||
QNPUWCMudhzxSNr4+yVXRVpcjsjKtplJcXC5aIuJwq3C5OdysCGqXWjLuUu1
|
||||
OFSoPvTsYC2VxYdFUcczeHEFTxXoXz3I0TyLPyxUNsJiKpUGt/SXmV/IyAx+
|
||||
h6pZ2OUXspC9d78DdiHZtItPjEGiIb678ZyMxWPE59XQd/ad92mlPHU8InXD
|
||||
yTq6otZ7LwAOLGbDR9bqN7oX8PCHRwuu30hk2b4+WkZn/WLd2KCPddQswZJg
|
||||
Qgi5ajUaFhZvxF5YNTqIzzYVh7Y8fFMfzH9AO+SJqy+0ECX0GwtHHeVsXYNb
|
||||
P/NO/ma4MI8301JyipPmdtzvvt9NOD/PJcnZH2KmDquARXMO/vKbn3rNUXog
|
||||
pTFqqyNTr4L5FK86QPEoE4hDy9ItHGlEuiNVD+5suGVGUgYfV7AvZU46EeqO
|
||||
rfFj8wNSX1aK/pIwWmh1EkygPSxomWRUANLX1jO6zX9wk2X80Xn9q/8jot1k
|
||||
Vl54OOd7cvGls2wKkEZi5h3p6KKZHJ+WIDBQupeJbuma1GK8wAiwjDH59Y0X
|
||||
wXHAk7XA+t4u0dgRpZbUUMqQmvEvfJaCr4qMlpuGdEYbbpIMUB1qCfYU9taL
|
||||
zbepMIT+XYD5mTyytZhR+zrsfpt1EzbrhuabqPioySoIS/1+bWfxvndq16r0
|
||||
AdNxR5LiVSVh8QJr3B/HJhVghgSVrrynniG3E94abNWL/GNxPS/dTHSf8ass
|
||||
vbv7+uznADzHsMiG/ZlLAEkQJ9j0ENJvHmnayeVFIXDV6jPCcQJ+rURDgl7z
|
||||
/qTLfe3o3zBMG78LcB+xDNXTQrK5Z0LX7h17hLSElpiUghFa9nviCsT0nkcr
|
||||
nz302P4IOFwJuYMMCEfW+ywTn+CHpKjLHWkZSZ4q6LzNTbbgXZn/vh7njNf0
|
||||
QHaHmaMNxnDhUw/Bl13uM52qtsfEYK07SEhLFlJbAk0G7q+OabK8dJxCRwS3
|
||||
X9k4juzLUYhX8XBovg9G3YEVckb6iM8/LF/yvNXbUsPrdhYU9lPA63xD0Pgb
|
||||
zthZCLIlnF+lS6e41WJv3n1dc4dFWD7F5tmt/7uwLC6oUGYsccSzY+bUkYhL
|
||||
dp7tlQRd5AG/Xz8XilORk8cUjvi6uZss5LyQpKvGSU+77C8ZV/oS62BdS5TE
|
||||
osBTrO2/9FGzQtHT+8DJSTPPgR6rcQUWLPemiG09ACKfRQ/g3b9Qj0upOcKL
|
||||
6dti0lq7Aorc39vV18DPMFBOwzchUEBlBFyuSa4AoD30tsoilAC3qbzBwu3z
|
||||
QLjmst76HEcWDkxgDAhlBz6/XgiVZsCivn7ygigmc2+hNEzIdDsKKfM9bkoe
|
||||
3uJzmmsv8Bh5ZEtfGoGNmu/zA7tgvTOCBeotYeHr2O6pLmYb3hK+E/qCBl14
|
||||
8pK4qYrjAlF+ZMq9BzXcaz5mRfKVfAQtghHOaNqopBczSE1bjFF6HaNhIaGa
|
||||
N8YdabNQG7mLI/fgBxJfkPl6HdIhEpctp4RURbSFhW+wn0o85VyHM6a+6Vgj
|
||||
NrYmhxPZ6N1KN0Qy76aNiw7nAToRRcOv87uZnkDIeVH8mP/0hldyiy/Y97cG
|
||||
QgOeQHOG27QW57nHhqLRqvf0zzQZekuXWFbqajpaabEcdGXyiUpJ8/ZopBPM
|
||||
AJwfkyA2LkV946IA4JV6sPnu9pYzpXQ4vdQKJ6DoDUyRTQmgmfSFGtfHAozY
|
||||
V9k0iQeetSkYYtOagTrg3t92v7M00o/NJW/rKX4jj2djD8wtBovOcv4kxg4Z
|
||||
o58Iv94ROim48XfyesvSYKN1xqqbXH4sfE6b4b9pLUxQVOmWANLK9MK8D+Ci
|
||||
IvrGbz5U5bZP6vlNbe9bYzjvWTPjaMrjXknRTBcikavqOfDTSIVFtT4qvhvK
|
||||
42PpOrm0qdiLwExGKQ9FfEfYZRgEcYRGg7rH3oNz6ZNOEXppF3tCl9yVOlFb
|
||||
ygdIeT3Z3HeOQbAsi8jK7o16DSXL7ZOpFq9Bv9yzusrF7Eht/fSEpAVUO3D1
|
||||
IuqjZcsQRhMtIvnF0oFujFtooJx9x3dj/RarvEGX/NzwATZkgJ+yWs2etruA
|
||||
EzMQqED4j7Lb790zEWnt+nuHdCdlPnNy8RG5u5X62p3h5KqUbg9HfmIuuESi
|
||||
hwr6dKsVQGc5XUB5KTt0dtjWlK5iaetDsZFuF5+aE0Xa6PmiQ2e7ZPFyxXmO
|
||||
T/PSHzobx0qClKCu+tSWA1HDSL08IeoGZEyyhoaxyn5D9r1Mqg101v/iu59r
|
||||
lRRs+plAhbuq5aQA3WKtF1N6Zb5+AVRpNUyrxyHoH36ddR4/n7lnIld3STGD
|
||||
RqZLrOuKHS3dCNW2Pt15lU+loYsWFZwC6T/tAbvwhax+XaBMiKQSDFmG9sBw
|
||||
TiM1JWXhq2IsjXBvCl6k2AKWLQOvc/Hin+oYs4d7M9mi0vdoEOAMadU/+Pqn
|
||||
uZzP941mOUV5UeTCCbjpyfI7qtIi3TH1cQmC2kG2HrvQYuM6Momp//JusH1+
|
||||
9eHgFo25HbitcKJ1sAqxsnYIW5/jIVyIJC7tatxmNfFQQ/LUb2cT+Jowwsf4
|
||||
bbPinA9S6aQFy9k3vk07V2ouYl+cpMMXmNAUrboFRLxw7QDapWYMKdmnbU5O
|
||||
HZuDz3iyrm0lMPsRtt/f5WUhZYY4vXT5/dj+8P6Pr5fdc4S84i5qEzf7bX/I
|
||||
Sc6fpISdYBscfHdv6uXsEVtVPKEuQVYwhyc4kkwVKjZBaqsgjAA7VEhQXzO3
|
||||
rC7di4UhabWQCQTG1GYZyrj4bm6dg/32uVxMoLS5kuSpi3nMz5JmQahLqRxh
|
||||
argg13K2/MJ7w2AI23gCvO5bEmD1ZXIi1aGYdZfu7+KqrTumYxj0KgIesgU0
|
||||
6ekmPh4Zu5lIyKopa89nfQVj3uKbwr9LLHegfzeMhvI5WQWghKcNcXEvJwSA
|
||||
vEik5aXm2qSKXT+ijXBy5MuNeICoGaQ5WA0OJ30Oh5dN0XpLtFUWHZKThJvR
|
||||
mngm1QCMMw2v/j8=
|
||||
=9sJE
|
||||
-----END PGP MESSAGE-----
|
||||
143
tests/stress.rs
143
tests/stress.rs
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user