mirror of
https://github.com/chatmail/core.git
synced 2026-04-03 14:02:10 +03:00
Compare commits
4 Commits
fix_set_pr
...
fix/str-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d47d25c1e | ||
|
|
e4f9446e3c | ||
|
|
abbbd0cb67 | ||
|
|
ae9f52e001 |
@@ -13,7 +13,7 @@ restore-workspace: &restore-workspace
|
||||
restore-cache: &restore-cache
|
||||
restore_cache:
|
||||
keys:
|
||||
- cargo-v1-{{ checksum "rust-toolchain" }}-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
|
||||
- cargo-v0-{{ checksum "rust-toolchain" }}-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
|
||||
- repo-source-{{ .Branch }}-{{ .Revision }}
|
||||
|
||||
commands:
|
||||
@@ -53,11 +53,10 @@ jobs:
|
||||
command: cargo generate-lockfile
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cargo-v1-{{ checksum "rust-toolchain" }}-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
|
||||
- cargo-v0-{{ checksum "rust-toolchain" }}-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
|
||||
- run: rustup install $(cat rust-toolchain)
|
||||
- run: rustup default $(cat rust-toolchain)
|
||||
- run: rustup component add --toolchain $(cat rust-toolchain) rustfmt
|
||||
- run: rustup component add --toolchain $(cat rust-toolchain) clippy-preview
|
||||
- run: cargo update
|
||||
- run: cargo fetch
|
||||
- run: rustc +stable --version
|
||||
@@ -68,7 +67,7 @@ jobs:
|
||||
paths:
|
||||
- crate
|
||||
- save_cache:
|
||||
key: cargo-v1-{{ checksum "rust-toolchain" }}-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
|
||||
key: cargo-v0-{{ checksum "rust-toolchain" }}-{{ checksum "Cargo.toml" }}-{{ checksum "Cargo.lock" }}-{{ arch }}
|
||||
paths:
|
||||
- "~/.cargo"
|
||||
- "~/.rustup"
|
||||
@@ -161,15 +160,6 @@ jobs:
|
||||
- run: ls -laR workspace
|
||||
- run: ci_scripts/ci_upload.sh workspace/py-docs workspace/wheelhouse
|
||||
|
||||
clippy:
|
||||
executor: default
|
||||
steps:
|
||||
- *restore-workspace
|
||||
- *restore-cache
|
||||
- run:
|
||||
name: Run cargo clippy
|
||||
command: cargo clippy --all
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2.1
|
||||
@@ -185,10 +175,6 @@ workflows:
|
||||
requires:
|
||||
- cargo_fetch
|
||||
|
||||
- clippy:
|
||||
requires:
|
||||
- cargo_fetch
|
||||
|
||||
# Linux Desktop 64bit
|
||||
- test_x86_64-unknown-linux-gnu:
|
||||
requires:
|
||||
|
||||
176
Cargo.lock
generated
176
Cargo.lock
generated
@@ -1,5 +1,18 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "addr"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"psl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rental 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.0.3"
|
||||
@@ -199,11 +212,6 @@ name = "byte-tools"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bytecount"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.2"
|
||||
@@ -228,18 +236,6 @@ dependencies = [
|
||||
"ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cast5"
|
||||
version = "0.6.0"
|
||||
@@ -462,19 +458,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat"
|
||||
version = "1.0.0-alpha.4"
|
||||
version = "1.0.0-alpha.3"
|
||||
dependencies = [
|
||||
"addr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.38 (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.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"deltachat_derive 0.1.0",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image-meta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"imap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -506,19 +501,11 @@ dependencies = [
|
||||
"thread-local-object 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deltachat_derive"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deltachat_ffi"
|
||||
version = "1.0.0-alpha.4"
|
||||
version = "1.0.0-alpha.3"
|
||||
dependencies = [
|
||||
"deltachat 1.0.0-alpha.4",
|
||||
"deltachat 1.0.0-alpha.3",
|
||||
"human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -760,11 +747,6 @@ dependencies = [
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.1.26"
|
||||
@@ -910,16 +892,6 @@ dependencies = [
|
||||
"unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image-meta"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imap"
|
||||
version = "1.0.2"
|
||||
@@ -1588,6 +1560,39 @@ dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psl"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"psl-codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psl-codegen"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"psl-lexer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sequence_trie 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psl-lexer"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "publicsuffix"
|
||||
version = "1.5.2"
|
||||
@@ -1600,14 +1605,6 @@ dependencies = [
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.2"
|
||||
@@ -1838,6 +1835,25 @@ dependencies = [
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rental"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rental-impl 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rental-impl"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"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.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.9.19"
|
||||
@@ -1951,14 +1967,6 @@ name = "safemem"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.15"
|
||||
@@ -2016,7 +2024,6 @@ version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2024,6 +2031,11 @@ name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "sequence_trie"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.98"
|
||||
@@ -2102,21 +2114,6 @@ name = "siphasher"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "skeptic"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.2"
|
||||
@@ -2555,16 +2552,6 @@ name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.2.0"
|
||||
@@ -2683,6 +2670,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum addr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22199dd03e5cff19ede8c2b835c93460f998b4716e225d06d740d925ceac5d75"
|
||||
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
|
||||
"checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9"
|
||||
"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d"
|
||||
@@ -2708,11 +2696,9 @@ dependencies = [
|
||||
"checksum buf_redux 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f"
|
||||
"checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8"
|
||||
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
"checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f"
|
||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
|
||||
"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
|
||||
"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe"
|
||||
"checksum cast5 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ce5759b4c52ca74f9a98421817c882f1fd9b0071ae41cd61ab9f9d059c04fd6"
|
||||
"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46"
|
||||
"checksum cfb-mode 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "190e7b55d3a27cf8879becf61035a141cbc783f3258a41d16d1706719f991345"
|
||||
@@ -2768,7 +2754,6 @@ dependencies = [
|
||||
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
|
||||
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||
"checksum getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8e190892c840661957ba9f32dacfb3eb405e657f9f9f60485605f0bb37d6f8"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
||||
@@ -2782,7 +2767,6 @@ dependencies = [
|
||||
"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f"
|
||||
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
|
||||
"checksum image-meta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b00861cbbb254a627d8acc0cec786b484297d896ab8f20fdc8e28536a3e918ef"
|
||||
"checksum imap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "178392198cb2716f4fe34b86a1bf1de1240a3e31136a199b16490fa87538fa25"
|
||||
"checksum imap-proto 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4e77b1d61faf028893531b071cc5584cdd02b6186cebe7f7168ffd8d591339a"
|
||||
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
||||
@@ -2853,8 +2837,10 @@ dependencies = [
|
||||
"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
|
||||
"checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum psl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0fcd4da9d98f254ad641dd081207cc14fcbec95dd58ee62ffc9b96f0684fd6c2"
|
||||
"checksum psl-codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "06f94f31e4f36b42e21b831d20bf0efc805b2155624697fb86f987b666518c3b"
|
||||
"checksum psl-lexer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cf84fe23023e855b9a9d038a1b08d5c438d3961d2ced6c2b2358b29fbf74a63"
|
||||
"checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d"
|
||||
"checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15"
|
||||
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
"checksum r2d2 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bc42ce75d9f4447fb2a04bbe1ed5d18dd949104572850ec19b164e274919f81b"
|
||||
@@ -2880,6 +2866,8 @@ dependencies = [
|
||||
"checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc"
|
||||
"checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c"
|
||||
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||
"checksum rental 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "01916ebd9fc2e81978a5dc9542a2fa47f5bb2ca3402e14c7cc42d6e3c5123e1f"
|
||||
"checksum rental-impl 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "82260d54cf2cbe9608df161f7e7c98e81fae702aa13af9e4d5d39dc2ffb25ab6"
|
||||
"checksum reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0777154c2c3eb54f5c480db01de845652d941e47191277cc673634c3853939"
|
||||
"checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a"
|
||||
"checksum rsa 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6ad8d3632f6745bb671c8637e2aa44015537c5e384789d2ea3235739301ed1e0"
|
||||
@@ -2889,7 +2877,6 @@ dependencies = [
|
||||
"checksum rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f47ea1ceb347d2deae482d655dc8eef4bd82363d3329baffa3818bd76fea48b"
|
||||
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
||||
"checksum safemem 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e133ccc4f4d1cd4f89cc8a7ff618287d56dc7f638b8e38fc32c5fdcadc339dd5"
|
||||
"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
|
||||
"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339"
|
||||
"checksum scheduled-thread-pool 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd07742e081ff6c077f5f6b283f12f32b9e7cc765b316160d66289b74546fbb3"
|
||||
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
@@ -2899,6 +2886,7 @@ dependencies = [
|
||||
"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum sequence_trie 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1ee22067b7ccd072eeb64454b9c6e1b33b61cd0d49e895fd48676a184580e0c3"
|
||||
"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113"
|
||||
"checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c"
|
||||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
||||
@@ -2907,7 +2895,6 @@ dependencies = [
|
||||
"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.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
||||
"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"
|
||||
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
|
||||
@@ -2961,7 +2948,6 @@ dependencies = [
|
||||
"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95"
|
||||
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
|
||||
"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat"
|
||||
version = "1.0.0-alpha.4"
|
||||
version = "1.0.0-alpha.3"
|
||||
authors = ["dignifiedquire <dignifiedquire@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MPL"
|
||||
@@ -10,7 +10,6 @@ cc = "1.0.35"
|
||||
pkg-config = "0.3"
|
||||
|
||||
[dependencies]
|
||||
deltachat_derive = { path = "./deltachat_derive" }
|
||||
libc = "0.2.51"
|
||||
pgp = { version = "0.2", default-features = false }
|
||||
hex = "0.3.2"
|
||||
@@ -37,6 +36,7 @@ rustyline = "4.1.0"
|
||||
lazy_static = "1.3.0"
|
||||
regex = "1.1.6"
|
||||
rusqlite = { version = "0.20", features = ["bundled"] }
|
||||
addr = "0.2.0"
|
||||
r2d2_sqlite = "0.12.0"
|
||||
r2d2 = "0.8.5"
|
||||
strum = "0.15.0"
|
||||
@@ -45,7 +45,6 @@ thread-local-object = "0.1.0"
|
||||
backtrace = "0.3.33"
|
||||
byteorder = "1.3.1"
|
||||
itertools = "0.8.0"
|
||||
image-meta = "0.1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.0"
|
||||
@@ -54,8 +53,7 @@ pretty_env_logger = "0.3.0"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"deltachat-ffi",
|
||||
"deltachat_derive",
|
||||
"deltachat-ffi"
|
||||
]
|
||||
|
||||
[[example]]
|
||||
|
||||
@@ -89,14 +89,6 @@ $ cargo test --all
|
||||
$ cargo build -p deltachat_ffi --release
|
||||
```
|
||||
|
||||
### Expensive tests
|
||||
|
||||
Some tests are expensive and marked with `#[ignore]`, to run these
|
||||
use the `--ignored` argument to the test binary (not to cargo itself):
|
||||
```sh
|
||||
$ cargo test -- --ignored
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- `vendored`: When using Openssl for TLS, this bundles a vendored version.
|
||||
|
||||
@@ -16,7 +16,7 @@ export BRANCH=${CIRCLE_BRANCH:-test7}
|
||||
#fi
|
||||
|
||||
# run everything else inside docker (TESTS, DOCS, WHEELS)
|
||||
docker run -e DCC_PY_LIVECONFIG -e BRANCH -e TESTS -e DOCS \
|
||||
docker run -e BRANCH -e TESTS -e DOCS \
|
||||
--rm -it -v $(pwd):/mnt -w /mnt \
|
||||
deltachat/coredeps ci_scripts/run_all.sh
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ export BRANCH=${CIRCLE_BRANCH:?specify branch for uploading purposes}
|
||||
|
||||
|
||||
# python docs to py.delta.chat
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null delta@py.delta.chat mkdir -p build/${BRANCH}
|
||||
rsync -avz \
|
||||
-e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" \
|
||||
"$PYDOCDIR/html/" \
|
||||
@@ -38,13 +37,11 @@ pip install devpi-client
|
||||
devpi use https://m.devpi.net
|
||||
devpi login dc --password $DEVPI_LOGIN
|
||||
|
||||
N_BRANCH=${BRANCH//[\/]}
|
||||
|
||||
devpi use dc/$N_BRANCH || {
|
||||
devpi index -c $N_BRANCH
|
||||
devpi use dc/$N_BRANCH
|
||||
devpi use dc/$BRANCH || {
|
||||
devpi index -c $BRANCH
|
||||
devpi use dc/$BRANCH
|
||||
}
|
||||
devpi index $N_BRANCH bases=/root/pypi
|
||||
devpi index $BRANCH bases=/root/pypi
|
||||
devpi upload deltachat*.whl
|
||||
|
||||
popd
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
set -e -x
|
||||
|
||||
# Install Rust
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2019-07-10 -y
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2019-04-19 -y
|
||||
export PATH=/root/.cargo/bin:$PATH
|
||||
rustc --version
|
||||
|
||||
# remove some 300-400 MB that we don't need for automated builds
|
||||
rm -rf /root/.rustup/toolchains/nightly-2019-07-10-x86_64-unknown-linux-gnu/share/
|
||||
rm -rf /root/.rustup/toolchains/nightly-2019-04-19-x86_64-unknown-linux-gnu/share/
|
||||
|
||||
@@ -37,10 +37,6 @@ if [ -n "$TESTS" ]; then
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# run tox
|
||||
# XXX we don't run liveconfig tests because they hang sometimes
|
||||
# see https://github.com/deltachat/deltachat-core-rust/issues/331
|
||||
# unset DCC_PY_LIVECONFIG
|
||||
|
||||
tox --workdir "$TOXWORKDIR" -e lint,py27,py35,py36,py37,auditwheels
|
||||
popd
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat_ffi"
|
||||
version = "1.0.0-alpha.4"
|
||||
version = "1.0.0-alpha.3"
|
||||
description = "Deltachat FFI"
|
||||
authors = ["dignifiedquire <dignifiedquire@gmail.com>"]
|
||||
edition = "2018"
|
||||
@@ -25,3 +25,4 @@ default = ["vendored", "nightly", "ringbuf"]
|
||||
vendored = ["deltachat/vendored"]
|
||||
nightly = ["deltachat/nightly"]
|
||||
ringbuf = ["deltachat/ringbuf"]
|
||||
|
||||
|
||||
@@ -372,10 +372,14 @@ void dc_delete_all_locations (dc_context_t*);
|
||||
*/
|
||||
void dc_array_unref (dc_array_t*);
|
||||
|
||||
void dc_array_add_uint (dc_array_t*, uintptr_t);
|
||||
void dc_array_add_id (dc_array_t*, uint32_t);
|
||||
void dc_array_add_ptr (dc_array_t*, void*);
|
||||
|
||||
size_t dc_array_get_cnt (const dc_array_t*);
|
||||
uintptr_t dc_array_get_uint (const dc_array_t*, size_t index);
|
||||
uint32_t dc_array_get_id (const dc_array_t*, size_t index);
|
||||
void* dc_array_get_ptr (const dc_array_t*, size_t index);
|
||||
double dc_array_get_latitude (const dc_array_t*, size_t index);
|
||||
double dc_array_get_longitude (const dc_array_t*, size_t index);
|
||||
double dc_array_get_accuracy (const dc_array_t*, size_t index);
|
||||
@@ -387,7 +391,7 @@ char* dc_array_get_marker (const dc_array_t*, size_t index);
|
||||
int dc_array_is_independent (const dc_array_t*, size_t index);
|
||||
|
||||
int dc_array_search_id (const dc_array_t*, uint32_t needle, size_t* indx);
|
||||
const uint32_t* dc_array_get_raw (const dc_array_t*);
|
||||
const uintptr_t* dc_array_get_raw (const dc_array_t*);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,14 +44,11 @@ pub unsafe extern "C" fn dc_context_new(
|
||||
Box::into_raw(Box::new(ctx))
|
||||
}
|
||||
|
||||
/// Release the context structure.
|
||||
///
|
||||
/// This function releases the memory of the `dc_context_t` structure.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_context_unref(context: *mut dc_context_t) {
|
||||
assert!(!context.is_null());
|
||||
let context = &mut *context;
|
||||
context::dc_close(context);
|
||||
context::dc_context_unref(context);
|
||||
Box::from_raw(context);
|
||||
}
|
||||
|
||||
@@ -545,7 +542,7 @@ pub unsafe extern "C" fn dc_get_chat_contacts(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_array_t::from(dc_chat::dc_get_chat_contacts(context, chat_id)).into_raw()
|
||||
dc_chat::dc_get_chat_contacts(context, chat_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -645,7 +642,7 @@ pub unsafe extern "C" fn dc_set_chat_profile_image(
|
||||
assert!(chat_id > constants::DC_CHAT_ID_LAST_SPECIAL as u32);
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_set_chat_profile_image(context, chat_id, &dc_tools::to_string(image)) as libc::c_int
|
||||
dc_chat::dc_set_chat_profile_image(context, chat_id, image)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -817,7 +814,7 @@ pub unsafe extern "C" fn dc_get_contacts(
|
||||
};
|
||||
|
||||
match Contact::get_all(context, flags, query) {
|
||||
Ok(contacts) => dc_array_t::from(contacts).into_raw(),
|
||||
Ok(contacts) => contacts,
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
@@ -837,7 +834,7 @@ pub unsafe extern "C" fn dc_get_blocked_contacts(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_array_t::from(Contact::get_all_blocked(context)).into_raw()
|
||||
Contact::get_all_blocked(context)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -864,12 +861,7 @@ pub unsafe extern "C" fn dc_get_contact_encrinfo(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
Contact::get_encrinfo(context, contact_id)
|
||||
.map(|s| s.strdup())
|
||||
.unwrap_or_else(|e| {
|
||||
error!(context, 0, "{}", e);
|
||||
std::ptr::null_mut()
|
||||
})
|
||||
Contact::get_encrinfo(context, contact_id).strdup()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1064,12 +1056,24 @@ pub unsafe extern "C" fn dc_array_unref(a: *mut dc_array::dc_array_t) {
|
||||
dc_array::dc_array_unref(a)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_add_uint(array: *mut dc_array_t, item: libc::uintptr_t) {
|
||||
assert!(!array.is_null());
|
||||
|
||||
dc_array::dc_array_add_uint(array, item)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_add_id(array: *mut dc_array_t, item: libc::c_uint) {
|
||||
assert!(!array.is_null());
|
||||
|
||||
dc_array::dc_array_add_id(array, item)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_add_ptr(array: *mut dc_array_t, item: *mut libc::c_void) {
|
||||
assert!(!array.is_null());
|
||||
|
||||
dc_array::dc_array_add_ptr(array, item)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_cnt(array: *const dc_array_t) -> libc::size_t {
|
||||
@@ -1078,6 +1082,15 @@ pub unsafe extern "C" fn dc_array_get_cnt(array: *const dc_array_t) -> libc::siz
|
||||
dc_array::dc_array_get_cnt(array)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_uint(
|
||||
array: *const dc_array_t,
|
||||
index: libc::size_t,
|
||||
) -> libc::uintptr_t {
|
||||
assert!(!array.is_null());
|
||||
|
||||
dc_array::dc_array_get_uint(array, index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_id(
|
||||
array: *const dc_array_t,
|
||||
index: libc::size_t,
|
||||
@@ -1087,6 +1100,15 @@ pub unsafe extern "C" fn dc_array_get_id(
|
||||
dc_array::dc_array_get_id(array, index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_ptr(
|
||||
array: *const dc_array_t,
|
||||
index: libc::size_t,
|
||||
) -> *mut libc::c_void {
|
||||
assert!(!array.is_null());
|
||||
|
||||
dc_array::dc_array_get_ptr(array, index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_latitude(
|
||||
array: *const dc_array_t,
|
||||
index: libc::size_t,
|
||||
@@ -1171,7 +1193,7 @@ pub unsafe extern "C" fn dc_array_search_id(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_raw(array: *const dc_array_t) -> *const u32 {
|
||||
pub unsafe extern "C" fn dc_array_get_raw(array: *const dc_array_t) -> *const libc::size_t {
|
||||
assert!(!array.is_null());
|
||||
|
||||
dc_array::dc_array_get_raw(array)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
[package]
|
||||
name = "deltachat_derive"
|
||||
version = "0.1.0"
|
||||
authors = ["Dmitry Bogatov <KAction@debian.org>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = "0.14.4"
|
||||
quote = "0.6.3"
|
||||
@@ -1,45 +0,0 @@
|
||||
#![recursion_limit = "128"]
|
||||
extern crate proc_macro;
|
||||
|
||||
use crate::proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn;
|
||||
|
||||
// For now, assume (not check) that these macroses are applied to enum without
|
||||
// data. If this assumption is violated, compiler error will point to
|
||||
// generated code, which is not very user-friendly.
|
||||
|
||||
#[proc_macro_derive(ToSql)]
|
||||
pub fn to_sql_derive(input: TokenStream) -> TokenStream {
|
||||
let ast: syn::DeriveInput = syn::parse(input).unwrap();
|
||||
let name = &ast.ident;
|
||||
|
||||
let gen = quote! {
|
||||
impl rusqlite::types::ToSql for #name {
|
||||
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
|
||||
let num = *self as i64;
|
||||
let value = rusqlite::types::Value::Integer(num);
|
||||
let output = rusqlite::types::ToSqlOutput::Owned(value);
|
||||
|
||||
std::result::Result::Ok(output)
|
||||
}
|
||||
}
|
||||
};
|
||||
gen.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(FromSql)]
|
||||
pub fn from_sql_derive(input: TokenStream) -> TokenStream {
|
||||
let ast: syn::DeriveInput = syn::parse(input).unwrap();
|
||||
let name = &ast.ident;
|
||||
|
||||
let gen = quote! {
|
||||
impl rusqlite::types::FromSql for #name {
|
||||
fn column_result(col: rusqlite::types::ValueRef) -> rusqlite::types::FromSqlResult<Self> {
|
||||
let inner = rusqlite::types::FromSql::column_result(col)?;
|
||||
num_traits::FromPrimitive::from_i64(inner).ok_or(rusqlite::types::FromSqlError::InvalidType)
|
||||
}
|
||||
}
|
||||
};
|
||||
gen.into()
|
||||
}
|
||||
@@ -125,7 +125,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
return 0;
|
||||
}
|
||||
|
||||
let ok_to_continue;
|
||||
let mut current_block: u64;
|
||||
let mut success: libc::c_int = 0;
|
||||
let real_spec: *mut libc::c_char;
|
||||
let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
@@ -138,71 +138,77 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
.sql
|
||||
.set_config(context, "import_spec", Some(as_str(real_spec)))
|
||||
.unwrap();
|
||||
ok_to_continue = true;
|
||||
current_block = 7149356873433890176;
|
||||
} else {
|
||||
let rs = context.sql.get_config(context, "import_spec");
|
||||
if rs.is_none() {
|
||||
error!(context, 0, "Import: No file or folder given.");
|
||||
ok_to_continue = false;
|
||||
current_block = 8522321847195001863;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 7149356873433890176;
|
||||
}
|
||||
real_spec = rs.unwrap_or_default().strdup();
|
||||
}
|
||||
if ok_to_continue {
|
||||
let ok_to_continue2;
|
||||
suffix = dc_get_filesuffix_lc(real_spec);
|
||||
if !suffix.is_null() && strcmp(suffix, b"eml\x00" as *const u8 as *const libc::c_char) == 0
|
||||
{
|
||||
if 0 != dc_poke_eml_file(context, real_spec) {
|
||||
read_cnt += 1
|
||||
}
|
||||
ok_to_continue2 = true;
|
||||
} else {
|
||||
/* import a directory */
|
||||
let dir_name = std::path::Path::new(as_str(real_spec));
|
||||
let dir = std::fs::read_dir(dir_name);
|
||||
if dir.is_err() {
|
||||
error!(
|
||||
context,
|
||||
0,
|
||||
"Import: Cannot open directory \"{}\".",
|
||||
as_str(real_spec),
|
||||
);
|
||||
ok_to_continue2 = false;
|
||||
match current_block {
|
||||
8522321847195001863 => {}
|
||||
_ => {
|
||||
suffix = dc_get_filesuffix_lc(real_spec);
|
||||
if !suffix.is_null()
|
||||
&& strcmp(suffix, b"eml\x00" as *const u8 as *const libc::c_char) == 0
|
||||
{
|
||||
if 0 != dc_poke_eml_file(context, real_spec) {
|
||||
read_cnt += 1
|
||||
}
|
||||
current_block = 1622411330066726685;
|
||||
} else {
|
||||
let dir = dir.unwrap();
|
||||
for entry in dir {
|
||||
if entry.is_err() {
|
||||
break;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
let name_f = entry.file_name();
|
||||
let name = name_f.to_string_lossy();
|
||||
if name.ends_with(".eml") {
|
||||
let path_plus_name = format!("{}/{}", as_str(real_spec), name);
|
||||
info!(context, 0, "Import: {}", path_plus_name);
|
||||
let path_plus_name_c = CString::yolo(path_plus_name);
|
||||
if 0 != dc_poke_eml_file(context, path_plus_name_c.as_ptr()) {
|
||||
read_cnt += 1
|
||||
/* import a directory */
|
||||
let dir_name = std::path::Path::new(as_str(real_spec));
|
||||
let dir = std::fs::read_dir(dir_name);
|
||||
if dir.is_err() {
|
||||
error!(
|
||||
context,
|
||||
0,
|
||||
"Import: Cannot open directory \"{}\".",
|
||||
as_str(real_spec),
|
||||
);
|
||||
current_block = 8522321847195001863;
|
||||
} else {
|
||||
let dir = dir.unwrap();
|
||||
for entry in dir {
|
||||
if entry.is_err() {
|
||||
break;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
let name_f = entry.file_name();
|
||||
let name = name_f.to_string_lossy();
|
||||
if name.ends_with(".eml") {
|
||||
let path_plus_name = format!("{}/{}", as_str(real_spec), name);
|
||||
info!(context, 0, "Import: {}", path_plus_name);
|
||||
let path_plus_name_c = CString::yolo(path_plus_name);
|
||||
if 0 != dc_poke_eml_file(context, path_plus_name_c.as_ptr()) {
|
||||
read_cnt += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
current_block = 1622411330066726685;
|
||||
}
|
||||
ok_to_continue2 = true;
|
||||
}
|
||||
}
|
||||
if ok_to_continue2 {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Import: {} items read from \"{}\".",
|
||||
read_cnt,
|
||||
as_str(real_spec)
|
||||
);
|
||||
if read_cnt > 0 {
|
||||
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
|
||||
match current_block {
|
||||
8522321847195001863 => {}
|
||||
_ => {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Import: {} items read from \"{}\".",
|
||||
read_cnt,
|
||||
as_str(real_spec)
|
||||
);
|
||||
if read_cnt > 0 {
|
||||
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
|
||||
}
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,12 +301,13 @@ unsafe fn log_msglist(context: &Context, msglist: *mut dc_array_t) {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn log_contactlist(context: &Context, contacts: &Vec<u32>) {
|
||||
let mut contacts = contacts.clone();
|
||||
if !contacts.contains(&1) {
|
||||
contacts.push(1);
|
||||
unsafe fn log_contactlist(context: &Context, contacts: *mut dc_array_t) {
|
||||
if !dc_array_search_id(contacts, 1 as uint32_t, 0 as *mut size_t) {
|
||||
dc_array_add_id(contacts, 1 as uint32_t);
|
||||
}
|
||||
for contact_id in contacts {
|
||||
let cnt = dc_array_get_cnt(contacts);
|
||||
for i in 0..cnt {
|
||||
let contact_id = dc_array_get_id(contacts, i as size_t);
|
||||
let line;
|
||||
let mut line2 = "".to_string();
|
||||
if let Ok(contact) = Contact::get_by_id(context, contact_id) {
|
||||
@@ -464,7 +471,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
event <event-id to test>\n\
|
||||
fileinfo <file>\n\
|
||||
clear -- clear screen\n\
|
||||
exit or quit\n\
|
||||
exit\n\
|
||||
============================================="
|
||||
),
|
||||
},
|
||||
@@ -597,13 +604,9 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
}
|
||||
"listchats" | "listarchived" | "chats" => {
|
||||
let listflags = if arg0 == "listarchived" { 0x01 } else { 0 };
|
||||
let chatlist = Chatlist::try_load(
|
||||
context,
|
||||
listflags,
|
||||
if arg1.is_empty() { None } else { Some(arg1) },
|
||||
None,
|
||||
)?;
|
||||
let chatlist = Chatlist::try_load(context, listflags, Some(arg1), None)?;
|
||||
|
||||
let mut i: usize;
|
||||
let cnt = chatlist.len();
|
||||
if cnt > 0 {
|
||||
info!(
|
||||
@@ -611,7 +614,9 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
"================================================================================"
|
||||
);
|
||||
|
||||
for i in (0..cnt).rev() {
|
||||
i = cnt - 1;
|
||||
|
||||
while i > 0 {
|
||||
let chat = dc_get_chat(context, chatlist.get_chat_id(i));
|
||||
let temp_subtitle = dc_chat_get_subtitle(chat);
|
||||
let temp_name = dc_chat_get_name(chat);
|
||||
@@ -665,6 +670,8 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
context, 0,
|
||||
"================================================================================"
|
||||
);
|
||||
|
||||
i -= 1
|
||||
}
|
||||
}
|
||||
if dc_is_sending_locations_to_chat(context, 0 as uint32_t) {
|
||||
@@ -810,7 +817,15 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty(), "Argument <image> missing.");
|
||||
|
||||
if dc_set_chat_profile_image(context, dc_chat_get_id(sel_chat), arg1) {
|
||||
if 0 != dc_set_chat_profile_image(
|
||||
context,
|
||||
dc_chat_get_id(sel_chat),
|
||||
if !arg1.is_empty() {
|
||||
arg1_c
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
},
|
||||
) {
|
||||
println!("Chat image set");
|
||||
} else {
|
||||
bail!("Failed to set chat image");
|
||||
@@ -820,14 +835,16 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
|
||||
let contacts = dc_get_chat_contacts(context, dc_chat_get_id(sel_chat));
|
||||
ensure!(!contacts.is_null(), "Failed to retreive contacts");
|
||||
info!(context, 0, "Memberlist:");
|
||||
|
||||
log_contactlist(context, &contacts);
|
||||
log_contactlist(context, contacts);
|
||||
println!(
|
||||
"{} contacts\nLocation streaming: {}",
|
||||
contacts.len(),
|
||||
dc_array_get_cnt(contacts),
|
||||
dc_is_sending_locations_to_chat(context, dc_chat_get_id(sel_chat)),
|
||||
);
|
||||
dc_array_unref(contacts);
|
||||
}
|
||||
"getlocations" => {
|
||||
let contact_id = arg1.parse().unwrap_or_default();
|
||||
@@ -1047,8 +1064,13 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
},
|
||||
Some(arg1),
|
||||
)?;
|
||||
log_contactlist(context, &contacts);
|
||||
println!("{} contacts.", contacts.len());
|
||||
if !contacts.is_null() {
|
||||
log_contactlist(context, contacts);
|
||||
println!("{} contacts.", dc_array_get_cnt(contacts) as libc::c_int,);
|
||||
dc_array_unref(contacts);
|
||||
} else {
|
||||
bail!("");
|
||||
}
|
||||
}
|
||||
"addcontact" => {
|
||||
ensure!(!arg1.is_empty(), "Arguments [<name>] <addr> expected.");
|
||||
@@ -1069,7 +1091,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
|
||||
let mut res = format!("Contact info for: {}:\n\n", name_n_addr);
|
||||
|
||||
res += &Contact::get_encrinfo(context, contact_id)?;
|
||||
res += &Contact::get_encrinfo(context, contact_id);
|
||||
|
||||
let chatlist = Chatlist::try_load(context, 0, None, Some(contact_id))?;
|
||||
let chatlist_cnt = chatlist.len();
|
||||
@@ -1118,10 +1140,20 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
}
|
||||
"fileinfo" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <file> missing.");
|
||||
let mut buf = 0 as *mut libc::c_uchar;
|
||||
let mut buf_bytes = 0;
|
||||
let mut w = 0;
|
||||
let mut h = 0;
|
||||
|
||||
if let Some(buf) = dc_read_file_safe(context, &arg1) {
|
||||
let (width, height) = dc_get_filemeta(&buf)?;
|
||||
println!("width={}, height={}", width, height);
|
||||
if 0 != dc_read_file(
|
||||
context,
|
||||
arg1_c,
|
||||
&mut buf as *mut *mut libc::c_uchar as *mut *mut libc::c_void,
|
||||
&mut buf_bytes,
|
||||
) {
|
||||
dc_get_filemeta(buf as *const libc::c_void, buf_bytes, &mut w, &mut h);
|
||||
println!("width={}, height={}", w, h,);
|
||||
free(buf as *mut libc::c_void);
|
||||
} else {
|
||||
bail!("Command failed.");
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
//!
|
||||
//! Usage: cargo run --example repl --release -- <databasefile>
|
||||
//! All further options can be set using the set-command (type ? for help).
|
||||
#![feature(ptr_cast)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate deltachat;
|
||||
@@ -334,8 +335,8 @@ const CONTACT_COMMANDS: [&'static str; 6] = [
|
||||
"delcontact",
|
||||
"cleanupcontacts",
|
||||
];
|
||||
const MISC_COMMANDS: [&'static str; 9] = [
|
||||
"getqr", "getbadqr", "checkqr", "event", "fileinfo", "clear", "exit", "quit", "help",
|
||||
const MISC_COMMANDS: [&'static str; 8] = [
|
||||
"getqr", "getbadqr", "checkqr", "event", "fileinfo", "clear", "exit", "help",
|
||||
];
|
||||
|
||||
impl Hinter for DcHelper {
|
||||
@@ -455,6 +456,12 @@ fn main_0(args: Vec<String>) -> Result<(), failure::Error> {
|
||||
println!("history saved");
|
||||
{
|
||||
stop_threads(&ctx.read().unwrap());
|
||||
|
||||
unsafe {
|
||||
let mut ctx = ctx.write().unwrap();
|
||||
dc_close(&mut ctx);
|
||||
dc_context_unref(&mut ctx);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -549,7 +556,7 @@ unsafe fn handle_cmd(line: &str, ctx: Arc<RwLock<Context>>) -> Result<ExitResult
|
||||
dc_join_securejoin(&ctx.read().unwrap(), arg1_c);
|
||||
}
|
||||
}
|
||||
"exit" | "quit" => return Ok(ExitResult::Exit),
|
||||
"exit" => return Ok(ExitResult::Exit),
|
||||
_ => dc_cmdline(&ctx.read().unwrap(), line)?,
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ without any "build-from-source" steps.
|
||||
1. `Install virtualenv <https://virtualenv.pypa.io/en/stable/installation/>`_,
|
||||
then create a fresh python environment and activate it in your shell::
|
||||
|
||||
virtualenv venv # or: python -m venv
|
||||
virtualenv -p python3 venv
|
||||
source venv/bin/activate
|
||||
|
||||
Afterwards, invoking ``python`` or ``pip install`` will only
|
||||
@@ -39,12 +39,6 @@ and push them to a python package index. To install the latest github ``master``
|
||||
|
||||
pip install -i https://m.devpi.net/dc/master deltachat
|
||||
|
||||
.. note::
|
||||
|
||||
If you can help to automate the building of wheels for Mac or Windows,
|
||||
that'd be much appreciated! please then get
|
||||
`in contact with us <https://delta.chat/en/contribute>`_.
|
||||
|
||||
|
||||
Installing bindings from source
|
||||
===============================
|
||||
@@ -54,55 +48,34 @@ to core deltachat library::
|
||||
|
||||
git clone https://github.com/deltachat/deltachat-core-rust
|
||||
cd deltachat-core-rust
|
||||
cargo build -p deltachat_ffi --release
|
||||
|
||||
This will result in a ``libdeltachat.so`` and ``libdeltachat.a`` files
|
||||
in the ``target/release`` directory. These files are needed for
|
||||
creating the python bindings for deltachat::
|
||||
|
||||
cd python
|
||||
DCC_RS_DEV=`pwd`/.. pip install -e .
|
||||
|
||||
If you don't have one active, create and activate a python "virtualenv":
|
||||
Now test if the bindings find the correct library::
|
||||
|
||||
python virtualenv venv # or python -m venv
|
||||
source venv/bin/activate
|
||||
python -c 'import deltachat ; print(deltachat.__version__)'
|
||||
|
||||
Afterwards ``which python`` tells you that it comes out of the "venv"
|
||||
directory that contains all python install artifacts. Let's first
|
||||
install test tools::
|
||||
|
||||
pip install pytest pytest-timeout requests
|
||||
|
||||
then cargo-build and install the deltachat bindings::
|
||||
|
||||
python install_python_bindings.py
|
||||
|
||||
The bindings will be installed in release mode but with debug symbols.
|
||||
The release mode is neccessary because some tests generate RSA keys
|
||||
which is prohibitively slow in debug mode.
|
||||
|
||||
After succcessul binding installation you can finally run the tests::
|
||||
|
||||
pytest -v tests
|
||||
This should print your deltachat bindings version.
|
||||
|
||||
.. note::
|
||||
|
||||
Some tests are sometimes failing/hanging because of
|
||||
https://github.com/deltachat/deltachat-core-rust/issues/331
|
||||
and
|
||||
https://github.com/deltachat/deltachat-core-rust/issues/326
|
||||
If you can help to automate the building of wheels for Mac or Windows,
|
||||
that'd be much appreciated! please then get
|
||||
`in contact with us <https://delta.chat/en/contribute>`_.
|
||||
|
||||
Using a system-installed deltachat-core-rust
|
||||
--------------------------------------------
|
||||
|
||||
running "live" tests (experimental)
|
||||
-----------------------------------
|
||||
|
||||
If you want to run "liveconfig" functional tests you can set
|
||||
``DCC_PY_LIVECONFIG`` to:
|
||||
|
||||
- a particular https-url that you can ask for from the delta
|
||||
chat devs.
|
||||
|
||||
- or the path of a file that contains two lines, each describing
|
||||
via "addr=... mail_pwd=..." a test account login that will
|
||||
be used for the live tests.
|
||||
|
||||
With ``DCC_PY_LIVECONFIG`` set pytest invocations will use real
|
||||
e-mail accounts and run through all functional "liveconfig" tests.
|
||||
|
||||
When calling ``pip`` without specifying the ``DCC_RS_DEV`` environment
|
||||
variable cffi will try to use a ``deltachat.h`` from a system location
|
||||
like ``/usr/local/include`` and will try to dynamically link against a
|
||||
``libdeltachat.so`` in a similar location (e.g. ``/usr/local/lib``).
|
||||
|
||||
|
||||
Code examples
|
||||
@@ -111,34 +84,68 @@ Code examples
|
||||
You may look at `examples <https://py.delta.chat/examples.html>`_.
|
||||
|
||||
|
||||
Running tests
|
||||
=============
|
||||
|
||||
Get a checkout of the `deltachat-core-rust github repository`_ and type::
|
||||
|
||||
pip install tox
|
||||
./run-integration-tests.sh
|
||||
|
||||
If you want to run functional tests with real
|
||||
e-mail test accounts, generate a "liveconfig" file where each
|
||||
lines contains test account settings, for example::
|
||||
|
||||
# 'liveconfig' file specifying imap/smtp accounts
|
||||
addr=some-email@example.org mail_pw=password
|
||||
addr=other-email@example.org mail_pw=otherpassword
|
||||
|
||||
The "keyword=value" style allows to specify any
|
||||
`deltachat account config setting <https://c.delta.chat/classdc__context__t.html#aff3b894f6cfca46cab5248fdffdf083d>`_ so you can also specify smtp or imap servers, ports, ssl modes etc.
|
||||
Typically DC's automatic configuration allows to not specify these settings.
|
||||
|
||||
The ``run-integration-tests.sh`` script will automatically use
|
||||
``python/liveconfig`` if it exists, to manually run tests with this
|
||||
``liveconfig`` file use::
|
||||
|
||||
tox -- --liveconfig liveconfig
|
||||
|
||||
|
||||
.. _`deltachat-core-rust github repository`: https://github.com/deltachat/deltachat-core-rust
|
||||
.. _`deltachat-core`: https://github.com/deltachat/deltachat-core-rust
|
||||
|
||||
Running test using a debug build
|
||||
--------------------------------
|
||||
|
||||
If you need to examine e.g. a coredump you may want to run the tests
|
||||
using a debug build::
|
||||
|
||||
DCC_RS_TARGET=debug ./run-integration-tests.sh -e py37 -- -x -v -k failing_test
|
||||
|
||||
|
||||
Building manylinux1 wheels
|
||||
==========================
|
||||
|
||||
.. note::
|
||||
|
||||
This section may not fully work.
|
||||
|
||||
Building portable manylinux1 wheels which come with libdeltachat.so
|
||||
and all it's dependencies is easy using the provided docker tooling.
|
||||
|
||||
using docker pull / premade images
|
||||
------------------------------------
|
||||
|
||||
We publish a build environment under the ``deltachat/coredeps`` tag so
|
||||
We publish a build environment under the ``deltachat/wheel`` tag so
|
||||
that you can pull it from the ``hub.docker.com`` site's "deltachat"
|
||||
organization::
|
||||
|
||||
$ docker pull deltachat/coredeps
|
||||
$ docker pull deltachat/wheel
|
||||
|
||||
This docker image can be used to run tests and build Python wheels for all interpreters::
|
||||
The ``deltachat/wheel`` image can be used to build both libdeltachat.so
|
||||
and the Python wheels::
|
||||
|
||||
$ bash ci_scripts/ci_run.sh
|
||||
$ docker run --rm -it -v $(pwd):/io/ deltachat/wheel /io/python/wheelbuilder/build-wheels.sh
|
||||
|
||||
This command runs tests and build-wheel scripts in a docker container.
|
||||
This command runs a script within the image, after mounting ``$(pwd)`` as ``/io`` within
|
||||
the docker image. The script is specified as a path within the docker image's filesystem.
|
||||
The resulting wheel files will be in ``python/wheelhouse``.
|
||||
|
||||
|
||||
Optionally build your own docker image
|
||||
@@ -147,10 +154,10 @@ Optionally build your own docker image
|
||||
If you want to build your own custom docker image you can do this::
|
||||
|
||||
$ cd deltachat-core # cd to deltachat-core checkout directory
|
||||
$ docker build -t deltachat/coredeps ci_scripts/docker_coredeps
|
||||
$ docker build -t deltachat/wheel python/wheelbuilder/
|
||||
|
||||
This will use the ``ci_scripts/docker_coredeps/Dockerfile`` to build
|
||||
up docker image called ``deltachat/coredeps``. You can afterwards
|
||||
This will use the ``python/wheelbuilder/Dockerfile`` to build
|
||||
up docker image called ``deltachat/wheel``. You can afterwards
|
||||
find it with::
|
||||
|
||||
$ docker images
|
||||
|
||||
@@ -37,3 +37,16 @@ Message
|
||||
.. autoclass:: deltachat.message.Message
|
||||
:members:
|
||||
|
||||
MessageType
|
||||
------------
|
||||
|
||||
.. autoclass:: deltachat.message.MessageType
|
||||
:members:
|
||||
|
||||
MessageState
|
||||
------------
|
||||
|
||||
.. autoclass:: deltachat.message.MessageState
|
||||
:members:
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ Playing around on the commandline
|
||||
----------------------------------
|
||||
|
||||
Once you have :doc:`installed deltachat bindings <install>`
|
||||
you can start playing from the python interpreter commandline.
|
||||
you can start playing from the python interpreter commandline::
|
||||
|
||||
For example you can type ``python`` and then::
|
||||
|
||||
# instantiate and configure deltachat account
|
||||
@@ -22,7 +23,7 @@ For example you can type ``python`` and then::
|
||||
# create a contact and send a message
|
||||
contact = ac.create_contact("someother@email.address")
|
||||
chat = ac.create_chat_by_contact(contact)
|
||||
chat.send_text("hi from the python interpreter command line")
|
||||
chat.send_text_message("hi from the python interpreter command line")
|
||||
|
||||
Checkout our :doc:`api` for the various high-level things you can do
|
||||
to send/receive messages, create contacts and chats.
|
||||
|
||||
@@ -6,18 +6,29 @@
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ["DCC_RS_TARGET"] = target = "release"
|
||||
if "DCC_RS_DEV" not in os.environ:
|
||||
dn = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
os.environ["DCC_RS_DEV"] = dn
|
||||
|
||||
os.environ["RUSTFLAGS"] = "-g"
|
||||
subprocess.check_call([
|
||||
"cargo", "build", "-p", "deltachat_ffi", "--" + target
|
||||
])
|
||||
toml = os.path.join(os.getcwd(), "..", "Cargo.toml")
|
||||
assert os.path.exists(toml)
|
||||
with open(toml) as f:
|
||||
s = orig = f.read()
|
||||
s += "\n"
|
||||
s += "[profile.release]\n"
|
||||
s += "debug = true\n"
|
||||
with open(toml, "w") as f:
|
||||
f.write(s)
|
||||
print("temporarily modifying Cargo.toml to provide release build with debug symbols ")
|
||||
try:
|
||||
subprocess.check_call([
|
||||
"cargo", "build", "-p", "deltachat_ffi", "--" + target
|
||||
])
|
||||
finally:
|
||||
with open(toml, "w") as f:
|
||||
f.write(orig)
|
||||
print("\nreseted Cargo.toml to previous original state")
|
||||
|
||||
subprocess.check_call("rm -rf build/ src/deltachat/*.so" , shell=True)
|
||||
|
||||
subprocess.check_call([
|
||||
|
||||
@@ -6,15 +6,10 @@ import platform
|
||||
import os
|
||||
import cffi
|
||||
import shutil
|
||||
from os.path import dirname as dn
|
||||
from os.path import abspath
|
||||
|
||||
|
||||
def ffibuilder():
|
||||
projdir = os.environ.get('DCC_RS_DEV')
|
||||
if not projdir:
|
||||
p = dn(dn(dn(dn(abspath(__file__)))))
|
||||
projdir = os.environ["DCC_RS_DEV"] = p
|
||||
target = os.environ.get('DCC_RS_TARGET', 'release')
|
||||
if projdir:
|
||||
if platform.system() == 'Darwin':
|
||||
|
||||
@@ -50,9 +50,8 @@ class Account(object):
|
||||
self._configkeys = self.get_config("sys.config_keys").split()
|
||||
self._imex_completed = threading.Event()
|
||||
|
||||
# XXX this can cause "illegal instructions" at test ends so we omit it for now
|
||||
# def __del__(self):
|
||||
# self.shutdown()
|
||||
def __del__(self):
|
||||
self.shutdown()
|
||||
|
||||
def _check_config_key(self, name):
|
||||
if name not in self._configkeys:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import pytest
|
||||
import requests
|
||||
import time
|
||||
from deltachat import Account
|
||||
from deltachat import props
|
||||
from deltachat.capi import lib
|
||||
import tempfile
|
||||
|
||||
@@ -36,8 +36,6 @@ def pytest_runtest_call(item):
|
||||
|
||||
|
||||
def pytest_report_header(config, startdir):
|
||||
summary = []
|
||||
|
||||
t = tempfile.mktemp()
|
||||
try:
|
||||
ac = Account(t, eventlogging=False)
|
||||
@@ -45,18 +43,13 @@ def pytest_report_header(config, startdir):
|
||||
ac.shutdown()
|
||||
finally:
|
||||
os.remove(t)
|
||||
summary.extend(['Deltachat core={} sqlite={}'.format(
|
||||
summary = ['Deltachat core={} sqlite={}'.format(
|
||||
info['deltachat_core_version'],
|
||||
info['sqlite_version'],
|
||||
)])
|
||||
|
||||
cfg = config.option.liveconfig
|
||||
)]
|
||||
cfg = config.getoption('--liveconfig')
|
||||
if cfg:
|
||||
if "#" in cfg:
|
||||
url, token = cfg.split("#", 1)
|
||||
summary.append('Liveconfig provider: {}#<token ommitted>'.format(url))
|
||||
else:
|
||||
summary.append('Liveconfig file: {}'.format(cfg))
|
||||
summary.append('Liveconfig: {}'.format(os.path.abspath(cfg)))
|
||||
return summary
|
||||
|
||||
|
||||
@@ -73,56 +66,9 @@ def data():
|
||||
return Data()
|
||||
|
||||
|
||||
class SessionLiveConfigFromFile:
|
||||
def __init__(self, fn):
|
||||
self.fn = fn
|
||||
self.configlist = []
|
||||
for line in open(fn):
|
||||
if line.strip() and not line.strip().startswith('#'):
|
||||
d = {}
|
||||
for part in line.split():
|
||||
name, value = part.split("=")
|
||||
d[name] = value
|
||||
self.configlist.append(d)
|
||||
|
||||
def get(self, index):
|
||||
return self.configlist[index]
|
||||
|
||||
def exists(self):
|
||||
return bool(self.configlist)
|
||||
|
||||
|
||||
class SessionLiveConfigFromURL:
|
||||
def __init__(self, url, create_token):
|
||||
self.configlist = []
|
||||
for i in range(2):
|
||||
res = requests.post(url, json={"token_create_user": int(create_token)})
|
||||
if res.status_code != 200:
|
||||
pytest.skip("creating newtmpuser failed {!r}".format(res))
|
||||
d = res.json()
|
||||
config = dict(addr=d["email"], mail_pw=d["password"])
|
||||
self.configlist.append(config)
|
||||
|
||||
def get(self, index):
|
||||
return self.configlist[index]
|
||||
|
||||
def exists(self):
|
||||
return bool(self.configlist)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def session_liveconfig(request):
|
||||
liveconfig_opt = request.config.option.liveconfig
|
||||
if liveconfig_opt:
|
||||
if liveconfig_opt.startswith("http"):
|
||||
url, create_token = liveconfig_opt.split("#", 1)
|
||||
return SessionLiveConfigFromURL(url, create_token)
|
||||
else:
|
||||
return SessionLiveConfigFromFile(liveconfig_opt)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def acfactory(pytestconfig, tmpdir, request, session_liveconfig):
|
||||
def acfactory(pytestconfig, tmpdir, request):
|
||||
fn = pytestconfig.getoption("--liveconfig")
|
||||
|
||||
class AccountMaker:
|
||||
def __init__(self):
|
||||
@@ -136,6 +82,18 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig):
|
||||
fin = self._finalizers.pop()
|
||||
fin()
|
||||
|
||||
@props.cached
|
||||
def configlist(self):
|
||||
configlist = []
|
||||
for line in open(fn):
|
||||
if line.strip() and not line.strip().startswith('#'):
|
||||
d = {}
|
||||
for part in line.split():
|
||||
name, value = part.split("=")
|
||||
d[name] = value
|
||||
configlist.append(d)
|
||||
return configlist
|
||||
|
||||
def get_unconfigured_account(self):
|
||||
self.offline_count += 1
|
||||
tmpdb = tmpdir.join("offlinedb%d" % self.offline_count)
|
||||
@@ -158,12 +116,10 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig):
|
||||
return ac
|
||||
|
||||
def get_online_configuring_account(self):
|
||||
if not session_liveconfig:
|
||||
pytest.skip("specify DCC_PY_LIVECONFIG or --liveconfig")
|
||||
configdict = session_liveconfig.get(self.live_count)
|
||||
if not fn:
|
||||
pytest.skip("specify a --liveconfig file to run tests with real accounts")
|
||||
self.live_count += 1
|
||||
if "e2ee_enabled" not in configdict:
|
||||
configdict["e2ee_enabled"] = "1"
|
||||
configdict = self.configlist.pop(0)
|
||||
tmpdb = tmpdir.join("livedb%d" % self.live_count)
|
||||
ac = Account(tmpdb.strpath, logid="ac{}".format(self.live_count))
|
||||
ac._evlogger.init_time = self.init_time
|
||||
|
||||
@@ -427,37 +427,6 @@ class TestOnlineAccount:
|
||||
lp.step("2")
|
||||
assert msg_out.is_out_mdn_received()
|
||||
|
||||
def test_send_and_receive_will_encrypt_decrypt(self, acfactory, lp):
|
||||
lp.sec("starting accounts, waiting for configuration")
|
||||
ac1 = acfactory.get_online_configuring_account()
|
||||
ac2 = acfactory.get_online_configuring_account()
|
||||
c2 = ac1.create_contact(email=ac2.get_config("addr"))
|
||||
chat = ac1.create_chat_by_contact(c2)
|
||||
assert chat.id >= const.DC_CHAT_ID_LAST_SPECIAL
|
||||
|
||||
wait_configuration_progress(ac1, 1000)
|
||||
wait_configuration_progress(ac2, 1000)
|
||||
|
||||
lp.sec("sending text message from ac1 to ac2")
|
||||
msg_out = chat.send_text("message1")
|
||||
|
||||
lp.sec("wait for ac2 to receive message")
|
||||
ev = ac2._evlogger.get_matching("DC_EVENT_MSGS_CHANGED")
|
||||
assert ev[2] == msg_out.id
|
||||
msg_in = ac2.get_message_by_id(msg_out.id)
|
||||
assert msg_in.text == "message1"
|
||||
|
||||
lp.sec("create new chat with contact and send back (encrypted) message")
|
||||
chat2b = ac2.create_chat_by_message(msg_in)
|
||||
chat2b.send_text("message-back")
|
||||
|
||||
lp.sec("wait for ac1 to receive message")
|
||||
ev = ac1._evlogger.get_matching("DC_EVENT_INCOMING_MSG")
|
||||
assert ev[1] == chat.id
|
||||
assert ev[2] > msg_out.id
|
||||
msg_back = ac1.get_message_by_id(ev[2])
|
||||
assert msg_back.text == "message-back"
|
||||
|
||||
def test_saved_mime_on_received_message(self, acfactory, lp):
|
||||
lp.sec("starting accounts, waiting for configuration")
|
||||
ac1 = acfactory.get_online_configuring_account()
|
||||
|
||||
@@ -19,7 +19,6 @@ deps =
|
||||
pytest
|
||||
pytest-faulthandler
|
||||
pdbpp
|
||||
requests
|
||||
|
||||
[testenv:auditwheels]
|
||||
skipsdist = True
|
||||
@@ -52,7 +51,6 @@ commands =
|
||||
|
||||
|
||||
[pytest]
|
||||
addopts = -v -rs
|
||||
python_files = tests/test_*.py
|
||||
norecursedirs = .tox
|
||||
xfail_strict=true
|
||||
|
||||
@@ -23,7 +23,7 @@ if [ $? != 0 ]; then
|
||||
fi
|
||||
|
||||
pushd python
|
||||
if [ -e "./liveconfig" && -z "$DCC_PY_LIVECONFIG" ]; then
|
||||
if [ -e "./liveconfig" ]; then
|
||||
export DCC_PY_LIVECONFIG=liveconfig
|
||||
fi
|
||||
tox "$@"
|
||||
|
||||
@@ -1 +1 @@
|
||||
nightly-2019-08-13
|
||||
nightly-2019-07-10
|
||||
|
||||
@@ -7,7 +7,6 @@ use crate::dc_msg::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::Result;
|
||||
use crate::stock::StockMessage;
|
||||
use std::ptr;
|
||||
|
||||
/// An object representing a single chatlist in memory.
|
||||
///
|
||||
@@ -291,7 +290,7 @@ impl<'a> Chatlist<'a> {
|
||||
};
|
||||
|
||||
if (*chat).id == DC_CHAT_ID_ARCHIVED_LINK as u32 {
|
||||
(*ret).text2 = dc_strdup(ptr::null())
|
||||
(*ret).text2 = dc_strdup(0 as *const libc::c_char)
|
||||
} else if lastmsg.is_null() || (*lastmsg).from_id == DC_CONTACT_ID_UNDEFINED as u32 {
|
||||
(*ret).text2 = self.context.stock_str(StockMessage::NoMessages).strdup();
|
||||
} else {
|
||||
|
||||
@@ -71,7 +71,7 @@ impl Context {
|
||||
let rel_path = self.sql.get_config(self, key);
|
||||
rel_path.map(|p| dc_get_abs_path_safe(self, &p).to_str().unwrap().to_string())
|
||||
}
|
||||
Config::SysVersion => Some((&*DC_VERSION_STR).clone()),
|
||||
Config::SysVersion => Some(std::str::from_utf8(DC_VERSION_STR).unwrap().into()),
|
||||
Config::SysMsgsizeMaxRecommended => Some(format!("{}", 24 * 1024 * 1024 / 4 * 3)),
|
||||
Config::SysConfigKeys => Some(get_config_keys_string()),
|
||||
_ => self.sql.get_config(self, key),
|
||||
@@ -120,7 +120,8 @@ impl Context {
|
||||
value
|
||||
};
|
||||
|
||||
self.sql.set_config(self, key, val)
|
||||
let ret = self.sql.set_config(self, key, val);
|
||||
ret
|
||||
}
|
||||
_ => self.sql.set_config(self, key, value),
|
||||
}
|
||||
|
||||
@@ -1,40 +1,15 @@
|
||||
//! Constants
|
||||
#![allow(non_camel_case_types)]
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
use rusqlite as sql;
|
||||
use rusqlite::types::*;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
pub const DC_VERSION_STR: &'static [u8; 14] = b"1.0.0-alpha.3\x00";
|
||||
|
||||
use deltachat_derive::*;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref DC_VERSION_STR: String = env!("CARGO_PKG_VERSION").to_string();
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql)]
|
||||
pub enum MoveState {
|
||||
Undefined = 0,
|
||||
Pending = 1,
|
||||
Stay = 2,
|
||||
Moving = 3,
|
||||
}
|
||||
|
||||
// some defaults
|
||||
pub const DC_E2EE_DEFAULT_ENABLED: i32 = 1;
|
||||
pub const DC_MDNS_DEFAULT_ENABLED: i32 = 1;
|
||||
pub const DC_INBOX_WATCH_DEFAULT: i32 = 1;
|
||||
pub const DC_SENTBOX_WATCH_DEFAULT: i32 = 1;
|
||||
pub const DC_MVBOX_WATCH_DEFAULT: i32 = 1;
|
||||
pub const DC_MVBOX_MOVE_DEFAULT: i32 = 1;
|
||||
|
||||
pub const DC_CHAT_NOT_BLOCKED: i32 = 0;
|
||||
pub const DC_CHAT_MANUALLY_BLOCKED: i32 = 1;
|
||||
pub const DC_CHAT_DEADDROP_BLOCKED: i32 = 2;
|
||||
|
||||
pub const DC_IMAP_SEEN: u32 = 0x1;
|
||||
|
||||
pub const DC_HANDSHAKE_CONTINUE_NORMAL_PROCESSING: i32 = 0x01;
|
||||
pub const DC_HANDSHAKE_STOP_NORMAL_PROCESSING: i32 = 0x02;
|
||||
pub const DC_HANDSHAKE_ADD_DELETE_JOB: i32 = 0x04;
|
||||
pub const DC_MOVE_STATE_MOVING: u32 = 3;
|
||||
pub const DC_MOVE_STATE_STAY: u32 = 2;
|
||||
pub const DC_MOVE_STATE_PENDING: u32 = 1;
|
||||
pub const DC_MOVE_STATE_UNDEFINED: u32 = 0;
|
||||
|
||||
pub const DC_GCL_ARCHIVED_ONLY: usize = 0x01;
|
||||
pub const DC_GCL_NO_SPECIALS: usize = 0x02;
|
||||
@@ -172,7 +147,7 @@ pub const DC_LP_IMAP_SOCKET_FLAGS: usize =
|
||||
pub const DC_LP_SMTP_SOCKET_FLAGS: usize =
|
||||
(DC_LP_SMTP_SOCKET_STARTTLS | DC_LP_SMTP_SOCKET_SSL | DC_LP_SMTP_SOCKET_PLAIN);
|
||||
|
||||
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql)]
|
||||
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||
#[repr(i32)]
|
||||
pub enum Viewtype {
|
||||
Unknown = 0,
|
||||
@@ -227,6 +202,23 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql for Viewtype {
|
||||
fn to_sql(&self) -> sql::Result<ToSqlOutput> {
|
||||
let num: i64 = self
|
||||
.to_i64()
|
||||
.expect("impossible: Viewtype -> i64 conversion failed");
|
||||
|
||||
Ok(ToSqlOutput::Owned(Value::Integer(num)))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql for Viewtype {
|
||||
fn column_result(col: ValueRef) -> FromSqlResult<Self> {
|
||||
let inner = FromSql::column_result(col)?;
|
||||
FromPrimitive::from_i64(inner).ok_or(FromSqlError::InvalidType)
|
||||
}
|
||||
}
|
||||
|
||||
// These constants are used as events
|
||||
// reported to the callback given to dc_context_new().
|
||||
// If you do not want to handle an event, it is always safe to return 0,
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::aheader::EncryptPreference;
|
||||
use crate::config::Config;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_array::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_tools::*;
|
||||
@@ -471,13 +472,13 @@ impl<'a> Contact<'a> {
|
||||
context: &Context,
|
||||
listflags: u32,
|
||||
query: Option<impl AsRef<str>>,
|
||||
) -> Result<Vec<u32>> {
|
||||
) -> Result<*mut dc_array_t> {
|
||||
let self_addr = context
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut add_self = false;
|
||||
let mut ret = Vec::new();
|
||||
let mut ret = dc_array_t::new(100);
|
||||
|
||||
if (listflags & DC_GCL_VERIFIED_ONLY) > 0 || query.is_some() {
|
||||
let s3str_like_cmd = format!(
|
||||
@@ -508,7 +509,7 @@ impl<'a> Contact<'a> {
|
||||
|row| row.get::<_, i32>(0),
|
||||
|ids| {
|
||||
for id in ids {
|
||||
ret.push(id? as u32);
|
||||
ret.add_id(id? as u32);
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
@@ -536,7 +537,7 @@ impl<'a> Contact<'a> {
|
||||
|row| row.get::<_, i32>(0),
|
||||
|ids| {
|
||||
for id in ids {
|
||||
ret.push(id? as u32);
|
||||
ret.add_id(id? as u32);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -544,10 +545,10 @@ impl<'a> Contact<'a> {
|
||||
}
|
||||
|
||||
if 0 != listflags & DC_GCL_ADD_SELF as u32 && add_self {
|
||||
ret.push(DC_CONTACT_ID_SELF as u32);
|
||||
ret.add_id(DC_CONTACT_ID_SELF as u32);
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
Ok(ret.into_raw())
|
||||
}
|
||||
|
||||
pub fn get_blocked_cnt(context: &Context) -> usize {
|
||||
@@ -563,27 +564,27 @@ impl<'a> Contact<'a> {
|
||||
}
|
||||
|
||||
/// Get blocked contacts.
|
||||
pub fn get_all_blocked(context: &Context) -> Vec<u32> {
|
||||
pub fn get_all_blocked(context: &Context) -> *mut dc_array_t {
|
||||
context
|
||||
.sql
|
||||
.query_map(
|
||||
"SELECT id FROM contacts WHERE id>? AND blocked!=0 ORDER BY LOWER(name||addr),id;",
|
||||
params![DC_CONTACT_ID_LAST_SPECIAL as i32],
|
||||
|row| row.get::<_, u32>(0),
|
||||
|row| row.get::<_, i32>(0),
|
||||
|ids| {
|
||||
ids.collect::<std::result::Result<Vec<_>, _>>()
|
||||
.map_err(Into::into)
|
||||
let mut ret = dc_array_t::new(100);
|
||||
|
||||
for id in ids {
|
||||
ret.add_id(id? as u32);
|
||||
}
|
||||
|
||||
Ok(ret.into_raw())
|
||||
},
|
||||
)
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_else(|_| std::ptr::null_mut())
|
||||
}
|
||||
|
||||
/// Returns a textual summary of the encryption state for the contact.
|
||||
///
|
||||
/// This function returns a string explaining the encryption state
|
||||
/// of the contact and if the connection is encrypted the
|
||||
/// fingerprints of the keys involved.
|
||||
pub fn get_encrinfo(context: &Context, contact_id: u32) -> Result<String> {
|
||||
pub fn get_encrinfo(context: &Context, contact_id: u32) -> String {
|
||||
let mut ret = String::new();
|
||||
|
||||
if let Ok(contact) = Contact::load_from_db(context, contact_id) {
|
||||
@@ -602,7 +603,7 @@ impl<'a> Contact<'a> {
|
||||
});
|
||||
ret += &p;
|
||||
if self_key.is_none() {
|
||||
dc_ensure_secret_key_exists(context)?;
|
||||
unsafe { dc_ensure_secret_key_exists(context) };
|
||||
self_key = Key::from_self_public(context, &loginparam.addr, &context.sql);
|
||||
}
|
||||
let p = context.stock_str(StockMessage::FingerPrints);
|
||||
@@ -645,7 +646,7 @@ impl<'a> Contact<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
ret
|
||||
}
|
||||
|
||||
/// Delete a contact. The contact is deleted from the local device. It may happen that this is not
|
||||
@@ -909,7 +910,20 @@ pub fn get_first_name<'a>(full_name: &'a str) -> &'a str {
|
||||
|
||||
/// Returns false if addr is an invalid address, otherwise true.
|
||||
pub fn may_be_valid_addr(addr: &str) -> bool {
|
||||
addr.parse::<EmailAddress>().is_ok()
|
||||
if addr.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let at = addr.find('@').unwrap_or_default();
|
||||
if at < 1 {
|
||||
return false;
|
||||
}
|
||||
let dot = addr.find('.').unwrap_or_default();
|
||||
if dot < 1 || dot > addr.len() - 3 || dot < at + 2 {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn addr_normalize(addr: &str) -> &str {
|
||||
|
||||
120
src/context.rs
120
src/context.rs
@@ -19,13 +19,11 @@ use crate::smtp::*;
|
||||
use crate::sql::Sql;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
use std::ptr;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Context {
|
||||
pub userdata: *mut libc::c_void,
|
||||
pub dbfile: Arc<RwLock<Option<PathBuf>>>,
|
||||
pub dbfile: Arc<RwLock<*mut libc::c_char>>,
|
||||
pub blobdir: Arc<RwLock<*mut libc::c_char>>,
|
||||
pub sql: Sql,
|
||||
pub inbox: Arc<RwLock<Imap>>,
|
||||
@@ -42,8 +40,6 @@ pub struct Context {
|
||||
pub bob: Arc<RwLock<BobStatus>>,
|
||||
pub last_smeared_timestamp: Arc<RwLock<i64>>,
|
||||
pub running_state: Arc<RwLock<RunningState>>,
|
||||
/// Mutex to avoid generating the key for the user more than once.
|
||||
pub generating_key_mutex: Mutex<()>,
|
||||
}
|
||||
|
||||
unsafe impl std::marker::Send for Context {}
|
||||
@@ -57,17 +53,15 @@ pub struct RunningState {
|
||||
|
||||
impl Context {
|
||||
pub fn has_dbfile(&self) -> bool {
|
||||
self.get_dbfile().is_some()
|
||||
!self.get_dbfile().is_null()
|
||||
}
|
||||
|
||||
pub fn has_blobdir(&self) -> bool {
|
||||
!self.get_blobdir().is_null()
|
||||
}
|
||||
|
||||
pub fn get_dbfile(&self) -> Option<PathBuf> {
|
||||
(*self.dbfile.clone().read().unwrap())
|
||||
.as_ref()
|
||||
.map(|x| x.clone())
|
||||
pub fn get_dbfile(&self) -> *const libc::c_char {
|
||||
*self.dbfile.clone().read().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_blobdir(&self) -> *const libc::c_char {
|
||||
@@ -83,14 +77,6 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Context {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dc_close(&self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RunningState {
|
||||
fn default() -> Self {
|
||||
RunningState {
|
||||
@@ -134,7 +120,7 @@ pub fn dc_context_new(
|
||||
) -> Context {
|
||||
Context {
|
||||
blobdir: Arc::new(RwLock::new(std::ptr::null_mut())),
|
||||
dbfile: Arc::new(RwLock::new(None)),
|
||||
dbfile: Arc::new(RwLock::new(std::ptr::null_mut())),
|
||||
inbox: Arc::new(RwLock::new({
|
||||
Imap::new(
|
||||
cb_get_config,
|
||||
@@ -145,7 +131,7 @@ pub fn dc_context_new(
|
||||
})),
|
||||
userdata,
|
||||
cb,
|
||||
os_name,
|
||||
os_name: os_name,
|
||||
running_state: Arc::new(RwLock::new(Default::default())),
|
||||
sql: Sql::new(),
|
||||
smtp: Arc::new(Mutex::new(Smtp::new())),
|
||||
@@ -176,7 +162,16 @@ pub fn dc_context_new(
|
||||
))),
|
||||
probe_imap_network: Arc::new(RwLock::new(false)),
|
||||
perform_inbox_jobs_needed: Arc::new(RwLock::new(false)),
|
||||
generating_key_mutex: Mutex::new(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn no_crashes_on_context_deref() {
|
||||
let mut ctx = dc_context_new(None, std::ptr::null_mut(), Some("Test OS".into()));
|
||||
unsafe { dc_context_unref(&mut ctx) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +201,7 @@ unsafe fn cb_precheck_imf(
|
||||
) -> libc::c_int {
|
||||
let mut rfc724_mid_exists: libc::c_int = 0i32;
|
||||
let msg_id: uint32_t;
|
||||
let mut old_server_folder: *mut libc::c_char = ptr::null_mut();
|
||||
let mut old_server_folder: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut old_server_uid: uint32_t = 0i32 as uint32_t;
|
||||
let mut mark_seen: libc::c_int = 0i32;
|
||||
msg_id = dc_rfc724_mid_exists(
|
||||
@@ -234,7 +229,7 @@ unsafe fn cb_precheck_imf(
|
||||
"[move] detected moved message {}",
|
||||
as_str(rfc724_mid),
|
||||
);
|
||||
dc_update_msg_move_state(context, rfc724_mid, MoveState::Stay);
|
||||
dc_update_msg_move_state(context, rfc724_mid, DC_MOVE_STATE_STAY);
|
||||
}
|
||||
if as_str(old_server_folder) != server_folder || old_server_uid != server_uid {
|
||||
dc_update_server_uid(context, rfc724_mid, server_folder, server_uid);
|
||||
@@ -245,7 +240,7 @@ unsafe fn cb_precheck_imf(
|
||||
}
|
||||
}
|
||||
free(old_server_folder as *mut libc::c_void);
|
||||
rfc724_mid_exists
|
||||
return rfc724_mid_exists;
|
||||
}
|
||||
|
||||
fn cb_set_config(context: &Context, key: &str, value: Option<&str>) {
|
||||
@@ -263,6 +258,12 @@ fn cb_get_config(context: &Context, key: &str) -> Option<String> {
|
||||
context.sql.get_config(context, key)
|
||||
}
|
||||
|
||||
pub unsafe fn dc_context_unref(context: &mut Context) {
|
||||
if 0 != dc_is_open(context) {
|
||||
dc_close(context);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_close(context: &Context) {
|
||||
info!(context, 0, "disconnecting INBOX-watch",);
|
||||
context.inbox.read().unwrap().disconnect(context);
|
||||
@@ -286,14 +287,18 @@ pub unsafe fn dc_close(context: &Context) {
|
||||
|
||||
context.sql.close(context);
|
||||
let mut dbfile = context.dbfile.write().unwrap();
|
||||
*dbfile = None;
|
||||
free(*dbfile as *mut libc::c_void);
|
||||
*dbfile = 0 as *mut libc::c_char;
|
||||
let mut blobdir = context.blobdir.write().unwrap();
|
||||
free(*blobdir as *mut libc::c_void);
|
||||
*blobdir = ptr::null_mut();
|
||||
*blobdir = 0 as *mut libc::c_char;
|
||||
}
|
||||
|
||||
pub unsafe fn dc_is_open(context: &Context) -> libc::c_int {
|
||||
context.sql.is_open() as libc::c_int
|
||||
match context.sql.is_open() {
|
||||
true => 1,
|
||||
false => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_userdata(context: &mut Context) -> *mut libc::c_void {
|
||||
@@ -305,14 +310,14 @@ pub unsafe fn dc_open(context: &Context, dbfile: &str, blobdir: Option<&str>) ->
|
||||
if 0 != dc_is_open(context) {
|
||||
return false;
|
||||
}
|
||||
*context.dbfile.write().unwrap() = Some(PathBuf::from(dbfile));
|
||||
if blobdir.is_some() && !blobdir.unwrap().is_empty() {
|
||||
*context.dbfile.write().unwrap() = dbfile.strdup();
|
||||
if blobdir.is_some() && blobdir.unwrap().len() > 0 {
|
||||
let dir = dc_ensure_no_slash_safe(blobdir.unwrap()).strdup();
|
||||
*context.blobdir.write().unwrap() = dir;
|
||||
} else {
|
||||
let dir = dbfile.to_string() + "-blobs";
|
||||
dc_create_folder(context, &dir);
|
||||
*context.blobdir.write().unwrap() = dir.strdup();
|
||||
let dir = (dbfile.to_string() + "-blobs").strdup();
|
||||
dc_create_folder(context, dir);
|
||||
*context.blobdir.write().unwrap() = dir;
|
||||
}
|
||||
// Create/open sqlite database, this may already use the blobdir
|
||||
let dbfile_path = std::path::Path::new(dbfile);
|
||||
@@ -440,7 +445,7 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
|
||||
public_key_count={}\n\
|
||||
fingerprint={}\n\
|
||||
level=awesome\n",
|
||||
&*DC_VERSION_STR,
|
||||
as_str(DC_VERSION_STR as *const u8 as *const _),
|
||||
rusqlite::version(),
|
||||
sqlite3_threadsafe(),
|
||||
// arch
|
||||
@@ -449,10 +454,11 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
|
||||
real_msgs,
|
||||
deaddrop_msgs,
|
||||
contacts,
|
||||
context
|
||||
.get_dbfile()
|
||||
.as_ref()
|
||||
.map_or(unset, |p| p.to_str().unwrap()),
|
||||
if context.has_dbfile() {
|
||||
as_str(context.get_dbfile())
|
||||
} else {
|
||||
unset
|
||||
},
|
||||
dbversion,
|
||||
if context.has_blobdir() {
|
||||
as_str(context.get_blobdir())
|
||||
@@ -481,7 +487,7 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_version_str() -> *mut libc::c_char {
|
||||
(&*DC_VERSION_STR).strdup()
|
||||
dc_strdup(DC_VERSION_STR as *const u8 as *const libc::c_char)
|
||||
}
|
||||
|
||||
pub fn dc_get_fresh_msgs(context: &Context) -> *mut dc_array_t {
|
||||
@@ -499,12 +505,13 @@ pub fn dc_get_fresh_msgs(context: &Context) -> *mut dc_array_t {
|
||||
&[10, 9, if 0 != show_deaddrop { 2 } else { 0 }],
|
||||
|row| row.get(0),
|
||||
|rows| {
|
||||
let mut ret = Vec::new();
|
||||
let mut ret = dc_array_t::new(128);
|
||||
|
||||
for row in rows {
|
||||
let id: u32 = row?;
|
||||
ret.push(id);
|
||||
let id = row?;
|
||||
ret.add_id(id);
|
||||
}
|
||||
Ok(dc_array_t::from(ret).into_raw())
|
||||
Ok(ret.into_raw())
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
@@ -538,7 +545,7 @@ pub fn dc_search_msgs(
|
||||
AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;"
|
||||
};
|
||||
|
||||
let mut ret = Vec::new();
|
||||
let mut ret = dc_array_t::new(100);
|
||||
|
||||
let success = context
|
||||
.sql
|
||||
@@ -548,7 +555,7 @@ pub fn dc_search_msgs(
|
||||
|row| row.get::<_, i32>(0),
|
||||
|rows| {
|
||||
for id in rows {
|
||||
ret.push(id? as u32);
|
||||
ret.add_id(id? as u32);
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
@@ -556,7 +563,7 @@ pub fn dc_search_msgs(
|
||||
.is_ok();
|
||||
|
||||
if success {
|
||||
return dc_array_t::from(ret).into_raw();
|
||||
return ret.into_raw();
|
||||
}
|
||||
|
||||
std::ptr::null_mut()
|
||||
@@ -584,24 +591,3 @@ pub fn dc_is_mvbox(context: &Context, folder_name: impl AsRef<str>) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn no_crashes_on_context_deref() {
|
||||
let ctx = dc_context_new(None, std::ptr::null_mut(), Some("Test OS".into()));
|
||||
std::mem::drop(ctx);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_context_double_close() {
|
||||
let ctx = dc_context_new(None, std::ptr::null_mut(), None);
|
||||
unsafe {
|
||||
dc_close(&ctx);
|
||||
dc_close(&ctx);
|
||||
}
|
||||
std::mem::drop(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
188
src/dc_array.rs
188
src/dc_array.rs
@@ -7,7 +7,7 @@ use crate::types::*;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum dc_array_t {
|
||||
Locations(Vec<dc_location>),
|
||||
Uint(Vec<u32>),
|
||||
Uint(Vec<uintptr_t>),
|
||||
}
|
||||
|
||||
impl dc_array_t {
|
||||
@@ -24,14 +24,18 @@ impl dc_array_t {
|
||||
Box::into_raw(Box::new(self))
|
||||
}
|
||||
|
||||
pub fn add_id(&mut self, item: uint32_t) {
|
||||
pub fn add_uint(&mut self, item: uintptr_t) {
|
||||
if let Self::Uint(array) = self {
|
||||
array.push(item);
|
||||
} else {
|
||||
panic!("Attempt to add id to array of other type");
|
||||
panic!("Attempt to add uint to array of other type");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_id(&mut self, item: uint32_t) {
|
||||
self.add_uint(item as uintptr_t);
|
||||
}
|
||||
|
||||
pub fn add_location(&mut self, location: dc_location) {
|
||||
if let Self::Locations(array) = self {
|
||||
array.push(location)
|
||||
@@ -40,6 +44,14 @@ impl dc_array_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_uint(&self, index: usize) -> uintptr_t {
|
||||
if let Self::Uint(array) = self {
|
||||
array[index]
|
||||
} else {
|
||||
panic!("Attempt to get uint from array of other type");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_id(&self, index: usize) -> uint32_t {
|
||||
match self {
|
||||
Self::Locations(array) => array[index].location_id,
|
||||
@@ -47,6 +59,14 @@ impl dc_array_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ptr(&self, index: size_t) -> *mut libc::c_void {
|
||||
if let Self::Uint(array) = self {
|
||||
array[index] as *mut libc::c_void
|
||||
} else {
|
||||
panic!("Not an array of pointers");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_location(&self, index: usize) -> &dc_location {
|
||||
if let Self::Locations(array) = self {
|
||||
&array[index]
|
||||
@@ -105,7 +125,7 @@ impl dc_array_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn search_id(&self, needle: u32) -> Option<usize> {
|
||||
pub fn search_id(&self, needle: uintptr_t) -> Option<usize> {
|
||||
if let Self::Uint(array) = self {
|
||||
for (i, &u) in array.iter().enumerate() {
|
||||
if u == needle {
|
||||
@@ -127,12 +147,6 @@ impl dc_array_t {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u32>> for dc_array_t {
|
||||
fn from(array: Vec<u32>) -> Self {
|
||||
dc_array_t::Uint(array)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<dc_location>> for dc_array_t {
|
||||
fn from(array: Vec<dc_location>) -> Self {
|
||||
dc_array_t::Locations(array)
|
||||
@@ -140,62 +154,120 @@ impl From<Vec<dc_location>> for dc_array_t {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_unref(array: *mut dc_array_t) {
|
||||
assert!(!array.is_null());
|
||||
if array.is_null() {
|
||||
return;
|
||||
}
|
||||
Box::from_raw(array);
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_add_uint(array: *mut dc_array_t, item: uintptr_t) {
|
||||
if !array.is_null() {
|
||||
(*array).add_uint(item);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_add_id(array: *mut dc_array_t, item: uint32_t) {
|
||||
assert!(!array.is_null());
|
||||
(*array).add_id(item);
|
||||
if !array.is_null() {
|
||||
(*array).add_id(item);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_add_ptr(array: *mut dc_array_t, item: *mut libc::c_void) {
|
||||
dc_array_add_uint(array, item as uintptr_t);
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_cnt(array: *const dc_array_t) -> size_t {
|
||||
assert!(!array.is_null());
|
||||
(*array).len()
|
||||
if array.is_null() {
|
||||
0
|
||||
} else {
|
||||
(*array).len()
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_uint(array: *const dc_array_t, index: size_t) -> uintptr_t {
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0
|
||||
} else {
|
||||
(*array).get_uint(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_id(array: *const dc_array_t, index: size_t) -> uint32_t {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_id(index)
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0
|
||||
} else {
|
||||
(*array).get_id(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_ptr(array: *const dc_array_t, index: size_t) -> *mut libc::c_void {
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
std::ptr::null_mut()
|
||||
} else {
|
||||
(*array).get_ptr(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_latitude(array: *const dc_array_t, index: size_t) -> libc::c_double {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_latitude(index)
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0.0
|
||||
} else {
|
||||
(*array).get_latitude(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_longitude(array: *const dc_array_t, index: size_t) -> libc::c_double {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_longitude(index)
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0.0
|
||||
} else {
|
||||
(*array).get_longitude(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_accuracy(array: *const dc_array_t, index: size_t) -> libc::c_double {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_accuracy(index)
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0.0
|
||||
} else {
|
||||
(*array).get_accuracy(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_timestamp(array: *const dc_array_t, index: size_t) -> i64 {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_timestamp(index)
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0
|
||||
} else {
|
||||
(*array).get_timestamp(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_chat_id(array: *const dc_array_t, index: size_t) -> uint32_t {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_chat_id(index)
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0
|
||||
} else {
|
||||
(*array).get_chat_id(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_contact_id(array: *const dc_array_t, index: size_t) -> uint32_t {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_contact_id(index)
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0
|
||||
} else {
|
||||
(*array).get_contact_id(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_msg_id(array: *const dc_array_t, index: size_t) -> uint32_t {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_msg_id(index)
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
0
|
||||
} else {
|
||||
(*array).get_msg_id(index)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_marker(array: *const dc_array_t, index: size_t) -> *mut libc::c_char {
|
||||
assert!(!array.is_null());
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
if let dc_array_t::Locations(v) = &*array {
|
||||
if let Some(s) = &v[index].marker {
|
||||
@@ -204,7 +276,7 @@ pub unsafe fn dc_array_get_marker(array: *const dc_array_t, index: size_t) -> *m
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
} else {
|
||||
panic!("Not an array of locations");
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +291,9 @@ pub unsafe fn dc_array_get_marker(array: *const dc_array_t, index: size_t) -> *m
|
||||
* 1=Location was reported independently.
|
||||
*/
|
||||
pub unsafe fn dc_array_is_independent(array: *const dc_array_t, index: size_t) -> libc::c_int {
|
||||
assert!(!array.is_null());
|
||||
if array.is_null() || index >= (*array).len() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if let dc_array_t::Locations(v) = &*array {
|
||||
v[index].independent as libc::c_int
|
||||
@@ -233,9 +307,10 @@ pub unsafe fn dc_array_search_id(
|
||||
needle: uint32_t,
|
||||
ret_index: *mut size_t,
|
||||
) -> bool {
|
||||
assert!(!array.is_null());
|
||||
|
||||
if let Some(i) = (*array).search_id(needle) {
|
||||
if array.is_null() {
|
||||
return false;
|
||||
}
|
||||
if let Some(i) = (*array).search_id(needle as uintptr_t) {
|
||||
if !ret_index.is_null() {
|
||||
*ret_index = i
|
||||
}
|
||||
@@ -245,9 +320,10 @@ pub unsafe fn dc_array_search_id(
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_raw(array: *const dc_array_t) -> *const u32 {
|
||||
assert!(!array.is_null());
|
||||
|
||||
pub unsafe fn dc_array_get_raw(array: *const dc_array_t) -> *const uintptr_t {
|
||||
if array.is_null() {
|
||||
return 0 as *const uintptr_t;
|
||||
}
|
||||
if let dc_array_t::Uint(v) = &*array {
|
||||
v.as_ptr()
|
||||
} else {
|
||||
@@ -264,24 +340,27 @@ pub fn dc_array_new_locations(initsize: size_t) -> *mut dc_array_t {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_empty(array: *mut dc_array_t) {
|
||||
assert!(!array.is_null());
|
||||
|
||||
if array.is_null() {
|
||||
return;
|
||||
}
|
||||
(*array).clear()
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_duplicate(array: *const dc_array_t) -> *mut dc_array_t {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).clone().into_raw()
|
||||
if array.is_null() {
|
||||
std::ptr::null_mut()
|
||||
} else {
|
||||
(*array).clone().into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_string(
|
||||
array: *const dc_array_t,
|
||||
sep: *const libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
assert!(!array.is_null());
|
||||
assert!(!sep.is_null());
|
||||
|
||||
if array.is_null() || sep.is_null() {
|
||||
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
|
||||
}
|
||||
if let dc_array_t::Uint(v) = &*array {
|
||||
let cnt = v.len();
|
||||
let sep = as_str(sep);
|
||||
@@ -327,6 +406,10 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(dc_array_get_id(arr, -1i32 as size_t), 0);
|
||||
assert_eq!(dc_array_get_id(arr, 1000 as size_t), 0);
|
||||
assert_eq!(dc_array_get_id(arr, 1001 as size_t), 0);
|
||||
|
||||
dc_array_empty(arr);
|
||||
|
||||
assert_eq!(dc_array_get_cnt(arr), 0);
|
||||
@@ -355,13 +438,4 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_dc_array_out_of_bounds() {
|
||||
let arr = dc_array_new(7);
|
||||
for i in 0..1000 {
|
||||
unsafe { dc_array_add_id(arr, (i + 2) as uint32_t) };
|
||||
}
|
||||
unsafe { dc_array_get_id(arr, 1000) };
|
||||
}
|
||||
}
|
||||
|
||||
276
src/dc_chat.rs
276
src/dc_chat.rs
@@ -13,7 +13,6 @@ use crate::sql::{self, Sql};
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
use std::ptr;
|
||||
|
||||
/**
|
||||
* @class dc_chat_t
|
||||
@@ -25,6 +24,7 @@ use std::ptr;
|
||||
*/
|
||||
#[derive(Clone)]
|
||||
pub struct Chat<'a> {
|
||||
magic: uint32_t,
|
||||
pub id: uint32_t,
|
||||
pub type_0: libc::c_int,
|
||||
pub name: *mut libc::c_char,
|
||||
@@ -65,6 +65,7 @@ pub unsafe fn dc_create_chat_by_msg_id(context: &Context, msg_id: uint32_t) -> u
|
||||
|
||||
pub unsafe fn dc_chat_new<'a>(context: &'a Context) -> *mut Chat<'a> {
|
||||
let chat = Chat {
|
||||
magic: 0xc4a7c4a7,
|
||||
id: 0,
|
||||
type_0: 0,
|
||||
name: std::ptr::null_mut(),
|
||||
@@ -80,24 +81,25 @@ pub unsafe fn dc_chat_new<'a>(context: &'a Context) -> *mut Chat<'a> {
|
||||
Box::into_raw(Box::new(chat))
|
||||
}
|
||||
|
||||
pub unsafe fn dc_chat_unref(chat: *mut Chat) {
|
||||
if chat.is_null() {
|
||||
pub unsafe fn dc_chat_unref(mut chat: *mut Chat) {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return;
|
||||
}
|
||||
dc_chat_empty(chat);
|
||||
(*chat).magic = 0;
|
||||
Box::from_raw(chat);
|
||||
}
|
||||
|
||||
pub unsafe fn dc_chat_empty(mut chat: *mut Chat) {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return;
|
||||
}
|
||||
free((*chat).name as *mut libc::c_void);
|
||||
(*chat).name = ptr::null_mut();
|
||||
(*chat).name = 0 as *mut libc::c_char;
|
||||
(*chat).type_0 = 0i32;
|
||||
(*chat).id = 0i32 as uint32_t;
|
||||
free((*chat).grpid as *mut libc::c_void);
|
||||
(*chat).grpid = ptr::null_mut();
|
||||
(*chat).grpid = 0 as *mut libc::c_char;
|
||||
(*chat).blocked = 0i32;
|
||||
(*chat).gossiped_timestamp = 0;
|
||||
(*chat).param = Params::new();
|
||||
@@ -118,7 +120,7 @@ pub fn dc_block_chat(context: &Context, chat_id: u32, new_blocking: libc::c_int)
|
||||
}
|
||||
|
||||
pub fn dc_chat_load_from_db(chat: *mut Chat, chat_id: u32) -> bool {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || unsafe { (*chat).magic != 0xc4a7c4a7u32 } {
|
||||
return false;
|
||||
}
|
||||
unsafe { dc_chat_empty(chat) };
|
||||
@@ -180,22 +182,6 @@ pub fn dc_chat_load_from_db(chat: *mut Chat, chat_id: u32) -> bool {
|
||||
.strdup();
|
||||
},
|
||||
_ => {
|
||||
unsafe {
|
||||
if (*chat).type_0 == DC_CHAT_TYPE_SINGLE {
|
||||
free((*chat).name as *mut libc::c_void);
|
||||
let contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
|
||||
let mut chat_name = "Err [Name not found]".to_owned();
|
||||
if !(*contacts).is_empty() {
|
||||
if let Ok(contact) =
|
||||
Contact::get_by_id((*chat).context, contacts[0])
|
||||
{
|
||||
chat_name = contact.get_display_name().to_owned();
|
||||
}
|
||||
}
|
||||
(*chat).name = (&chat_name).strdup();
|
||||
}
|
||||
}
|
||||
|
||||
if unsafe { &(*chat).param }.exists(Param::Selftalk) {
|
||||
unsafe {
|
||||
free((*chat).name as *mut libc::c_void);
|
||||
@@ -233,7 +219,7 @@ pub unsafe fn dc_create_chat_by_contact_id(context: &Context, contact_id: uint32
|
||||
contact_id,
|
||||
0i32,
|
||||
&mut chat_id,
|
||||
ptr::null_mut(),
|
||||
0 as *mut libc::c_int,
|
||||
);
|
||||
if 0 != chat_id {
|
||||
send_event = 1;
|
||||
@@ -350,11 +336,11 @@ pub unsafe fn dc_get_chat_id_by_contact_id(context: &Context, contact_id: uint32
|
||||
let mut chat_id: uint32_t = 0i32 as uint32_t;
|
||||
let mut chat_id_blocked: libc::c_int = 0i32;
|
||||
dc_lookup_real_nchat_by_contact_id(context, contact_id, &mut chat_id, &mut chat_id_blocked);
|
||||
if 0 != chat_id_blocked {
|
||||
return if 0 != chat_id_blocked {
|
||||
0i32 as libc::c_uint
|
||||
} else {
|
||||
chat_id
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub unsafe fn dc_prepare_msg<'a>(
|
||||
@@ -372,7 +358,7 @@ pub unsafe fn dc_prepare_msg<'a>(
|
||||
(*msg).chat_id as uintptr_t,
|
||||
(*msg).id as uintptr_t,
|
||||
);
|
||||
msg_id
|
||||
return msg_id;
|
||||
}
|
||||
|
||||
pub fn msgtype_has_file(msgtype: Viewtype) -> bool {
|
||||
@@ -438,7 +424,11 @@ unsafe fn prepare_msg_common<'a>(
|
||||
} else if !(*msg).param.exists(Param::MimeType) {
|
||||
let mut better_mime = std::ptr::null_mut();
|
||||
|
||||
dc_msg_guess_msgtype_from_suffix(pathNfilename, ptr::null_mut(), &mut better_mime);
|
||||
dc_msg_guess_msgtype_from_suffix(
|
||||
pathNfilename,
|
||||
0 as *mut Viewtype,
|
||||
&mut better_mime,
|
||||
);
|
||||
|
||||
if !better_mime.is_null() {
|
||||
(*msg).param.set(Param::MimeType, as_str(better_mime));
|
||||
@@ -490,12 +480,12 @@ unsafe fn prepare_msg_raw(
|
||||
let mut do_guarantee_e2ee: libc::c_int;
|
||||
let e2ee_enabled: libc::c_int;
|
||||
let mut OK_TO_CONTINUE = true;
|
||||
let mut parent_rfc724_mid = ptr::null_mut();
|
||||
let mut parent_references = ptr::null_mut();
|
||||
let mut parent_in_reply_to = ptr::null_mut();
|
||||
let mut new_rfc724_mid = ptr::null_mut();
|
||||
let mut new_references = ptr::null_mut();
|
||||
let mut new_in_reply_to = ptr::null_mut();
|
||||
let mut parent_rfc724_mid = 0 as *mut libc::c_char;
|
||||
let mut parent_references = 0 as *mut libc::c_char;
|
||||
let mut parent_in_reply_to = 0 as *mut libc::c_char;
|
||||
let mut new_rfc724_mid = 0 as *mut libc::c_char;
|
||||
let mut new_references = 0 as *mut libc::c_char;
|
||||
let mut new_in_reply_to = 0 as *mut libc::c_char;
|
||||
let mut msg_id = 0;
|
||||
let mut to_id = 0;
|
||||
let mut location_id = 0;
|
||||
@@ -521,7 +511,7 @@ unsafe fn prepare_msg_raw(
|
||||
if (*chat).type_0 == 120 || (*chat).type_0 == 130 {
|
||||
(*chat).grpid
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut libc::c_char
|
||||
},
|
||||
from_c.as_ptr(),
|
||||
);
|
||||
@@ -820,7 +810,7 @@ unsafe fn get_parent_mime_headers(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_chat_is_self_talk(chat: *const Chat) -> libc::c_int {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return 0;
|
||||
}
|
||||
(*chat).param.exists(Param::Selftalk) as libc::c_int
|
||||
@@ -1065,12 +1055,12 @@ pub unsafe fn dc_get_draft(context: &Context, chat_id: uint32_t) -> *mut dc_msg_
|
||||
}
|
||||
draft_msg_id = get_draft_msg_id(context, chat_id);
|
||||
if draft_msg_id == 0i32 as libc::c_uint {
|
||||
return ptr::null_mut();
|
||||
return 0 as *mut dc_msg_t;
|
||||
}
|
||||
draft_msg = dc_msg_new_untyped(context);
|
||||
if !dc_msg_load_from_db(draft_msg, context, draft_msg_id) {
|
||||
dc_msg_unref(draft_msg);
|
||||
return ptr::null_mut();
|
||||
return 0 as *mut dc_msg_t;
|
||||
}
|
||||
|
||||
draft_msg
|
||||
@@ -1082,7 +1072,7 @@ pub fn dc_get_chat_msgs(
|
||||
flags: uint32_t,
|
||||
marker1before: uint32_t,
|
||||
) -> *mut dc_array_t {
|
||||
let mut ret = Vec::new();
|
||||
let mut ret = dc_array_t::new(512);
|
||||
|
||||
let mut last_day = 0;
|
||||
let cnv_to_local = dc_gm2local_offset();
|
||||
@@ -1092,17 +1082,17 @@ pub fn dc_get_chat_msgs(
|
||||
for row in rows {
|
||||
let (curr_id, ts) = row?;
|
||||
if curr_id as u32 == marker1before {
|
||||
ret.push(DC_MSG_ID_MARKER1 as u32);
|
||||
ret.add_id(1);
|
||||
}
|
||||
if 0 != flags & 0x1 {
|
||||
let curr_local_timestamp = ts + cnv_to_local;
|
||||
let curr_day = (curr_local_timestamp / 86400) as libc::c_int;
|
||||
if curr_day != last_day {
|
||||
ret.push(DC_MSG_ID_LAST_SPECIAL as u32);
|
||||
ret.add_id(9);
|
||||
last_day = curr_day;
|
||||
}
|
||||
}
|
||||
ret.push(curr_id as u32);
|
||||
ret.add_id(curr_id as u32);
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
@@ -1150,7 +1140,7 @@ pub fn dc_get_chat_msgs(
|
||||
};
|
||||
|
||||
if success.is_ok() {
|
||||
dc_array_t::from(ret).into_raw()
|
||||
ret.into_raw()
|
||||
} else {
|
||||
0 as *mut dc_array_t
|
||||
}
|
||||
@@ -1263,11 +1253,11 @@ pub fn dc_get_chat_media(
|
||||
],
|
||||
|row| row.get::<_, i32>(0),
|
||||
|ids| {
|
||||
let mut ret = Vec::new();
|
||||
let mut ret = dc_array_t::new(100);
|
||||
for id in ids {
|
||||
ret.push(id? as u32);
|
||||
ret.add_id(id? as u32);
|
||||
}
|
||||
Ok(dc_array_t::from(ret).into_raw())
|
||||
Ok(ret.into_raw())
|
||||
}
|
||||
).unwrap_or_else(|_| std::ptr::null_mut())
|
||||
}
|
||||
@@ -1282,7 +1272,7 @@ pub unsafe fn dc_get_next_media(
|
||||
) -> uint32_t {
|
||||
let mut ret_msg_id: uint32_t = 0i32 as uint32_t;
|
||||
let msg: *mut dc_msg_t = dc_msg_new_untyped(context);
|
||||
let mut list: *mut dc_array_t = ptr::null_mut();
|
||||
let mut list: *mut dc_array_t = 0 as *mut dc_array_t;
|
||||
let mut i: libc::c_int;
|
||||
let cnt: libc::c_int;
|
||||
|
||||
@@ -1320,9 +1310,7 @@ pub unsafe fn dc_get_next_media(
|
||||
}
|
||||
}
|
||||
|
||||
if !list.is_null() {
|
||||
dc_array_unref(list);
|
||||
}
|
||||
dc_array_unref(list);
|
||||
dc_msg_unref(msg);
|
||||
ret_msg_id
|
||||
}
|
||||
@@ -1418,12 +1406,12 @@ pub fn dc_delete_chat(context: &Context, chat_id: u32) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn dc_get_chat_contacts(context: &Context, chat_id: u32) -> Vec<u32> {
|
||||
pub fn dc_get_chat_contacts(context: &Context, chat_id: u32) -> *mut dc_array_t {
|
||||
/* Normal chats do not include SELF. Group chats do (as it may happen that one is deleted from a
|
||||
groupchat but the chats stays visible, moreover, this makes displaying lists easier) */
|
||||
|
||||
if chat_id == 1 {
|
||||
return Vec::new();
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
// we could also create a list for all contacts in the deaddrop by searching contacts belonging to chats with
|
||||
@@ -1435,11 +1423,19 @@ pub fn dc_get_chat_contacts(context: &Context, chat_id: u32) -> Vec<u32> {
|
||||
"SELECT cc.contact_id FROM chats_contacts cc \
|
||||
LEFT JOIN contacts c ON c.id=cc.contact_id WHERE cc.chat_id=? \
|
||||
ORDER BY c.id=1, LOWER(c.name||c.addr), c.id;",
|
||||
params![chat_id],
|
||||
|row| row.get::<_, u32>(0),
|
||||
|ids| ids.collect::<Result<Vec<_>, _>>().map_err(Into::into),
|
||||
params![chat_id as i32],
|
||||
|row| row.get::<_, i32>(0),
|
||||
|ids| {
|
||||
let mut ret = dc_array_t::new(100);
|
||||
|
||||
for id in ids {
|
||||
ret.add_id(id? as u32);
|
||||
}
|
||||
|
||||
Ok(ret.into_raw())
|
||||
},
|
||||
)
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_else(|_| std::ptr::null_mut())
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_chat(context: &Context, chat_id: uint32_t) -> *mut Chat {
|
||||
@@ -1451,11 +1447,11 @@ pub unsafe fn dc_get_chat(context: &Context, chat_id: uint32_t) -> *mut Chat {
|
||||
}
|
||||
|
||||
if 0 != success {
|
||||
obj
|
||||
return obj;
|
||||
} else {
|
||||
dc_chat_unref(obj);
|
||||
ptr::null_mut()
|
||||
}
|
||||
return 0 as *mut Chat;
|
||||
};
|
||||
}
|
||||
|
||||
// handle group chats
|
||||
@@ -1548,7 +1544,7 @@ pub unsafe fn dc_add_contact_to_chat_ex(
|
||||
let contact = contact.unwrap();
|
||||
|
||||
/*this also makes sure, not contacts are added to special or normal chats*/
|
||||
if !(!real_group_exists(context, chat_id)
|
||||
if !(0 == real_group_exists(context, chat_id)
|
||||
|| !Contact::real_exists_by_id(context, contact_id)
|
||||
&& contact_id != DC_CONTACT_ID_SELF as u32
|
||||
|| !dc_chat_load_from_db(chat, chat_id))
|
||||
@@ -1630,10 +1626,11 @@ pub unsafe fn dc_add_contact_to_chat_ex(
|
||||
success
|
||||
}
|
||||
|
||||
fn real_group_exists(context: &Context, chat_id: u32) -> bool {
|
||||
// TODO should return bool /rtn
|
||||
fn real_group_exists(context: &Context, chat_id: u32) -> libc::c_int {
|
||||
// check if a group or a verified group exists under the given ID
|
||||
if !context.sql.is_open() || chat_id <= 9 {
|
||||
return false;
|
||||
return 02;
|
||||
}
|
||||
|
||||
context
|
||||
@@ -1642,7 +1639,7 @@ fn real_group_exists(context: &Context, chat_id: u32) -> bool {
|
||||
"SELECT id FROM chats WHERE id=? AND (type=120 OR type=130);",
|
||||
params![chat_id as i32],
|
||||
)
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_default() as libc::c_int
|
||||
}
|
||||
|
||||
pub fn dc_reset_gossiped_timestamp(context: &Context, chat_id: u32) {
|
||||
@@ -1694,7 +1691,7 @@ pub unsafe fn dc_remove_contact_from_chat(
|
||||
{
|
||||
/* we do not check if "contact_id" exists but just delete all records with the id from chats_contacts */
|
||||
/* this allows to delete pending references to deleted contacts. Of course, this should _not_ happen. */
|
||||
if !(!real_group_exists(context, chat_id) || !dc_chat_load_from_db(chat, chat_id)) {
|
||||
if !(0 == real_group_exists(context, chat_id) || !dc_chat_load_from_db(chat, chat_id)) {
|
||||
if !(dc_is_contact_in_chat(context, chat_id, 1 as uint32_t) == 1) {
|
||||
log_event!(
|
||||
context,
|
||||
@@ -1793,7 +1790,7 @@ pub unsafe fn dc_set_chat_name(
|
||||
|| *new_name.offset(0isize) as libc::c_int == 0i32
|
||||
|| chat_id <= 9i32 as libc::c_uint)
|
||||
{
|
||||
if !(!real_group_exists(context, chat_id) || !dc_chat_load_from_db(chat, chat_id)) {
|
||||
if !(0i32 == real_group_exists(context, chat_id) || !dc_chat_load_from_db(chat, chat_id)) {
|
||||
if strcmp((*chat).name, new_name) == 0i32 {
|
||||
success = 1i32
|
||||
} else if !(dc_is_contact_in_chat(context, chat_id, 1i32 as uint32_t) == 1i32) {
|
||||
@@ -1853,62 +1850,76 @@ pub unsafe fn dc_set_chat_name(
|
||||
success
|
||||
}
|
||||
|
||||
// TODO should return bool /rtn
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn dc_set_chat_profile_image(
|
||||
context: &Context,
|
||||
chat_id: uint32_t,
|
||||
new_image: impl AsRef<str>,
|
||||
) -> bool {
|
||||
if chat_id <= 9 {
|
||||
return false;
|
||||
}
|
||||
new_image: *const libc::c_char,
|
||||
) -> libc::c_int {
|
||||
let mut OK_TO_CONTINUE = true;
|
||||
let mut success: libc::c_int = 0i32;
|
||||
let chat: *mut Chat = dc_chat_new(context);
|
||||
let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context);
|
||||
let mut success = false;
|
||||
|
||||
if real_group_exists(context, chat_id) && dc_chat_load_from_db(chat, chat_id) {
|
||||
if !(dc_is_contact_in_chat(context, chat_id, 1i32 as uint32_t) == 1i32) {
|
||||
log_event!(
|
||||
context,
|
||||
Event::ERROR_SELF_NOT_IN_GROUP,
|
||||
0,
|
||||
"Cannot set chat profile image; self not in group.",
|
||||
);
|
||||
} else {
|
||||
(*chat).param.set(Param::ProfileImage, new_image.as_ref());
|
||||
if !(0 == dc_chat_update_param(chat)) {
|
||||
if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||
(*msg).param.set_int(Param::Cmd, 3);
|
||||
(*msg).param.set(Param::Arg, new_image.as_ref());
|
||||
(*msg).type_0 = Viewtype::Text;
|
||||
(*msg).text = Some(context.stock_system_msg(
|
||||
if new_image.as_ref().is_empty() {
|
||||
StockMessage::MsgGrpImgDeleted
|
||||
} else {
|
||||
StockMessage::MsgGrpImgChanged
|
||||
},
|
||||
"",
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as uint32_t,
|
||||
));
|
||||
(*msg).id = dc_send_msg(context, chat_id, msg);
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
chat_id as uintptr_t,
|
||||
(*msg).id as uintptr_t,
|
||||
);
|
||||
}
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
chat_id as uintptr_t,
|
||||
0i32 as uintptr_t,
|
||||
let mut new_image_rel: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
if !(chat_id <= 9i32 as libc::c_uint) {
|
||||
if !(0i32 == real_group_exists(context, chat_id) || !dc_chat_load_from_db(chat, chat_id)) {
|
||||
if !(dc_is_contact_in_chat(context, chat_id, 1i32 as uint32_t) == 1i32) {
|
||||
log_event!(
|
||||
context,
|
||||
Event::ERROR_SELF_NOT_IN_GROUP,
|
||||
0,
|
||||
"Cannot set chat profile image; self not in group.",
|
||||
);
|
||||
success = true;
|
||||
} else {
|
||||
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
|
||||
if !new_image.is_null() {
|
||||
new_image_rel = dc_strdup(new_image);
|
||||
if !dc_make_rel_and_copy(context, &mut new_image_rel) {
|
||||
OK_TO_CONTINUE = false;
|
||||
}
|
||||
}
|
||||
if OK_TO_CONTINUE {
|
||||
(*chat)
|
||||
.param
|
||||
.set(Param::ProfileImage, as_str(new_image_rel));
|
||||
if !(0 == dc_chat_update_param(chat)) {
|
||||
if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||
(*msg).param.set_int(Param::Cmd, 3);
|
||||
(*msg).param.set(Param::Arg, as_str(new_image_rel));
|
||||
(*msg).type_0 = Viewtype::Text;
|
||||
(*msg).text = Some(context.stock_system_msg(
|
||||
if !new_image_rel.is_null() {
|
||||
StockMessage::MsgGrpImgChanged
|
||||
} else {
|
||||
StockMessage::MsgGrpImgDeleted
|
||||
},
|
||||
"",
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as uint32_t,
|
||||
));
|
||||
(*msg).id = dc_send_msg(context, chat_id, msg);
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
chat_id as uintptr_t,
|
||||
(*msg).id as uintptr_t,
|
||||
);
|
||||
}
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
chat_id as uintptr_t,
|
||||
0i32 as uintptr_t,
|
||||
);
|
||||
success = 1i32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dc_chat_unref(chat);
|
||||
dc_msg_unref(msg);
|
||||
free(new_image_rel as *mut libc::c_void);
|
||||
|
||||
success
|
||||
}
|
||||
@@ -2009,21 +2020,21 @@ pub unsafe fn dc_forward_msgs(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_chat_get_id(chat: *const Chat) -> uint32_t {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return 0i32 as uint32_t;
|
||||
}
|
||||
(*chat).id
|
||||
}
|
||||
|
||||
pub unsafe fn dc_chat_get_type(chat: *const Chat) -> libc::c_int {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return 0i32;
|
||||
}
|
||||
(*chat).type_0
|
||||
}
|
||||
|
||||
pub unsafe fn dc_chat_get_name(chat: *const Chat) -> *mut libc::c_char {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char);
|
||||
}
|
||||
dc_strdup((*chat).name)
|
||||
@@ -2031,7 +2042,7 @@ pub unsafe fn dc_chat_get_name(chat: *const Chat) -> *mut libc::c_char {
|
||||
|
||||
pub unsafe fn dc_chat_get_subtitle(chat: *const Chat) -> *mut libc::c_char {
|
||||
/* returns either the address or the number of chat members */
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char);
|
||||
}
|
||||
|
||||
@@ -2066,11 +2077,11 @@ pub unsafe fn dc_chat_get_subtitle(chat: *const Chat) -> *mut libc::c_char {
|
||||
.strdup();
|
||||
}
|
||||
}
|
||||
if !ret.is_null() {
|
||||
return if !ret.is_null() {
|
||||
ret
|
||||
} else {
|
||||
dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn dc_get_chat_contact_cnt(context: &Context, chat_id: u32) -> libc::c_int {
|
||||
@@ -2088,8 +2099,9 @@ pub fn dc_get_chat_contact_cnt(context: &Context, chat_id: u32) -> libc::c_int {
|
||||
pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char {
|
||||
let mut image_rel: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut image_abs: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t;
|
||||
|
||||
if !chat.is_null() {
|
||||
if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) {
|
||||
image_rel = (*chat)
|
||||
.param
|
||||
.get(Param::ProfileImage)
|
||||
@@ -2097,10 +2109,10 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
|
||||
.strdup();
|
||||
if !image_rel.is_null() && 0 != *image_rel.offset(0isize) as libc::c_int {
|
||||
image_abs = dc_get_abs_path((*chat).context, image_rel)
|
||||
} else if (*chat).type_0 == DC_CHAT_TYPE_SINGLE {
|
||||
let contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
|
||||
if !contacts.is_empty() {
|
||||
if let Ok(contact) = Contact::get_by_id((*chat).context, contacts[0]) {
|
||||
} else if (*chat).type_0 == 100i32 {
|
||||
contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
|
||||
if !(*contacts).is_empty() {
|
||||
if let Ok(contact) = Contact::get_by_id((*chat).context, (*contacts).get_id(0)) {
|
||||
if let Some(img) = contact.get_profile_image() {
|
||||
image_abs = img.strdup();
|
||||
}
|
||||
@@ -2110,18 +2122,20 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
|
||||
}
|
||||
|
||||
free(image_rel as *mut libc::c_void);
|
||||
dc_array_unref(contacts);
|
||||
|
||||
image_abs
|
||||
}
|
||||
|
||||
pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t {
|
||||
let mut color: uint32_t = 0i32 as uint32_t;
|
||||
let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t;
|
||||
|
||||
if !chat.is_null() {
|
||||
if (*chat).type_0 == DC_CHAT_TYPE_SINGLE {
|
||||
let contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
|
||||
if !contacts.is_empty() {
|
||||
if let Ok(contact) = Contact::get_by_id((*chat).context, contacts[0]) {
|
||||
if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) {
|
||||
if (*chat).type_0 == 100i32 {
|
||||
contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
|
||||
if !(*contacts).is_empty() {
|
||||
if let Ok(contact) = Contact::get_by_id((*chat).context, (*contacts).get_id(0)) {
|
||||
color = contact.get_color();
|
||||
}
|
||||
}
|
||||
@@ -2130,12 +2144,14 @@ pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t {
|
||||
}
|
||||
}
|
||||
|
||||
dc_array_unref(contacts);
|
||||
|
||||
color
|
||||
}
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_chat_get_archived(chat: *const Chat) -> libc::c_int {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return 0i32;
|
||||
}
|
||||
(*chat).archived
|
||||
@@ -2143,7 +2159,7 @@ pub unsafe fn dc_chat_get_archived(chat: *const Chat) -> libc::c_int {
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_chat_is_unpromoted(chat: *const Chat) -> libc::c_int {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return 0;
|
||||
}
|
||||
(*chat).param.get_int(Param::Unpromoted).unwrap_or_default() as libc::c_int
|
||||
@@ -2151,7 +2167,7 @@ pub unsafe fn dc_chat_is_unpromoted(chat: *const Chat) -> libc::c_int {
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_chat_is_verified(chat: *const Chat) -> libc::c_int {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return 0i32;
|
||||
}
|
||||
((*chat).type_0 == 130i32) as libc::c_int
|
||||
@@ -2159,7 +2175,7 @@ pub unsafe fn dc_chat_is_verified(chat: *const Chat) -> libc::c_int {
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_chat_is_sending_locations(chat: *const Chat) -> libc::c_int {
|
||||
if chat.is_null() {
|
||||
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
|
||||
return 0i32;
|
||||
}
|
||||
(*chat).is_sending_locations
|
||||
@@ -2221,7 +2237,7 @@ pub fn dc_add_device_msg(context: &Context, chat_id: uint32_t, text: *const libc
|
||||
}
|
||||
let rfc724_mid = unsafe {
|
||||
dc_create_outgoing_rfc724_mid(
|
||||
ptr::null(),
|
||||
0 as *const libc::c_char,
|
||||
b"@device\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
};
|
||||
|
||||
1288
src/dc_configure.rs
1288
src/dc_configure.rs
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@ use lazy_static::lazy_static;
|
||||
use crate::dc_saxparser::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::x::*;
|
||||
use std::ptr;
|
||||
|
||||
lazy_static! {
|
||||
static ref LINE_RE: regex::Regex = regex::Regex::new(r"(\r?\n)+").unwrap();
|
||||
@@ -39,7 +38,7 @@ pub unsafe fn dc_dehtml(buf_terminated: *mut libc::c_char) -> *mut libc::c_char
|
||||
starttag_cb: None,
|
||||
endtag_cb: None,
|
||||
text_cb: None,
|
||||
userdata: ptr::null_mut(),
|
||||
userdata: 0 as *mut libc::c_void,
|
||||
};
|
||||
dc_saxparser_init(
|
||||
&mut saxparser,
|
||||
|
||||
346
src/dc_e2ee.rs
346
src/dc_e2ee.rs
@@ -1,8 +1,5 @@
|
||||
//! End-to-end encryption support.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::CStr;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use mmime::clist::*;
|
||||
@@ -19,12 +16,10 @@ use mmime::mmapstring::*;
|
||||
use mmime::{mailmime_substitute, MAILIMF_NO_ERROR, MAIL_NO_ERROR};
|
||||
|
||||
use crate::aheader::*;
|
||||
use crate::config::Config;
|
||||
use crate::context::Context;
|
||||
use crate::dc_mimeparser::*;
|
||||
use crate::dc_securejoin::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::*;
|
||||
use crate::key::*;
|
||||
use crate::keyring::*;
|
||||
use crate::peerstate::*;
|
||||
@@ -101,11 +96,9 @@ pub unsafe fn dc_e2ee_encrypt(
|
||||
let addr = context.sql.get_config(context, "configured_addr");
|
||||
|
||||
if let Some(addr) = addr {
|
||||
let pubkey_ret = load_or_generate_self_public_key(context, &addr).map_err(|err| {
|
||||
error!(context, 0, "Failed to load public key: {}", err);
|
||||
err
|
||||
});
|
||||
if let Ok(public_key) = pubkey_ret {
|
||||
if let Some(public_key) =
|
||||
load_or_generate_self_public_key(context, &addr, in_out_message)
|
||||
{
|
||||
/*only for random-seed*/
|
||||
if prefer_encrypt == EncryptPreference::Mutual || 0 != e2ee_guaranteed {
|
||||
do_encrypt = 1i32;
|
||||
@@ -122,22 +115,11 @@ pub unsafe fn dc_e2ee_encrypt(
|
||||
|| 0 != e2ee_guaranteed)
|
||||
{
|
||||
let peerstate = peerstate.unwrap();
|
||||
info!(
|
||||
context,
|
||||
0, "dc_e2ee_encrypt {} has peerstate", recipient_addr
|
||||
);
|
||||
if let Some(key) = peerstate.peek_key(min_verified as usize) {
|
||||
keyring.add_owned(key.clone());
|
||||
peerstates.push(peerstate);
|
||||
}
|
||||
} else {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"dc_e2ee_encrypt {} HAS NO peerstate {}",
|
||||
recipient_addr,
|
||||
peerstate.is_some()
|
||||
);
|
||||
do_encrypt = 0i32;
|
||||
/* if we cannot encrypt to a single recipient, we cannot encrypt the message at all */
|
||||
break;
|
||||
@@ -146,7 +128,7 @@ pub unsafe fn dc_e2ee_encrypt(
|
||||
iter1 = if !iter1.is_null() {
|
||||
(*iter1).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,19 +153,19 @@ pub unsafe fn dc_e2ee_encrypt(
|
||||
mailprivacy_prepare_mime(in_out_message);
|
||||
let mut part_to_encrypt: *mut mailmime =
|
||||
(*in_out_message).mm_data.mm_message.mm_msg_mime;
|
||||
(*part_to_encrypt).mm_parent = ptr::null_mut();
|
||||
(*part_to_encrypt).mm_parent = 0 as *mut mailmime;
|
||||
let imffields_encrypted: *mut mailimf_fields = mailimf_fields_new_empty();
|
||||
/* mailmime_new_message_data() calls mailmime_fields_new_with_version() which would add the unwanted MIME-Version:-header */
|
||||
let message_to_encrypt: *mut mailmime = mailmime_new(
|
||||
MAILMIME_MESSAGE as libc::c_int,
|
||||
ptr::null(),
|
||||
0 as *const libc::c_char,
|
||||
0i32 as size_t,
|
||||
mailmime_fields_new_empty(),
|
||||
mailmime_get_content_message(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
0 as *mut mailmime_data,
|
||||
0 as *mut mailmime_data,
|
||||
0 as *mut mailmime_data,
|
||||
0 as *mut clist,
|
||||
imffields_encrypted,
|
||||
part_to_encrypt,
|
||||
);
|
||||
@@ -215,7 +197,7 @@ pub unsafe fn dc_e2ee_encrypt(
|
||||
let field: *mut mailimf_field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut libc::c_void
|
||||
})
|
||||
as *mut mailimf_field;
|
||||
if !field.is_null() {
|
||||
@@ -266,28 +248,28 @@ pub unsafe fn dc_e2ee_encrypt(
|
||||
imffields_unprotected,
|
||||
mailimf_field_new(
|
||||
MAILIMF_FIELD_SUBJECT as libc::c_int,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
0 as *mut mailimf_return,
|
||||
0 as *mut mailimf_orig_date,
|
||||
0 as *mut mailimf_from,
|
||||
0 as *mut mailimf_sender,
|
||||
0 as *mut mailimf_to,
|
||||
0 as *mut mailimf_cc,
|
||||
0 as *mut mailimf_bcc,
|
||||
0 as *mut mailimf_message_id,
|
||||
0 as *mut mailimf_orig_date,
|
||||
0 as *mut mailimf_from,
|
||||
0 as *mut mailimf_sender,
|
||||
0 as *mut mailimf_reply_to,
|
||||
0 as *mut mailimf_to,
|
||||
0 as *mut mailimf_cc,
|
||||
0 as *mut mailimf_bcc,
|
||||
0 as *mut mailimf_message_id,
|
||||
0 as *mut mailimf_in_reply_to,
|
||||
0 as *mut mailimf_references,
|
||||
subject,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
0 as *mut mailimf_comments,
|
||||
0 as *mut mailimf_keywords,
|
||||
0 as *mut mailimf_optional_field,
|
||||
),
|
||||
);
|
||||
clist_insert_after(
|
||||
@@ -315,7 +297,7 @@ pub unsafe fn dc_e2ee_encrypt(
|
||||
|
||||
/* create MIME-structure that will contain the encrypted text */
|
||||
let mut encrypted_part: *mut mailmime = new_data_part(
|
||||
ptr::null_mut(),
|
||||
0 as *mut libc::c_void,
|
||||
0i32 as size_t,
|
||||
b"multipart/encrypted\x00" as *const u8 as *const libc::c_char
|
||||
as *mut libc::c_char,
|
||||
@@ -401,7 +383,7 @@ unsafe fn new_data_part(
|
||||
let encoding_type: libc::c_int;
|
||||
let content_type_str: *mut libc::c_char;
|
||||
let mut do_encoding: libc::c_int;
|
||||
encoding = ptr::null_mut();
|
||||
encoding = 0 as *mut mailmime_mechanism;
|
||||
if default_content_type.is_null() {
|
||||
content_type_str =
|
||||
b"application/octet-stream\x00" as *const u8 as *const libc::c_char as *mut libc::c_char
|
||||
@@ -436,7 +418,7 @@ unsafe fn new_data_part(
|
||||
} else {
|
||||
encoding_type = default_encoding
|
||||
}
|
||||
encoding = mailmime_mechanism_new(encoding_type, ptr::null_mut());
|
||||
encoding = mailmime_mechanism_new(encoding_type, 0 as *mut libc::c_char);
|
||||
if encoding.is_null() {
|
||||
ok_to_continue = false;
|
||||
}
|
||||
@@ -444,10 +426,10 @@ unsafe fn new_data_part(
|
||||
if ok_to_continue {
|
||||
mime_fields = mailmime_fields_new_with_data(
|
||||
encoding,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
0 as *mut libc::c_char,
|
||||
0 as *mut libc::c_char,
|
||||
0 as *mut mailmime_disposition,
|
||||
0 as *mut mailmime_language,
|
||||
);
|
||||
if mime_fields.is_null() {
|
||||
ok_to_continue = false;
|
||||
@@ -477,55 +459,68 @@ unsafe fn new_data_part(
|
||||
mailmime_content_free(content);
|
||||
}
|
||||
}
|
||||
ptr::null_mut()
|
||||
return 0 as *mut mailmime;
|
||||
}
|
||||
|
||||
/// Load public key from database or generate a new one.
|
||||
///
|
||||
/// This will load a public key from the database, generating and
|
||||
/// storing a new one when one doesn't exist yet. Care is taken to
|
||||
/// only generate one key per context even when multiple threads call
|
||||
/// this function concurrently.
|
||||
fn load_or_generate_self_public_key(context: &Context, self_addr: impl AsRef<str>) -> Result<Key> {
|
||||
if let Some(key) = Key::from_self_public(context, &self_addr, &context.sql) {
|
||||
return Ok(key);
|
||||
}
|
||||
let _guard = context.generating_key_mutex.lock().unwrap();
|
||||
/*******************************************************************************
|
||||
* Generate Keypairs
|
||||
******************************************************************************/
|
||||
unsafe fn load_or_generate_self_public_key(
|
||||
context: &Context,
|
||||
self_addr: impl AsRef<str>,
|
||||
_random_data_mime: *mut mailmime,
|
||||
) -> Option<Key> {
|
||||
/* avoid double creation (we unlock the database during creation) */
|
||||
static mut S_IN_KEY_CREATION: libc::c_int = 0;
|
||||
|
||||
// Check again in case the key was generated while we were waiting for the lock.
|
||||
if let Some(key) = Key::from_self_public(context, &self_addr, &context.sql) {
|
||||
return Ok(key);
|
||||
let mut key = Key::from_self_public(context, &self_addr, &context.sql);
|
||||
if key.is_some() {
|
||||
return key;
|
||||
}
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
/* create the keypair - this may take a moment, however, as this is in a thread, this is no big deal */
|
||||
if 0 != S_IN_KEY_CREATION {
|
||||
return None;
|
||||
}
|
||||
let key_creation_here = 1;
|
||||
S_IN_KEY_CREATION = 1;
|
||||
|
||||
let start = clock();
|
||||
info!(
|
||||
context,
|
||||
0, "Generating keypair with {} bits, e={} ...", 2048, 65537,
|
||||
);
|
||||
match dc_pgp_create_keypair(&self_addr) {
|
||||
Some((public_key, private_key)) => {
|
||||
match dc_key_save_self_keypair(
|
||||
|
||||
if let Some((public_key, private_key)) = dc_pgp_create_keypair(&self_addr) {
|
||||
if !dc_key_save_self_keypair(
|
||||
context,
|
||||
&public_key,
|
||||
&private_key,
|
||||
&self_addr,
|
||||
1i32,
|
||||
&context.sql,
|
||||
) {
|
||||
/*set default*/
|
||||
warn!(context, 0, "Cannot save keypair.",);
|
||||
} else {
|
||||
info!(
|
||||
context,
|
||||
&public_key,
|
||||
&private_key,
|
||||
&self_addr,
|
||||
1,
|
||||
&context.sql,
|
||||
) {
|
||||
true => {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Keypair generated in {:.3}s.",
|
||||
start.elapsed().as_secs()
|
||||
);
|
||||
Ok(public_key)
|
||||
}
|
||||
false => Err(format_err!("Failed to save keypair")),
|
||||
}
|
||||
0,
|
||||
"Keypair generated in {:.3}s.",
|
||||
clock().wrapping_sub(start) as libc::c_double / 1000000 as libc::c_double,
|
||||
);
|
||||
}
|
||||
None => Err(format_err!("Failed to generate keypair")),
|
||||
|
||||
key = Some(public_key);
|
||||
} else {
|
||||
warn!(context, 0, "Cannot create keypair.");
|
||||
}
|
||||
|
||||
if 0 != key_creation_here {
|
||||
S_IN_KEY_CREATION = 0;
|
||||
}
|
||||
|
||||
key
|
||||
}
|
||||
|
||||
/* returns 1 if sth. was decrypted, 0 in other cases */
|
||||
@@ -540,23 +535,25 @@ pub unsafe fn dc_e2ee_decrypt(
|
||||
/*just a pointer into mailmime structure, must not be freed*/
|
||||
let imffields: *mut mailimf_fields = mailmime_find_mailimf_fields(in_out_message);
|
||||
let mut message_time = 0;
|
||||
let mut from: *mut libc::c_char = ptr::null_mut();
|
||||
let mut from: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut private_keyring = Keyring::default();
|
||||
let mut public_keyring_for_validate = Keyring::default();
|
||||
let mut gossip_headers: *mut mailimf_fields = ptr::null_mut();
|
||||
let mut gossip_headers: *mut mailimf_fields = 0 as *mut mailimf_fields;
|
||||
if !(in_out_message.is_null() || imffields.is_null()) {
|
||||
let mut field: *mut mailimf_field =
|
||||
mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int);
|
||||
if !field.is_null() && !(*field).fld_data.fld_from.is_null() {
|
||||
from = mailimf_find_first_addr((*(*field).fld_data.fld_from).frm_mb_list)
|
||||
}
|
||||
field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int);
|
||||
if !field.is_null() && !(*field).fld_data.fld_orig_date.is_null() {
|
||||
let orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date;
|
||||
if !orig_date.is_null() {
|
||||
message_time = dc_timestamp_from_date((*orig_date).dt_date_time);
|
||||
if message_time != 0 && message_time > time() {
|
||||
message_time = time()
|
||||
if !imffields.is_null() {
|
||||
let mut field: *mut mailimf_field =
|
||||
mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int);
|
||||
if !field.is_null() && !(*field).fld_data.fld_from.is_null() {
|
||||
from = mailimf_find_first_addr((*(*field).fld_data.fld_from).frm_mb_list)
|
||||
}
|
||||
field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int);
|
||||
if !field.is_null() && !(*field).fld_data.fld_orig_date.is_null() {
|
||||
let orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date;
|
||||
if !orig_date.is_null() {
|
||||
message_time = dc_timestamp_from_date((*orig_date).dt_date_time);
|
||||
if message_time != 0 && message_time > time() {
|
||||
message_time = time()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,7 +574,7 @@ pub unsafe fn dc_e2ee_decrypt(
|
||||
}
|
||||
} else if let Some(ref header) = autocryptheader {
|
||||
let p = Peerstate::from_header(context, header, message_time);
|
||||
assert!(p.save_to_db(&context.sql, true));
|
||||
p.save_to_db(&context.sql, true);
|
||||
peerstate = Some(p);
|
||||
}
|
||||
}
|
||||
@@ -647,7 +644,7 @@ unsafe fn update_gossip_peerstates(
|
||||
let field: *mut mailimf_field = (if !cur1.is_null() {
|
||||
(*cur1).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailimf_field;
|
||||
if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
||||
let optional_field: *const mailimf_optional_field =
|
||||
@@ -699,7 +696,7 @@ unsafe fn update_gossip_peerstates(
|
||||
cur1 = if !cur1.is_null() {
|
||||
(*cur1).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
|
||||
@@ -732,7 +729,7 @@ unsafe fn decrypt_recursive(
|
||||
{
|
||||
cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first;
|
||||
while !cur.is_null() {
|
||||
let mut decrypted_mime: *mut mailmime = ptr::null_mut();
|
||||
let mut decrypted_mime: *mut mailmime = 0 as *mut mailmime;
|
||||
if 0 != decrypt_part(
|
||||
context,
|
||||
(if !cur.is_null() {
|
||||
@@ -747,7 +744,7 @@ unsafe fn decrypt_recursive(
|
||||
) {
|
||||
if (*ret_gossip_headers).is_null() && ret_valid_signatures.len() > 0 {
|
||||
let mut dummy: size_t = 0i32 as size_t;
|
||||
let mut test: *mut mailimf_fields = ptr::null_mut();
|
||||
let mut test: *mut mailimf_fields = 0 as *mut mailimf_fields;
|
||||
if mailimf_envelope_and_optional_fields_parse(
|
||||
(*decrypted_mime).mm_mime_start,
|
||||
(*decrypted_mime).mm_length,
|
||||
@@ -778,7 +775,7 @@ unsafe fn decrypt_recursive(
|
||||
(if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailmime,
|
||||
private_keyring,
|
||||
public_keyring_for_validate,
|
||||
@@ -791,7 +788,7 @@ unsafe fn decrypt_recursive(
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -815,7 +812,7 @@ unsafe fn decrypt_recursive(
|
||||
}
|
||||
|
||||
unsafe fn decrypt_part(
|
||||
_context: &Context,
|
||||
context: &Context,
|
||||
mime: *mut mailmime,
|
||||
private_keyring: &Keyring,
|
||||
public_keyring_for_validate: &Keyring,
|
||||
@@ -826,12 +823,12 @@ unsafe fn decrypt_part(
|
||||
let mime_data: *mut mailmime_data;
|
||||
let mut mime_transfer_encoding: libc::c_int = MAILMIME_MECHANISM_BINARY as libc::c_int;
|
||||
/* mmap_string_unref()'d if set */
|
||||
let mut transfer_decoding_buffer: *mut libc::c_char = ptr::null_mut();
|
||||
let mut transfer_decoding_buffer: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
/* must not be free()'d */
|
||||
let mut decoded_data: *const libc::c_char = ptr::null_mut();
|
||||
let mut decoded_data: *const libc::c_char = 0 as *const libc::c_char;
|
||||
let mut decoded_data_bytes: size_t = 0i32 as size_t;
|
||||
let mut sth_decrypted: libc::c_int = 0i32;
|
||||
*ret_decrypted_mime = ptr::null_mut();
|
||||
*ret_decrypted_mime = 0 as *mut mailmime;
|
||||
mime_data = (*mime).mm_data.mm_single;
|
||||
/* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */
|
||||
if !((*mime_data).dt_type != MAILMIME_DATA_TEXT as libc::c_int
|
||||
@@ -845,7 +842,7 @@ unsafe fn decrypt_part(
|
||||
let field: *mut mailmime_field = (if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailmime_field;
|
||||
if !field.is_null() {
|
||||
if (*field).fld_type == MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int
|
||||
@@ -857,7 +854,7 @@ unsafe fn decrypt_part(
|
||||
cur = if !cur.is_null() {
|
||||
(*cur).next
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut clistcell
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -913,7 +910,7 @@ unsafe fn decrypt_part(
|
||||
let plain_buf = plain.as_ptr() as *const libc::c_char;
|
||||
|
||||
let mut index: size_t = 0i32 as size_t;
|
||||
let mut decrypted_mime: *mut mailmime = ptr::null_mut();
|
||||
let mut decrypted_mime: *mut mailmime = 0 as *mut mailmime;
|
||||
if mailmime_parse(
|
||||
plain_buf as *const _,
|
||||
plain_bytes,
|
||||
@@ -1011,7 +1008,7 @@ unsafe fn contains_report(mime: *mut mailmime) -> libc::c_int {
|
||||
(if !cur.is_null() {
|
||||
(*cur).data
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
0 as *mut libc::c_void
|
||||
}) as *mut mailmime,
|
||||
) {
|
||||
return 1i32;
|
||||
@@ -1034,52 +1031,36 @@ unsafe fn contains_report(mime: *mut mailmime) -> libc::c_int {
|
||||
/* frees data referenced by "mailmime" but not freed by mailmime_free(). After calling this function, in_out_message cannot be used any longer! */
|
||||
pub unsafe fn dc_e2ee_thanks(helper: &mut dc_e2ee_helper_t) {
|
||||
free(helper.cdata_to_free);
|
||||
helper.cdata_to_free = ptr::null_mut();
|
||||
helper.cdata_to_free = 0 as *mut libc::c_void;
|
||||
}
|
||||
|
||||
/// Ensures a private key exists for the configured user.
|
||||
///
|
||||
/// Normally the private key is generated when the first message is
|
||||
/// sent but in a few locations there are no such guarantees,
|
||||
/// e.g. when exporting keys, and calling this function ensures a
|
||||
/// private key will be present.
|
||||
///
|
||||
/// If this succeeds you are also guaranteed that the
|
||||
/// [Config::ConfiguredAddr] is configured, this address is returned.
|
||||
pub fn dc_ensure_secret_key_exists(context: &Context) -> Result<String> {
|
||||
let self_addr = context
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.ok_or(format_err!(concat!(
|
||||
"Failed to get self address, ",
|
||||
"cannot ensure secret key if not configured."
|
||||
)))?;
|
||||
load_or_generate_self_public_key(context, &self_addr)?;
|
||||
Ok(self_addr)
|
||||
/* makes sure, the private key exists, needed only for exporting keys and the case no message was sent before */
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_ensure_secret_key_exists(context: &Context) -> libc::c_int {
|
||||
/* normally, the key is generated as soon as the first mail is send
|
||||
(this is to gain some extra-random-seed by the message content and the timespan between program start and message sending) */
|
||||
let mut success: libc::c_int = 0i32;
|
||||
|
||||
let self_addr = context.sql.get_config(context, "configured_addr");
|
||||
if self_addr.is_none() {
|
||||
warn!(
|
||||
context,
|
||||
0, "Cannot ensure secret key if context is not configured.",
|
||||
);
|
||||
} else if load_or_generate_self_public_key(context, self_addr.unwrap(), 0 as *mut mailmime)
|
||||
.is_some()
|
||||
{
|
||||
/*no random text data for seeding available*/
|
||||
success = 1;
|
||||
}
|
||||
|
||||
success
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::test_utils::*;
|
||||
|
||||
mod ensure_secret_key_exists {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_prexisting() {
|
||||
let t = dummy_context();
|
||||
let test_addr = configure_alice_keypair(&t.ctx);
|
||||
assert_eq!(dc_ensure_secret_key_exists(&t.ctx).unwrap(), test_addr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_configured() {
|
||||
let t = dummy_context();
|
||||
assert!(dc_ensure_secret_key_exists(&t.ctx).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mailmime_parse() {
|
||||
let plain = b"Chat-Disposition-Notification-To: holger@deltachat.de
|
||||
@@ -1140,47 +1121,4 @@ Sent with my Delta Chat Messenger: https://delta.chat";
|
||||
|
||||
unsafe { free(decrypted_mime as *mut _) };
|
||||
}
|
||||
|
||||
mod load_or_generate_self_public_key {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_existing() {
|
||||
let t = dummy_context();
|
||||
let addr = configure_alice_keypair(&t.ctx);
|
||||
let key = load_or_generate_self_public_key(&t.ctx, addr);
|
||||
assert!(key.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // generating keys is expensive
|
||||
fn test_generate() {
|
||||
let t = dummy_context();
|
||||
let addr = "alice@example.org";
|
||||
let key0 = load_or_generate_self_public_key(&t.ctx, addr);
|
||||
assert!(key0.is_ok());
|
||||
let key1 = load_or_generate_self_public_key(&t.ctx, addr);
|
||||
assert!(key1.is_ok());
|
||||
assert_eq!(key0.unwrap(), key1.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_generate_concurrent() {
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
let t = dummy_context();
|
||||
let ctx = Arc::new(t.ctx);
|
||||
let ctx0 = Arc::clone(&ctx);
|
||||
let thr0 =
|
||||
thread::spawn(move || load_or_generate_self_public_key(&ctx0, "alice@example.org"));
|
||||
let ctx1 = Arc::clone(&ctx);
|
||||
let thr1 =
|
||||
thread::spawn(move || load_or_generate_self_public_key(&ctx1, "alice@example.org"));
|
||||
let res0 = thr0.join().unwrap();
|
||||
let res1 = thr1.join().unwrap();
|
||||
assert_eq!(res0.unwrap(), res1.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
418
src/dc_imex.rs
418
src/dc_imex.rs
@@ -1,5 +1,4 @@
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
use mmime::mailmime_content::*;
|
||||
use mmime::mmapstring::*;
|
||||
@@ -62,7 +61,7 @@ pub unsafe fn dc_imex_has_backup(
|
||||
"Backup check: Cannot open directory \"{}\".\x00",
|
||||
dir_name.display(),
|
||||
);
|
||||
return ptr::null_mut();
|
||||
return 0 as *mut libc::c_char;
|
||||
}
|
||||
let mut newest_backup_time = 0;
|
||||
let mut newest_backup_path: Option<std::path::PathBuf> = None;
|
||||
@@ -101,8 +100,8 @@ pub unsafe fn dc_imex_has_backup(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
let mut setup_file_name: *mut libc::c_char = ptr::null_mut();
|
||||
let mut msg: *mut dc_msg_t = ptr::null_mut();
|
||||
let mut setup_file_name: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t;
|
||||
if dc_alloc_ongoing(context) == 0 {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
@@ -160,7 +159,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
let msg_id = dc_send_msg(context, chat_id, msg);
|
||||
if msg_id != 0 {
|
||||
dc_msg_unref(msg);
|
||||
msg = ptr::null_mut();
|
||||
msg = 0 as *mut dc_msg_t;
|
||||
info!(context, 0, "Wait for setup message being sent ...",);
|
||||
loop {
|
||||
if context
|
||||
@@ -195,15 +194,20 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
setup_code.strdup()
|
||||
}
|
||||
|
||||
/// Renders HTML body of a setup file message.
|
||||
///
|
||||
/// The `passphrase` must be at least 2 characters long.
|
||||
pub fn dc_render_setup_file(context: &Context, passphrase: &str) -> Result<String> {
|
||||
ensure!(
|
||||
passphrase.len() >= 2,
|
||||
"Passphrase must be at least 2 chars long."
|
||||
);
|
||||
let self_addr = dc_ensure_secret_key_exists(context)?;
|
||||
unsafe {
|
||||
ensure!(
|
||||
!(dc_ensure_secret_key_exists(context) == 0),
|
||||
"No secret key available."
|
||||
);
|
||||
}
|
||||
let self_addr = context
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.ok_or(format_err!("Failed to get self address."))?;
|
||||
let private_key = Key::from_self_private(context, self_addr, &context.sql)
|
||||
.ok_or(format_err!("Failed to get private key."))?;
|
||||
let ac_headers = match context
|
||||
@@ -286,12 +290,12 @@ pub unsafe fn dc_continue_key_transfer(
|
||||
setup_code: *const libc::c_char,
|
||||
) -> libc::c_int {
|
||||
let mut success: libc::c_int = 0i32;
|
||||
let mut msg: *mut dc_msg_t = ptr::null_mut();
|
||||
let mut filename: *mut libc::c_char = ptr::null_mut();
|
||||
let mut filecontent: *mut libc::c_char = ptr::null_mut();
|
||||
let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t;
|
||||
let mut filename: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut filecontent: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut filebytes: size_t = 0i32 as size_t;
|
||||
let mut armored_key: *mut libc::c_char = ptr::null_mut();
|
||||
let mut norm_sc: *mut libc::c_char = ptr::null_mut();
|
||||
let mut armored_key: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut norm_sc: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
if !(msg_id <= 9i32 as libc::c_uint || setup_code.is_null()) {
|
||||
msg = dc_get_msg(context, msg_id);
|
||||
if msg.is_null()
|
||||
@@ -424,19 +428,19 @@ pub unsafe fn dc_decrypt_setup_file(
|
||||
filecontent: *const libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
let fc_buf: *mut libc::c_char;
|
||||
let mut fc_headerline: *const libc::c_char = ptr::null();
|
||||
let mut fc_base64: *const libc::c_char = ptr::null();
|
||||
let mut binary: *mut libc::c_char = ptr::null_mut();
|
||||
let mut fc_headerline: *const libc::c_char = 0 as *const libc::c_char;
|
||||
let mut fc_base64: *const libc::c_char = 0 as *const libc::c_char;
|
||||
let mut binary: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut binary_bytes: size_t = 0i32 as size_t;
|
||||
let mut indx: size_t = 0i32 as size_t;
|
||||
|
||||
let mut payload: *mut libc::c_char = ptr::null_mut();
|
||||
let mut payload: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
fc_buf = dc_strdup(filecontent);
|
||||
if dc_split_armored_data(
|
||||
fc_buf,
|
||||
&mut fc_headerline,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
0 as *mut *const libc::c_char,
|
||||
0 as *mut *const libc::c_char,
|
||||
&mut fc_base64,
|
||||
) && !fc_headerline.is_null()
|
||||
&& strcmp(
|
||||
@@ -480,7 +484,7 @@ pub unsafe fn dc_normalize_setup_code(
|
||||
in_0: *const libc::c_char,
|
||||
) -> *mut libc::c_char {
|
||||
if in_0.is_null() {
|
||||
return ptr::null_mut();
|
||||
return 0 as *mut libc::c_char;
|
||||
}
|
||||
let mut out = String::new();
|
||||
let mut outlen;
|
||||
@@ -509,7 +513,7 @@ pub unsafe fn dc_normalize_setup_code(
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t) {
|
||||
let mut ok_to_continue = true;
|
||||
let mut current_block: u64;
|
||||
let mut success: libc::c_int = 0;
|
||||
let mut ongoing_allocated_here: libc::c_int = 0;
|
||||
let what: libc::c_int;
|
||||
@@ -517,8 +521,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t)
|
||||
if !(0 == dc_alloc_ongoing(context)) {
|
||||
ongoing_allocated_here = 1;
|
||||
what = (*job).param.get_int(Param::Cmd).unwrap_or_default();
|
||||
let param1_s = (*job).param.get(Param::Arg).unwrap_or_default();
|
||||
let param1 = CString::yolo(param1_s);
|
||||
let param1 = CString::yolo((*job).param.get(Param::Arg).unwrap_or_default());
|
||||
let _param2 = CString::yolo((*job).param.get(Param::Arg2).unwrap_or_default());
|
||||
|
||||
if strlen(param1.as_ptr()) == 0 {
|
||||
@@ -531,45 +534,185 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t)
|
||||
} else {
|
||||
if what == 1 || what == 11 {
|
||||
/* before we export anything, make sure the private key exists */
|
||||
if dc_ensure_secret_key_exists(context).is_err() {
|
||||
if 0 == dc_ensure_secret_key_exists(context) {
|
||||
error!(
|
||||
context,
|
||||
0,
|
||||
"Import/export: Cannot create private key or private key not available.",
|
||||
);
|
||||
ok_to_continue = false;
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
dc_create_folder(context, ¶m1_s);
|
||||
dc_create_folder(context, param1.as_ptr());
|
||||
current_block = 4495394744059808450;
|
||||
}
|
||||
} else {
|
||||
current_block = 4495394744059808450;
|
||||
}
|
||||
if ok_to_continue {
|
||||
match what {
|
||||
match current_block {
|
||||
3568988166330621280 => {}
|
||||
_ => match what {
|
||||
1 => {
|
||||
if 0 != export_self_keys(context, param1.as_ptr()) {
|
||||
info!(context, 0, "Import/export completed.",);
|
||||
success = 1
|
||||
current_block = 10991094515395304355;
|
||||
match current_block {
|
||||
2973387206439775448 => {
|
||||
if 0 == import_backup(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
11250025114629486028 => {
|
||||
if 0 == import_self_keys(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
12669919903773909120 => {
|
||||
if 0 == export_backup(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if 0 == export_self_keys(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
}
|
||||
match current_block {
|
||||
3568988166330621280 => {}
|
||||
_ => {
|
||||
info!(context, 0, "Import/export completed.",);
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
if 0 != import_self_keys(context, param1.as_ptr()) {
|
||||
info!(context, 0, "Import/export completed.",);
|
||||
success = 1
|
||||
current_block = 11250025114629486028;
|
||||
match current_block {
|
||||
2973387206439775448 => {
|
||||
if 0 == import_backup(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
11250025114629486028 => {
|
||||
if 0 == import_self_keys(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
12669919903773909120 => {
|
||||
if 0 == export_backup(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if 0 == export_self_keys(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
}
|
||||
match current_block {
|
||||
3568988166330621280 => {}
|
||||
_ => {
|
||||
info!(context, 0, "Import/export completed.",);
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
11 => {
|
||||
if 0 != export_backup(context, param1.as_ptr()) {
|
||||
info!(context, 0, "Import/export completed.",);
|
||||
success = 1
|
||||
current_block = 12669919903773909120;
|
||||
match current_block {
|
||||
2973387206439775448 => {
|
||||
if 0 == import_backup(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
11250025114629486028 => {
|
||||
if 0 == import_self_keys(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
12669919903773909120 => {
|
||||
if 0 == export_backup(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if 0 == export_self_keys(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
}
|
||||
match current_block {
|
||||
3568988166330621280 => {}
|
||||
_ => {
|
||||
info!(context, 0, "Import/export completed.",);
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
12 => {
|
||||
if 0 != import_backup(context, param1.as_ptr()) {
|
||||
info!(context, 0, "Import/export completed.",);
|
||||
success = 1
|
||||
current_block = 2973387206439775448;
|
||||
match current_block {
|
||||
2973387206439775448 => {
|
||||
if 0 == import_backup(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
11250025114629486028 => {
|
||||
if 0 == import_self_keys(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
12669919903773909120 => {
|
||||
if 0 == export_backup(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if 0 == export_self_keys(context, param1.as_ptr()) {
|
||||
current_block = 3568988166330621280;
|
||||
} else {
|
||||
current_block = 1118134448028020070;
|
||||
}
|
||||
}
|
||||
}
|
||||
match current_block {
|
||||
3568988166330621280 => {}
|
||||
_ => {
|
||||
info!(context, 0, "Import/export completed.",);
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -597,10 +740,7 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
|
||||
0,
|
||||
"Import \"{}\" to \"{}\".",
|
||||
as_str(backup_to_import),
|
||||
context
|
||||
.get_dbfile()
|
||||
.as_ref()
|
||||
.map_or("<<None>>", |p| p.to_str().unwrap())
|
||||
as_str(context.get_dbfile()),
|
||||
);
|
||||
|
||||
if 0 != dc_is_configured(context) {
|
||||
@@ -608,8 +748,8 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
|
||||
return 0;
|
||||
}
|
||||
&context.sql.close(&context);
|
||||
dc_delete_file(context, context.get_dbfile().unwrap());
|
||||
if dc_file_exist(context, context.get_dbfile().unwrap()) {
|
||||
dc_delete_file(context, context.get_dbfile());
|
||||
if 0 != dc_file_exist(context, context.get_dbfile()) {
|
||||
error!(
|
||||
context,
|
||||
0, "Cannot import backups: Cannot delete the old file.",
|
||||
@@ -617,19 +757,12 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
|
||||
return 0;
|
||||
}
|
||||
|
||||
if !dc_copy_file(
|
||||
context,
|
||||
as_path(backup_to_import),
|
||||
context.get_dbfile().unwrap(),
|
||||
) {
|
||||
if 0 == dc_copy_file(context, backup_to_import, context.get_dbfile()) {
|
||||
return 0;
|
||||
}
|
||||
/* error already logged */
|
||||
/* re-open copied database file */
|
||||
if !context
|
||||
.sql
|
||||
.open(&context, &context.get_dbfile().unwrap(), 0)
|
||||
{
|
||||
if !context.sql.open(&context, as_path(context.get_dbfile()), 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -748,20 +881,11 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
|
||||
context,
|
||||
0,
|
||||
"Backup \"{}\" to \"{}\".",
|
||||
context
|
||||
.get_dbfile()
|
||||
.as_ref()
|
||||
.map_or("<<None>>", |p| p.to_str().unwrap()),
|
||||
as_str(context.get_dbfile()),
|
||||
as_str(dest_pathNfilename),
|
||||
);
|
||||
if dc_copy_file(
|
||||
context,
|
||||
context.get_dbfile().unwrap(),
|
||||
as_path(dest_pathNfilename),
|
||||
) {
|
||||
context
|
||||
.sql
|
||||
.open(&context, &context.get_dbfile().unwrap(), 0);
|
||||
if !(0 == dc_copy_file(context, context.get_dbfile(), dest_pathNfilename)) {
|
||||
context.sql.open(&context, as_path(context.get_dbfile()), 0);
|
||||
closed = false;
|
||||
/* add all files as blobs to the database copy (this does not require the source to be locked, neigher the destination as it is used only here) */
|
||||
/*for logging only*/
|
||||
@@ -917,12 +1041,10 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
|
||||
}
|
||||
}
|
||||
if closed {
|
||||
context
|
||||
.sql
|
||||
.open(&context, &context.get_dbfile().unwrap(), 0);
|
||||
context.sql.open(&context, as_path(context.get_dbfile()), 0);
|
||||
}
|
||||
if 0 != delete_dest_file {
|
||||
dc_delete_file(context, as_path(dest_pathNfilename));
|
||||
dc_delete_file(context, dest_pathNfilename);
|
||||
}
|
||||
free(dest_pathNfilename as *mut libc::c_void);
|
||||
|
||||
@@ -940,16 +1062,16 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
Maybe we should make the "default" key handlong also a little bit smarter
|
||||
(currently, the last imported key is the standard key unless it contains the string "legacy" in its name) */
|
||||
let mut imported_cnt: libc::c_int = 0;
|
||||
let mut suffix: *mut libc::c_char = ptr::null_mut();
|
||||
let mut path_plus_name: *mut libc::c_char = ptr::null_mut();
|
||||
let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut path_plus_name: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut set_default: libc::c_int;
|
||||
let mut buf: *mut libc::c_char = ptr::null_mut();
|
||||
let mut buf: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut buf_bytes: size_t = 0 as size_t;
|
||||
// a pointer inside buf, MUST NOT be free()'d
|
||||
let mut private_key: *const libc::c_char;
|
||||
let mut buf2: *mut libc::c_char = ptr::null_mut();
|
||||
let mut buf2: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
// a pointer inside buf2, MUST NOT be free()'d
|
||||
let mut buf2_headerline: *const libc::c_char = ptr::null_mut();
|
||||
let mut buf2_headerline: *const libc::c_char = 0 as *const libc::c_char;
|
||||
if !dir_name.is_null() {
|
||||
let dir = std::path::Path::new(as_str(dir_name));
|
||||
let dir_handle = std::fs::read_dir(dir);
|
||||
@@ -984,7 +1106,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
);
|
||||
info!(context, 0, "Checking: {}", as_str(path_plus_name));
|
||||
free(buf as *mut libc::c_void);
|
||||
buf = ptr::null_mut();
|
||||
buf = 0 as *mut libc::c_char;
|
||||
if 0 == dc_read_file(
|
||||
context,
|
||||
path_plus_name,
|
||||
@@ -1142,7 +1264,7 @@ unsafe fn export_key_to_asc_file(
|
||||
)
|
||||
}
|
||||
info!(context, 0, "Exporting key {}", as_str(file_name),);
|
||||
dc_delete_file(context, as_path(file_name));
|
||||
dc_delete_file(context, file_name);
|
||||
if !key.write_asc_to_file(file_name, context) {
|
||||
error!(context, 0, "Cannot write key to {}", as_str(file_name),);
|
||||
} else {
|
||||
@@ -1162,15 +1284,147 @@ unsafe fn export_key_to_asc_file(
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::ffi::CStr;
|
||||
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::key;
|
||||
use crate::test_utils::*;
|
||||
|
||||
unsafe extern "C" fn logging_cb(
|
||||
_ctx: &Context,
|
||||
evt: Event,
|
||||
_d1: uintptr_t,
|
||||
d2: uintptr_t,
|
||||
) -> uintptr_t {
|
||||
let to_str = |x| CStr::from_ptr(x as *const libc::c_char).to_str().unwrap();
|
||||
match evt {
|
||||
Event::INFO => println!("I: {}", to_str(d2)),
|
||||
Event::WARNING => println!("W: {}", to_str(d2)),
|
||||
Event::ERROR => println!("E: {}", to_str(d2)),
|
||||
_ => (),
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
/// Create Alice with a pre-generated keypair.
|
||||
fn create_alice_keypair(ctx: &Context) {
|
||||
ctx.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
|
||||
.unwrap();
|
||||
|
||||
// The keypair was created using:
|
||||
// let (public, private) = crate::pgp::dc_pgp_create_keypair("alice@example.com")
|
||||
// .unwrap();
|
||||
// println!("{}", public.to_base64(64));
|
||||
// println!("{}", private.to_base64(64));
|
||||
let public = key::Key::from_base64(
|
||||
concat!(
|
||||
"xsBNBF086ewBCACmJKuoxIO6T87yi4Q3MyNpMch3Y8KrtHDQyUszU36eqM3Pmd1l",
|
||||
"FrbcCd8ZWo2pq6OJSwsM/jjRGn1zo2YOaQeJRRrC+KrKGqSUtRSYQBPrPjE2YjSX",
|
||||
"AMbu8jBI6VVUhHeghriBkK79PY9O/oRhIJC0p14IJe6CQ6OI2fTmTUHF9i/nJ3G4",
|
||||
"Wb3/K1bU3yVfyPZjTZQPYPvvh03vxHULKurtYkX5DTEMSWsF4qzLMps+l87VuLV9",
|
||||
"iQnbN7YMRLHHx2KkX5Ivi7JCefhCa54M0K3bDCCxuVWAM5wjQwNZjzR+WL+dYchw",
|
||||
"oFvuF8NrlzjM9dSv+2rn+J7f99ijSXarzPC7ABEBAAHNEzxhbGljZUBleGFtcGxl",
|
||||
"LmNvbT7CwIkEEAEIADMCGQEFAl086fgCGwMECwkIBwYVCAkKCwIDFgIBFiEE+iai",
|
||||
"x4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcei3ogf/cruUmQ+th52TFHTHdkw9",
|
||||
"OHUl3MrXtZ7QmHyOAFvbXE/6n5Eeh+eZoF8MWWV72m14Wbs+vTcNQkFVTdOPptkK",
|
||||
"A8e4cJqwDOHsyAnvQXZ7WNje9+BMzcoipIUawHP4ORFaPDsKLZQ0b4wBbKn8ziea",
|
||||
"6zjGF0/qljTdoxTtsYpv5wXYuhwbYklrLOqgSa5M7LXUe7E3g9mbg+9iX1GuB8m6",
|
||||
"GkquJN814Y+xny4xhZzGOfue6SeP12jJMNSjSP7416dRq7794VGnkkW9V/7oFEUK",
|
||||
"u5wO9FFbgDySOSlEjByGejSGuBmho0iJSjcPjZ7EY/j3M3orq4dpza5C82OeSvxD",
|
||||
"Fc7ATQRdPOnsAQgA5oLxXRLnyugzOmNCy7dxV3JrDZscA6JNlJlDWIShT0YSs+zG",
|
||||
"9JzDeQql+sYXgUSxOoIayItuXtnFn7tstwGoOnYvadm/e5/7V5fKAQRtCtdN51av",
|
||||
"62n18Venlm0yNKpROPcZ6M/sc4m6uU6YRZ/a1idal8VGY0wLKlghjIBuIiBoVQ/R",
|
||||
"noW+/fhmwIg08dQ5m8hQe3GEOZEeLrTWL/9awPlXK7Y+DmJOoR4qbHWEcRfbzS6q",
|
||||
"4zW8vk2ztB8ngwbnqYy8zrN1DCICN1gYdlU++uVw6Bb1XfY8Cdldh1VLKpF35mAm",
|
||||
"jxLZfVDcoObFH3Cv2GB7BEYxv86KC2Y6T74Q/wARAQABwsB2BBgBCAAgBQJdPOn4",
|
||||
"AhsMFiEE+iaix4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcegLxwf/dXshJnoW",
|
||||
"qEnRsf6rVb9/Mc66ti+NVQLfNd275dybh/QIJdK3NmSxdnTPIEJRVspJywJoupwX",
|
||||
"FNrnHG2Ff6QPvHqI+/oNu986r9d7Z1oQibbLHKt8t6kpOfg/xGxotagJuiCQvR9m",
|
||||
"MjD1DqsdB37SjDxGupZOOJSXWi6KX60IE+uM+QOBfeOZziQwuFmA5wV6RDXIeYJf",
|
||||
"qrcbeXeR1d0nfNpPHQR1gBiqmxNb6KBbdXD2+EXW60axC7D2b1APmzMlammDliPw",
|
||||
"sK9U1rc9nuquEBvGDOJf4K+Dzn+mDCqRpP6uAuQ7RKHyim4uyN0wwKObzPqgJCGw",
|
||||
"jTglkixw+aSTXw=="
|
||||
),
|
||||
KeyType::Public,
|
||||
)
|
||||
.unwrap();
|
||||
let private = key::Key::from_base64(
|
||||
concat!(
|
||||
"xcLYBF086ewBCACmJKuoxIO6T87yi4Q3MyNpMch3Y8KrtHDQyUszU36eqM3Pmd1l",
|
||||
"FrbcCd8ZWo2pq6OJSwsM/jjRGn1zo2YOaQeJRRrC+KrKGqSUtRSYQBPrPjE2YjSX",
|
||||
"AMbu8jBI6VVUhHeghriBkK79PY9O/oRhIJC0p14IJe6CQ6OI2fTmTUHF9i/nJ3G4",
|
||||
"Wb3/K1bU3yVfyPZjTZQPYPvvh03vxHULKurtYkX5DTEMSWsF4qzLMps+l87VuLV9",
|
||||
"iQnbN7YMRLHHx2KkX5Ivi7JCefhCa54M0K3bDCCxuVWAM5wjQwNZjzR+WL+dYchw",
|
||||
"oFvuF8NrlzjM9dSv+2rn+J7f99ijSXarzPC7ABEBAAEACAChqzVOuErmVRqvcYtq",
|
||||
"m1xt1H+ZjX20z5Sn1fhTLYAcq236AWMqJvwxCXoKlc8bt2UfB+Ls9cQb1YcVq353",
|
||||
"r0QiExiDeK3YlCxqd/peXJwFYTNKFC3QcnUhtpG9oS/jWjN+BRotGbjtu6Vj3M68",
|
||||
"JJAq+mHJ0/9OyrqrREvGfo7uLZt7iMGemDlrDakvrbIyZrPLgay+nZ3dEFKeOQ6F",
|
||||
"FrU05jyUVdoHBy0Tqx/6VpFUX9+IHcMHL2lTJB0nynBj+XZ/G4aX3WYoo3YlixHb",
|
||||
"Iu35fGFA0TChoGaGPzqcI/kg2Z+b/BryG9NM3LA2cO8iGrGXAE1nPFp91jmCrQ3V",
|
||||
"WushBADERP+uojjjfdO5J+RkmcFe9mFYDdtkhN+kV+LdePjiNNtcXMBhasstio0S",
|
||||
"ut0GKnE7DFRhX7mkN9w2apJ2ooeFeVVWot18eSdp6Rzh6/1Z7TmhYFJ3oUxxLbnQ",
|
||||
"sWIXIec1SzqWBFJUCn3IP0mCnJktFg/uGW6yLs01r5ds52uSBQQA2LSWiTwk9tEm",
|
||||
"dr9mz3tHnmrkyGiyKhKGM1Z7Rch63D5yQc1s4kUMBlyuLL2QtM/e4dtaz2JAkO8k",
|
||||
"QrYCnNgJ+2roTAK3kDZgYtymjdvK3HpQNtjVo7dds5RJVb6U618phZwU5WNFAEJW",
|
||||
"yyImmycGfjLv+18cW/3mq0QVZejkM78D/2kHaIeJAowtBOFY2zDrKyDRoBHaUSgj",
|
||||
"5BjGoviRC5rYihWDEyYDQ6mBJQstAD0Ty3MYzyUxl6ruB/BMWnMDFq5+TqtdBzu3",
|
||||
"jCtZ8OEyH8A5Kdo68Wzo/PGxzMtusOdNj9+3PBmSq4yibJxbLSrn59aVUYpGLjeG",
|
||||
"Kyvm9OTKkrOGN27NEzxhbGljZUBleGFtcGxlLmNvbT7CwIkEEAEIADMCGQEFAl08",
|
||||
"6fgCGwMECwkIBwYVCAkKCwIDFgIBFiEE+iaix4d0doj87Q0ek6DcNkbrcegACgkQ",
|
||||
"k6DcNkbrcei3ogf/cruUmQ+th52TFHTHdkw9OHUl3MrXtZ7QmHyOAFvbXE/6n5Ee",
|
||||
"h+eZoF8MWWV72m14Wbs+vTcNQkFVTdOPptkKA8e4cJqwDOHsyAnvQXZ7WNje9+BM",
|
||||
"zcoipIUawHP4ORFaPDsKLZQ0b4wBbKn8ziea6zjGF0/qljTdoxTtsYpv5wXYuhwb",
|
||||
"YklrLOqgSa5M7LXUe7E3g9mbg+9iX1GuB8m6GkquJN814Y+xny4xhZzGOfue6SeP",
|
||||
"12jJMNSjSP7416dRq7794VGnkkW9V/7oFEUKu5wO9FFbgDySOSlEjByGejSGuBmh",
|
||||
"o0iJSjcPjZ7EY/j3M3orq4dpza5C82OeSvxDFcfC2ARdPOnsAQgA5oLxXRLnyugz",
|
||||
"OmNCy7dxV3JrDZscA6JNlJlDWIShT0YSs+zG9JzDeQql+sYXgUSxOoIayItuXtnF",
|
||||
"n7tstwGoOnYvadm/e5/7V5fKAQRtCtdN51av62n18Venlm0yNKpROPcZ6M/sc4m6",
|
||||
"uU6YRZ/a1idal8VGY0wLKlghjIBuIiBoVQ/RnoW+/fhmwIg08dQ5m8hQe3GEOZEe",
|
||||
"LrTWL/9awPlXK7Y+DmJOoR4qbHWEcRfbzS6q4zW8vk2ztB8ngwbnqYy8zrN1DCIC",
|
||||
"N1gYdlU++uVw6Bb1XfY8Cdldh1VLKpF35mAmjxLZfVDcoObFH3Cv2GB7BEYxv86K",
|
||||
"C2Y6T74Q/wARAQABAAgAhSvFEYZoj1sSrXrHDjZOrryViGjCCH9t3pmkxLDrGIdd",
|
||||
"KsFyN8ORUo6KUZS745yx3yFnI9EZ1IZvm9aF+jxk2lGJFtgLvfoxFOvGckwCSy8T",
|
||||
"/MCiJZkz01hWo5s2VCLJheWL/GqTKjS5wXDcm+y8Wtilh+UawycdlDsSNr/D4MZL",
|
||||
"j3Chq9K03l5UIR8DcC7SavNi55R2oGOfboXsdvwOlrNZdCkZOlXDI4ZKFwbDHCtp",
|
||||
"Do5FS30hnJi2TecUPZWB1CaGFWnevINd4ikugVjcAoZj/QAIvfrOCgqisF/Ylg9u",
|
||||
"RMUPBapmcJUueILwd0iQqvGG0aCqtchvSmlg15/lQQQA9G1NNjNAH+NQrXvDJFJe",
|
||||
"/V1U3F3pz7jCjQa69c0dxSBUeNX1pG8XXD6tSkkd4Ni1mzZGcZXOmVUM6cA9I7RH",
|
||||
"95RqV+QIfnXVneCRrlCjV8m6OBlkivkESXc3nW5wtCIfw7oKg9w1xuVNUaAlbCt9",
|
||||
"QVLaxXJiY7ad0f5U9XJ1+w8EAPFs+M/+GZK1wOZYBL1vo7x0gL9ZggmjC4B+viBJ",
|
||||
"8Q60mqTrphYFsbXHuwKV0g9aIoZMucKyEE0QLR7imttiLEz1nD8bfEScbGy9ZG//",
|
||||
"wRfyJmCVAjA0pQ6LtB93d70PSVzzJrMHgbLKrDuSd6RChl7n9BIEdVyk7LEph0Yg",
|
||||
"9UsRBADm6DvpKL+P3lQ0eLTfAgcQTOqLZDYmI3PvqqSkHb1kHChqOXXs8hGOSSwK",
|
||||
"Gjcd4CZeNOGWR42rZyRhVgtkt6iYviIaVAWUfme6K+sLQBCeyMlmEGtykAA+LmPB",
|
||||
"f4zdyUNADfoxgZF3EKHf6I3nlVn5cdT+o/9vjdY2XAOwcls1RzaFwsB2BBgBCAAg",
|
||||
"BQJdPOn4AhsMFiEE+iaix4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcegLxwf/",
|
||||
"dXshJnoWqEnRsf6rVb9/Mc66ti+NVQLfNd275dybh/QIJdK3NmSxdnTPIEJRVspJ",
|
||||
"ywJoupwXFNrnHG2Ff6QPvHqI+/oNu986r9d7Z1oQibbLHKt8t6kpOfg/xGxotagJ",
|
||||
"uiCQvR9mMjD1DqsdB37SjDxGupZOOJSXWi6KX60IE+uM+QOBfeOZziQwuFmA5wV6",
|
||||
"RDXIeYJfqrcbeXeR1d0nfNpPHQR1gBiqmxNb6KBbdXD2+EXW60axC7D2b1APmzMl",
|
||||
"ammDliPwsK9U1rc9nuquEBvGDOJf4K+Dzn+mDCqRpP6uAuQ7RKHyim4uyN0wwKOb",
|
||||
"zPqgJCGwjTglkixw+aSTXw=="
|
||||
),
|
||||
KeyType::Private,
|
||||
)
|
||||
.unwrap();
|
||||
let saved = key::dc_key_save_self_keypair(
|
||||
&ctx,
|
||||
&public,
|
||||
&private,
|
||||
"alice@example.org",
|
||||
1,
|
||||
&ctx.sql,
|
||||
);
|
||||
assert_eq!(saved, true, "Failed to save Alice's key");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_render_setup_file() {
|
||||
let t = test_context(Some(logging_cb));
|
||||
|
||||
configure_alice_keypair(&t.ctx);
|
||||
create_alice_keypair(&t.ctx); // Trick things to think we're configured.
|
||||
let msg = dc_render_setup_file(&t.ctx, "hello").unwrap();
|
||||
println!("{}", &msg);
|
||||
// Check some substrings, indicating things got substituted.
|
||||
@@ -1202,7 +1456,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_render_setup_file_newline_replace() {
|
||||
let t = test_context(Some(ac_setup_msg_cb));
|
||||
configure_alice_keypair(&t.ctx);
|
||||
create_alice_keypair(&t.ctx);
|
||||
let msg = dc_render_setup_file(&t.ctx, "pw").unwrap();
|
||||
println!("{}", &msg);
|
||||
assert!(msg.contains("<p>hello<br>there</p>"));
|
||||
|
||||
550
src/dc_job.rs
550
src/dc_job.rs
@@ -1,7 +1,6 @@
|
||||
use mmime::mmapstring::*;
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::ptr;
|
||||
use std::time::Duration;
|
||||
|
||||
use rand::{thread_rng, Rng};
|
||||
@@ -102,8 +101,10 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network:
|
||||
Ok(job)
|
||||
},
|
||||
|jobs| {
|
||||
jobs.collect::<Result<Vec<dc_job_t>, _>>()
|
||||
.map_err(Into::into)
|
||||
let res = jobs
|
||||
.collect::<Result<Vec<dc_job_t>, _>>()
|
||||
.map_err(Into::into);
|
||||
res
|
||||
},
|
||||
);
|
||||
match jobs {
|
||||
@@ -291,9 +292,9 @@ unsafe fn dc_suspend_smtp_thread(context: &Context, suspend: bool) {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) {
|
||||
let ok_to_continue;
|
||||
let mut current_block: u64;
|
||||
let mut filename: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut buf: *mut libc::c_void = ptr::null_mut();
|
||||
let mut buf: *mut libc::c_void = 0 as *mut libc::c_void;
|
||||
let mut buf_bytes: size_t = 0i32 as size_t;
|
||||
|
||||
/* connect to SMTP server, if not yet done */
|
||||
@@ -302,87 +303,101 @@ unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) {
|
||||
let connected = context.smtp.lock().unwrap().connect(context, &loginparam);
|
||||
|
||||
if !connected {
|
||||
dc_job_try_again_later(job, 3i32, ptr::null());
|
||||
ok_to_continue = false;
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
current_block = 14216916617354591294;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 13109137661213826276;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 13109137661213826276;
|
||||
}
|
||||
if ok_to_continue {
|
||||
let filename_s = job.param.get(Param::File).unwrap_or_default();
|
||||
filename = filename_s.strdup();
|
||||
if strlen(filename) == 0 {
|
||||
warn!(context, 0, "Missing file name for job {}", job.job_id,);
|
||||
} else if !(0 == dc_read_file(context, filename, &mut buf, &mut buf_bytes)) {
|
||||
let recipients = job.param.get(Param::Recipients);
|
||||
if recipients.is_none() {
|
||||
warn!(context, 0, "Missing recipients for job {}", job.job_id,);
|
||||
} else {
|
||||
let recipients_list = recipients
|
||||
.unwrap()
|
||||
.split("\x1e")
|
||||
.filter_map(|addr| match lettre::EmailAddress::new(addr.to_string()) {
|
||||
Ok(addr) => Some(addr),
|
||||
Err(err) => {
|
||||
eprintln!("WARNING: invalid recipient: {} {:?}", addr, err);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
/* if there is a msg-id and it does not exist in the db, cancel sending.
|
||||
this happends if dc_delete_msgs() was called
|
||||
before the generated mime was sent out */
|
||||
let ok_to_continue1;
|
||||
if 0 != job.foreign_id {
|
||||
if 0 == dc_msg_exists(context, job.foreign_id) {
|
||||
warn!(
|
||||
context,
|
||||
0, "Message {} for job {} does not exist", job.foreign_id, job.job_id,
|
||||
);
|
||||
ok_to_continue1 = false;
|
||||
} else {
|
||||
ok_to_continue1 = true;
|
||||
}
|
||||
match current_block {
|
||||
13109137661213826276 => {
|
||||
filename = job.param.get(Param::File).unwrap_or_default().strdup();
|
||||
if strlen(filename) == 0 {
|
||||
warn!(context, 0, "Missing file name for job {}", job.job_id,);
|
||||
} else if !(0 == dc_read_file(context, filename, &mut buf, &mut buf_bytes)) {
|
||||
let recipients = job.param.get(Param::Recipients);
|
||||
if recipients.is_none() {
|
||||
warn!(context, 0, "Missing recipients for job {}", job.job_id,);
|
||||
} else {
|
||||
ok_to_continue1 = true;
|
||||
}
|
||||
if ok_to_continue1 {
|
||||
/* send message */
|
||||
let body = std::slice::from_raw_parts(buf as *const u8, buf_bytes).to_vec();
|
||||
|
||||
// hold the smtp lock during sending of a job and
|
||||
// its ok/error response processing. Note that if a message
|
||||
// was sent we need to mark it in the database as we
|
||||
// otherwise might send it twice.
|
||||
let mut sock = context.smtp.lock().unwrap();
|
||||
if 0 == sock.send(context, recipients_list, body) {
|
||||
sock.disconnect();
|
||||
dc_job_try_again_later(job, -1i32, sock.error);
|
||||
} else {
|
||||
dc_delete_file(context, filename_s);
|
||||
if 0 != job.foreign_id {
|
||||
dc_update_msg_state(context, job.foreign_id, DC_STATE_OUT_DELIVERED);
|
||||
let chat_id: i32 = context
|
||||
.sql
|
||||
.query_row_col(
|
||||
context,
|
||||
"SELECT chat_id FROM msgs WHERE id=?",
|
||||
params![job.foreign_id as i32],
|
||||
0,
|
||||
)
|
||||
.unwrap_or_default();
|
||||
context.call_cb(
|
||||
Event::MSG_DELIVERED,
|
||||
chat_id as uintptr_t,
|
||||
job.foreign_id as uintptr_t,
|
||||
let recipients_list = recipients
|
||||
.unwrap()
|
||||
.split("\x1e")
|
||||
.filter_map(|addr| match lettre::EmailAddress::new(addr.to_string()) {
|
||||
Ok(addr) => Some(addr),
|
||||
Err(err) => {
|
||||
eprintln!("WARNING: invalid recipient: {} {:?}", addr, err);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
/* if there is a msg-id and it does not exist in the db, cancel sending.
|
||||
this happends if dc_delete_msgs() was called
|
||||
before the generated mime was sent out */
|
||||
if 0 != job.foreign_id {
|
||||
if 0 == dc_msg_exists(context, job.foreign_id) {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Message {} for job {} does not exist",
|
||||
job.foreign_id,
|
||||
job.job_id,
|
||||
);
|
||||
current_block = 14216916617354591294;
|
||||
} else {
|
||||
current_block = 11194104282611034094;
|
||||
}
|
||||
} else {
|
||||
current_block = 11194104282611034094;
|
||||
}
|
||||
match current_block {
|
||||
14216916617354591294 => {}
|
||||
_ => {
|
||||
/* send message */
|
||||
let body =
|
||||
std::slice::from_raw_parts(buf as *const u8, buf_bytes).to_vec();
|
||||
if 0 == context.smtp.lock().unwrap().send(
|
||||
context,
|
||||
recipients_list,
|
||||
body,
|
||||
) {
|
||||
context.smtp.lock().unwrap().disconnect();
|
||||
dc_job_try_again_later(
|
||||
job,
|
||||
-1i32,
|
||||
(*&mut context.smtp.clone().lock().unwrap()).error,
|
||||
);
|
||||
} else {
|
||||
dc_delete_file(context, filename);
|
||||
if 0 != job.foreign_id {
|
||||
dc_update_msg_state(
|
||||
context,
|
||||
job.foreign_id,
|
||||
DC_STATE_OUT_DELIVERED,
|
||||
);
|
||||
let chat_id: i32 = context
|
||||
.sql
|
||||
.query_row_col(
|
||||
context,
|
||||
"SELECT chat_id FROM msgs WHERE id=?",
|
||||
params![job.foreign_id as i32],
|
||||
0,
|
||||
)
|
||||
.unwrap_or_default();
|
||||
context.call_cb(
|
||||
Event::MSG_DELIVERED,
|
||||
chat_id as uintptr_t,
|
||||
job.foreign_id as uintptr_t,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
free(buf);
|
||||
free(filename as *mut libc::c_void);
|
||||
@@ -401,7 +416,7 @@ pub unsafe fn dc_job_try_again_later(
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn dc_job_do_DC_JOB_MOVE_MSG(context: &Context, job: &mut dc_job_t) {
|
||||
let ok_to_continue;
|
||||
let mut current_block: u64;
|
||||
let msg = dc_msg_new_untyped(context);
|
||||
let mut dest_uid: uint32_t = 0i32 as uint32_t;
|
||||
|
||||
@@ -410,47 +425,76 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(context: &Context, job: &mut dc_job_t) {
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
dc_job_try_again_later(job, 3i32, ptr::null());
|
||||
ok_to_continue = false;
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
current_block = 2238328302157162973;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 2473556513754201174;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 2473556513754201174;
|
||||
}
|
||||
if ok_to_continue {
|
||||
if dc_msg_load_from_db(msg, context, job.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();
|
||||
|
||||
match inbox.mv(
|
||||
context,
|
||||
server_folder,
|
||||
(*msg).server_uid,
|
||||
&dest_folder,
|
||||
&mut dest_uid,
|
||||
) as libc::c_uint
|
||||
match current_block {
|
||||
2473556513754201174 => {
|
||||
if dc_msg_load_from_db(msg, context, job.foreign_id) {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
1 => {
|
||||
dc_job_try_again_later(job, 3i32, ptr::null());
|
||||
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 = as_str((*msg).server_folder);
|
||||
|
||||
match inbox.mv(
|
||||
context,
|
||||
server_folder,
|
||||
(*msg).server_uid,
|
||||
&dest_folder,
|
||||
&mut dest_uid,
|
||||
) as libc::c_uint
|
||||
{
|
||||
1 => {
|
||||
current_block = 6379107252614456477;
|
||||
match current_block {
|
||||
12072121998757195963 => {
|
||||
dc_update_server_uid(
|
||||
context,
|
||||
(*msg).rfc724_mid,
|
||||
&dest_folder,
|
||||
dest_uid,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
current_block = 12072121998757195963;
|
||||
match current_block {
|
||||
12072121998757195963 => {
|
||||
dc_update_server_uid(
|
||||
context,
|
||||
(*msg).rfc724_mid,
|
||||
&dest_folder,
|
||||
dest_uid,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
0 | 2 | _ => {}
|
||||
}
|
||||
3 => {
|
||||
dc_update_server_uid(context, (*msg).rfc724_mid, &dest_folder, dest_uid);
|
||||
}
|
||||
0 | 2 | _ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
dc_msg_unref(msg);
|
||||
@@ -469,7 +513,7 @@ fn connect_to_inbox(context: &Context, inbox: &Imap) -> libc::c_int {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context: &Context, job: &mut dc_job_t) {
|
||||
let ok_to_continue;
|
||||
let current_block: u64;
|
||||
let folder = job
|
||||
.param
|
||||
.get(Param::ServerFolder)
|
||||
@@ -482,109 +526,202 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context: &Context, job: &mut dc_
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
dc_job_try_again_later(job, 3, ptr::null());
|
||||
ok_to_continue = false;
|
||||
dc_job_try_again_later(job, 3, 0 as *const libc::c_char);
|
||||
current_block = 2670689566614003383;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 11006700562992250127;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 11006700562992250127;
|
||||
}
|
||||
if ok_to_continue {
|
||||
if inbox.set_seen(context, &folder, uid) == 0 {
|
||||
dc_job_try_again_later(job, 3i32, ptr::null());
|
||||
}
|
||||
if 0 != job.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);
|
||||
match current_block {
|
||||
11006700562992250127 => {
|
||||
if inbox.set_seen(context, &folder, uid) == 0 {
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
if 1 == inbox.mv(context, folder, uid, dest_folder, &mut dest_uid) as libc::c_uint {
|
||||
dc_job_try_again_later(job, 3, 0 as *const libc::c_char);
|
||||
if 0 != job.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);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
if 1 == inbox.mv(context, folder, uid, dest_folder, &mut dest_uid)
|
||||
as libc::c_uint
|
||||
{
|
||||
dc_job_try_again_later(job, 3, 0 as *const libc::c_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_job_t) {
|
||||
let ok_to_continue;
|
||||
let mut current_block: u64;
|
||||
let msg: *mut dc_msg_t = dc_msg_new_untyped(context);
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
dc_job_try_again_later(job, 3i32, ptr::null());
|
||||
ok_to_continue = false;
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
current_block = 17792648348530113339;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 15240798224410183470;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 15240798224410183470;
|
||||
}
|
||||
if ok_to_continue {
|
||||
if dc_msg_load_from_db(msg, context, job.foreign_id) {
|
||||
let server_folder = (*msg).server_folder.as_ref().unwrap();
|
||||
match inbox.set_seen(context, server_folder, (*msg).server_uid) as libc::c_uint {
|
||||
0 => {}
|
||||
1 => {
|
||||
dc_job_try_again_later(job, 3i32, ptr::null());
|
||||
}
|
||||
_ => {
|
||||
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) as libc::c_uint
|
||||
{
|
||||
1 => {
|
||||
match current_block {
|
||||
15240798224410183470 => {
|
||||
if dc_msg_load_from_db(msg, context, job.foreign_id) {
|
||||
let server_folder = CStr::from_ptr((*msg).server_folder).to_str().unwrap();
|
||||
match inbox.set_seen(context, server_folder, (*msg).server_uid) as libc::c_uint {
|
||||
0 => {}
|
||||
1 => {
|
||||
current_block = 12392248546350854223;
|
||||
match current_block {
|
||||
12392248546350854223 => {
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
}
|
||||
3 => {
|
||||
dc_send_mdn(context, (*msg).id);
|
||||
_ => {
|
||||
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 =
|
||||
CStr::from_ptr((*msg).server_folder).to_str().unwrap();
|
||||
match inbox.set_mdnsent(context, folder, (*msg).server_uid)
|
||||
as libc::c_uint
|
||||
{
|
||||
1 => {
|
||||
current_block = 4016212065805849280;
|
||||
match current_block {
|
||||
6186957421461061791 => {
|
||||
dc_send_mdn(context, (*msg).id);
|
||||
}
|
||||
_ => {
|
||||
dc_job_try_again_later(
|
||||
job,
|
||||
3i32,
|
||||
0 as *const libc::c_char,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
current_block = 6186957421461061791;
|
||||
match current_block {
|
||||
6186957421461061791 => {
|
||||
dc_send_mdn(context, (*msg).id);
|
||||
}
|
||||
_ => {
|
||||
dc_job_try_again_later(
|
||||
job,
|
||||
3i32,
|
||||
0 as *const libc::c_char,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
0 | 2 | _ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
current_block = 7746791466490516765;
|
||||
match current_block {
|
||||
12392248546350854223 => {
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
}
|
||||
_ => {
|
||||
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 =
|
||||
CStr::from_ptr((*msg).server_folder).to_str().unwrap();
|
||||
|
||||
match inbox.set_mdnsent(context, folder, (*msg).server_uid)
|
||||
as libc::c_uint
|
||||
{
|
||||
1 => {
|
||||
current_block = 4016212065805849280;
|
||||
match current_block {
|
||||
6186957421461061791 => {
|
||||
dc_send_mdn(context, (*msg).id);
|
||||
}
|
||||
_ => {
|
||||
dc_job_try_again_later(
|
||||
job,
|
||||
3i32,
|
||||
0 as *const libc::c_char,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
current_block = 6186957421461061791;
|
||||
match current_block {
|
||||
6186957421461061791 => {
|
||||
dc_send_mdn(context, (*msg).id);
|
||||
}
|
||||
_ => {
|
||||
dc_job_try_again_later(
|
||||
job,
|
||||
3i32,
|
||||
0 as *const libc::c_char,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
0 | 2 | _ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
0 | 2 | _ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
unsafe fn dc_send_mdn(context: &Context, msg_id: uint32_t) {
|
||||
let mut mimefactory: dc_mimefactory_t = dc_mimefactory_t {
|
||||
from_addr: ptr::null_mut(),
|
||||
from_displayname: ptr::null_mut(),
|
||||
selfstatus: ptr::null_mut(),
|
||||
recipients_names: ptr::null_mut(),
|
||||
recipients_addr: ptr::null_mut(),
|
||||
from_addr: 0 as *mut libc::c_char,
|
||||
from_displayname: 0 as *mut libc::c_char,
|
||||
selfstatus: 0 as *mut libc::c_char,
|
||||
recipients_names: 0 as *mut clist,
|
||||
recipients_addr: 0 as *mut clist,
|
||||
timestamp: 0,
|
||||
rfc724_mid: ptr::null_mut(),
|
||||
rfc724_mid: 0 as *mut libc::c_char,
|
||||
loaded: DC_MF_NOTHING_LOADED,
|
||||
msg: ptr::null_mut(),
|
||||
chat: ptr::null_mut(),
|
||||
msg: 0 as *mut dc_msg_t,
|
||||
chat: 0 as *mut Chat,
|
||||
increation: 0,
|
||||
in_reply_to: ptr::null_mut(),
|
||||
references: ptr::null_mut(),
|
||||
in_reply_to: 0 as *mut libc::c_char,
|
||||
references: 0 as *mut libc::c_char,
|
||||
req_mdn: 0,
|
||||
out: ptr::null_mut(),
|
||||
out: 0 as *mut MMAPString,
|
||||
out_encrypted: 0,
|
||||
out_gossiped: 0,
|
||||
out_last_added_location_id: 0,
|
||||
error: ptr::null_mut(),
|
||||
error: 0 as *mut libc::c_char,
|
||||
context,
|
||||
};
|
||||
dc_mimefactory_init(&mut mimefactory, context);
|
||||
@@ -667,7 +804,7 @@ unsafe fn dc_add_smtp_job(
|
||||
}
|
||||
free(recipients as *mut libc::c_void);
|
||||
free(pathNfilename as *mut libc::c_void);
|
||||
success
|
||||
return success;
|
||||
}
|
||||
|
||||
pub unsafe fn dc_job_add(
|
||||
@@ -727,6 +864,7 @@ pub unsafe fn dc_interrupt_imap_idle(context: &Context) {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context: &Context, job: &mut dc_job_t) {
|
||||
let mut current_block: u64;
|
||||
let mut delete_from_server: libc::c_int = 1i32;
|
||||
let msg: *mut dc_msg_t = dc_msg_new_untyped(context);
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
@@ -735,7 +873,6 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context: &Context, job: &mut dc_jo
|
||||
|| (*msg).rfc724_mid.is_null()
|
||||
|| *(*msg).rfc724_mid.offset(0isize) as libc::c_int == 0i32)
|
||||
{
|
||||
let ok_to_continue1;
|
||||
/* eg. device messages have no Message-ID */
|
||||
if dc_rfc724_mid_cnt(context, (*msg).rfc724_mid) != 1i32 {
|
||||
info!(
|
||||
@@ -746,35 +883,38 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context: &Context, job: &mut dc_jo
|
||||
}
|
||||
/* if this is the last existing part of the message, we delete the message from the server */
|
||||
if 0 != delete_from_server {
|
||||
let ok_to_continue;
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||
ok_to_continue = false;
|
||||
current_block = 8913536887710889399;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 5399440093318478209;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
current_block = 5399440093318478209;
|
||||
}
|
||||
if ok_to_continue {
|
||||
let mid = CStr::from_ptr((*msg).rfc724_mid).to_str().unwrap();
|
||||
let server_folder = (*msg).server_folder.as_ref().unwrap();
|
||||
if 0 == inbox.delete_msg(context, mid, server_folder, &mut (*msg).server_uid) {
|
||||
dc_job_try_again_later(job, -1i32, 0 as *const libc::c_char);
|
||||
ok_to_continue1 = false;
|
||||
} else {
|
||||
ok_to_continue1 = true;
|
||||
match current_block {
|
||||
8913536887710889399 => {}
|
||||
_ => {
|
||||
let mid = CStr::from_ptr((*msg).rfc724_mid).to_str().unwrap();
|
||||
let server_folder = CStr::from_ptr((*msg).server_folder).to_str().unwrap();
|
||||
if 0 == inbox.delete_msg(context, mid, server_folder, &mut (*msg).server_uid) {
|
||||
dc_job_try_again_later(job, -1i32, 0 as *const libc::c_char);
|
||||
current_block = 8913536887710889399;
|
||||
} else {
|
||||
current_block = 17407779659766490442;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ok_to_continue1 = false;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue1 = true;
|
||||
current_block = 17407779659766490442;
|
||||
}
|
||||
if ok_to_continue1 {
|
||||
dc_delete_msg_from_db(context, (*msg).id);
|
||||
match current_block {
|
||||
8913536887710889399 => {}
|
||||
_ => {
|
||||
dc_delete_msg_from_db(context, (*msg).id);
|
||||
}
|
||||
}
|
||||
}
|
||||
dc_msg_unref(msg);
|
||||
@@ -1036,25 +1176,43 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in
|
||||
} else {
|
||||
// no redo, no IMAP. moreover, as the data does not exist, there is no need in calling dc_set_msg_failed()
|
||||
if msgtype_has_file((*mimefactory.msg).type_0) {
|
||||
if let Some(pathNfilename) = (*mimefactory.msg).param.get(Param::File) {
|
||||
let pathNfilename = (*mimefactory.msg)
|
||||
.param
|
||||
.get(Param::File)
|
||||
.unwrap_or_default()
|
||||
.strdup();
|
||||
if strlen(pathNfilename) > 0 {
|
||||
if ((*mimefactory.msg).type_0 == Viewtype::Image
|
||||
|| (*mimefactory.msg).type_0 == Viewtype::Gif)
|
||||
&& !(*mimefactory.msg).param.exists(Param::Width)
|
||||
{
|
||||
let mut buf = 0 as *mut libc::c_uchar;
|
||||
let mut buf_bytes: size_t = 0;
|
||||
let mut w = 0;
|
||||
let mut h = 0;
|
||||
(*mimefactory.msg).param.set_int(Param::Width, 0);
|
||||
(*mimefactory.msg).param.set_int(Param::Height, 0);
|
||||
|
||||
if let Some(buf) = dc_read_file_safe(context, pathNfilename) {
|
||||
if let Ok((width, height)) = dc_get_filemeta(&buf) {
|
||||
(*mimefactory.msg).param.set_int(Param::Width, width as i32);
|
||||
(*mimefactory.msg)
|
||||
.param
|
||||
.set_int(Param::Height, height as i32);
|
||||
if 0 != dc_read_file(
|
||||
context,
|
||||
pathNfilename,
|
||||
&mut buf as *mut *mut libc::c_uchar as *mut *mut libc::c_void,
|
||||
&mut buf_bytes,
|
||||
) {
|
||||
if 0 != dc_get_filemeta(
|
||||
buf as *const libc::c_void,
|
||||
buf_bytes,
|
||||
&mut w,
|
||||
&mut h,
|
||||
) {
|
||||
(*mimefactory.msg).param.set_int(Param::Width, w as i32);
|
||||
(*mimefactory.msg).param.set_int(Param::Height, h as i32);
|
||||
}
|
||||
}
|
||||
free(buf as *mut libc::c_void);
|
||||
dc_msg_save_param_to_disk(mimefactory.msg);
|
||||
}
|
||||
}
|
||||
free(pathNfilename as *mut libc::c_void);
|
||||
}
|
||||
/* create message */
|
||||
if 0 == dc_mimefactory_render(&mut mimefactory) {
|
||||
|
||||
@@ -239,10 +239,10 @@ pub fn dc_get_locations(
|
||||
accuracy: row.get(3)?,
|
||||
timestamp: row.get(4)?,
|
||||
independent: row.get(5)?,
|
||||
msg_id,
|
||||
msg_id: msg_id,
|
||||
contact_id: row.get(7)?,
|
||||
chat_id: row.get(8)?,
|
||||
marker,
|
||||
marker: marker,
|
||||
};
|
||||
Ok(loc)
|
||||
},
|
||||
|
||||
@@ -6,11 +6,14 @@ use crate::dc_tools::*;
|
||||
use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
/* * Structure behind dc_lot_t */
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct dc_lot_t {
|
||||
pub magic: uint32_t,
|
||||
pub text1_meaning: libc::c_int,
|
||||
pub text1: *mut libc::c_char,
|
||||
pub text2: *mut libc::c_char,
|
||||
@@ -37,13 +40,14 @@ pub unsafe fn dc_lot_new() -> *mut dc_lot_t {
|
||||
lot = calloc(1, ::std::mem::size_of::<dc_lot_t>()) as *mut dc_lot_t;
|
||||
assert!(!lot.is_null());
|
||||
|
||||
(*lot).magic = 0x107107i32 as uint32_t;
|
||||
(*lot).text1_meaning = 0i32;
|
||||
|
||||
lot
|
||||
}
|
||||
|
||||
pub unsafe fn dc_lot_empty(mut lot: *mut dc_lot_t) {
|
||||
if lot.is_null() {
|
||||
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
|
||||
return;
|
||||
}
|
||||
free((*lot).text1 as *mut libc::c_void);
|
||||
@@ -62,16 +66,17 @@ pub unsafe fn dc_lot_empty(mut lot: *mut dc_lot_t) {
|
||||
(*lot).id = 0i32 as uint32_t;
|
||||
}
|
||||
|
||||
pub unsafe fn dc_lot_unref(set: *mut dc_lot_t) {
|
||||
if set.is_null() {
|
||||
pub unsafe fn dc_lot_unref(mut set: *mut dc_lot_t) {
|
||||
if set.is_null() || (*set).magic != 0x107107i32 as libc::c_uint {
|
||||
return;
|
||||
}
|
||||
dc_lot_empty(set);
|
||||
(*set).magic = 0i32 as uint32_t;
|
||||
free(set as *mut libc::c_void);
|
||||
}
|
||||
|
||||
pub unsafe fn dc_lot_get_text1(lot: *const dc_lot_t) -> *mut libc::c_char {
|
||||
if lot.is_null() {
|
||||
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
|
||||
return 0 as *mut libc::c_char;
|
||||
}
|
||||
|
||||
@@ -79,7 +84,7 @@ pub unsafe fn dc_lot_get_text1(lot: *const dc_lot_t) -> *mut libc::c_char {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_lot_get_text2(lot: *const dc_lot_t) -> *mut libc::c_char {
|
||||
if lot.is_null() {
|
||||
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
|
||||
return 0 as *mut libc::c_char;
|
||||
}
|
||||
|
||||
@@ -87,7 +92,7 @@ pub unsafe fn dc_lot_get_text2(lot: *const dc_lot_t) -> *mut libc::c_char {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_lot_get_text1_meaning(lot: *const dc_lot_t) -> libc::c_int {
|
||||
if lot.is_null() {
|
||||
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
|
||||
return 0i32;
|
||||
}
|
||||
|
||||
@@ -95,7 +100,7 @@ pub unsafe fn dc_lot_get_text1_meaning(lot: *const dc_lot_t) -> libc::c_int {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_lot_get_state(lot: *const dc_lot_t) -> libc::c_int {
|
||||
if lot.is_null() {
|
||||
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
|
||||
return 0i32;
|
||||
}
|
||||
|
||||
@@ -103,7 +108,7 @@ pub unsafe fn dc_lot_get_state(lot: *const dc_lot_t) -> libc::c_int {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_lot_get_id(lot: *const dc_lot_t) -> uint32_t {
|
||||
if lot.is_null() {
|
||||
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
|
||||
return 0i32 as uint32_t;
|
||||
}
|
||||
|
||||
@@ -111,7 +116,7 @@ pub unsafe fn dc_lot_get_id(lot: *const dc_lot_t) -> uint32_t {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_lot_get_timestamp(lot: *const dc_lot_t) -> i64 {
|
||||
if lot.is_null() {
|
||||
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -127,7 +132,7 @@ pub unsafe fn dc_lot_fill(
|
||||
contact: Option<&Contact>,
|
||||
context: &Context,
|
||||
) {
|
||||
if lot.is_null() || msg.is_null() {
|
||||
if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint || msg.is_null() {
|
||||
return;
|
||||
}
|
||||
if (*msg).state == 19i32 {
|
||||
@@ -166,15 +171,14 @@ pub unsafe fn dc_lot_fill(
|
||||
}
|
||||
}
|
||||
|
||||
let message_text = (*msg).text.as_ref().unwrap();
|
||||
let msgtext_c = (*msg)
|
||||
.text
|
||||
.as_ref()
|
||||
.map(|s| CString::yolo(String::as_str(s)));
|
||||
let msgtext_ptr = msgtext_c.map_or(ptr::null(), |s| s.as_ptr());
|
||||
|
||||
(*lot).text2 = dc_msg_get_summarytext_by_raw(
|
||||
(*msg).type_0,
|
||||
message_text.strdup(),
|
||||
&mut (*msg).param,
|
||||
160,
|
||||
context,
|
||||
);
|
||||
(*lot).text2 =
|
||||
dc_msg_get_summarytext_by_raw((*msg).type_0, msgtext_ptr, &mut (*msg).param, 160, context);
|
||||
|
||||
(*lot).timestamp = dc_msg_get_timestamp(msg);
|
||||
(*lot).state = (*msg).state;
|
||||
|
||||
@@ -13,7 +13,7 @@ use std::ptr;
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::{dc_get_version_str, Context};
|
||||
use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_location::*;
|
||||
@@ -478,19 +478,18 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
.map(|s| format!("/{}", s))
|
||||
.unwrap_or_default();
|
||||
let os_part = CString::new(os_part).expect("String -> CString conversion failed");
|
||||
let version = dc_get_version_str();
|
||||
|
||||
mailimf_fields_add(
|
||||
imf_fields,
|
||||
mailimf_field_new_custom(
|
||||
strdup(b"X-Mailer\x00" as *const u8 as *const libc::c_char),
|
||||
dc_mprintf(
|
||||
b"Delta Chat Core %s%s\x00" as *const u8 as *const libc::c_char,
|
||||
version,
|
||||
DC_VERSION_STR as *const u8 as *const libc::c_char,
|
||||
os_part.as_ptr(),
|
||||
),
|
||||
),
|
||||
);
|
||||
free(version.cast());
|
||||
|
||||
mailimf_fields_add(
|
||||
imf_fields,
|
||||
@@ -961,14 +960,12 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
message_text = format!("{}\r\n", p2).strdup();
|
||||
let human_mime_part: *mut mailmime = build_body_text(message_text);
|
||||
mailmime_add_part(multipart, human_mime_part);
|
||||
let version = dc_get_version_str();
|
||||
message_text2 =
|
||||
dc_mprintf(b"Reporting-UA: Delta Chat %s\r\nOriginal-Recipient: rfc822;%s\r\nFinal-Recipient: rfc822;%s\r\nOriginal-Message-ID: <%s>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n\x00"
|
||||
as *const u8 as *const libc::c_char,
|
||||
version,
|
||||
DC_VERSION_STR as *const u8 as *const libc::c_char,
|
||||
(*factory).from_addr, (*factory).from_addr,
|
||||
(*(*factory).msg).rfc724_mid);
|
||||
free(version.cast());
|
||||
let content_type_0: *mut mailmime_content = mailmime_content_new_with_str(
|
||||
b"message/disposition-notification\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
@@ -1314,14 +1311,16 @@ unsafe fn build_body_file(
|
||||
/*******************************************************************************
|
||||
* Render
|
||||
******************************************************************************/
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn is_file_size_okay(msg: *const dc_msg_t) -> bool {
|
||||
let mut file_size_okay = true;
|
||||
let path = (*msg).param.get(Param::File).unwrap_or_default();
|
||||
let bytes = dc_get_filebytes((*msg).context, &path);
|
||||
let pathNfilename = (*msg).param.get(Param::File).unwrap_or_default().strdup();
|
||||
let bytes = dc_get_filebytes((*msg).context, pathNfilename);
|
||||
|
||||
if bytes > (49 * 1024 * 1024 / 4 * 3) {
|
||||
file_size_okay = false;
|
||||
}
|
||||
free(pathNfilename as *mut _);
|
||||
|
||||
file_size_okay
|
||||
}
|
||||
|
||||
@@ -161,7 +161,12 @@ pub unsafe fn dc_mimeparser_parse(
|
||||
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int {
|
||||
mimeparser.subject = dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value)
|
||||
}
|
||||
if !dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Version").is_null() {
|
||||
if !dc_mimeparser_lookup_optional_field(
|
||||
mimeparser,
|
||||
b"Chat-Version\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
.is_null()
|
||||
{
|
||||
mimeparser.is_send_by_messenger = 1i32
|
||||
}
|
||||
if !dc_mimeparser_lookup_field(mimeparser, "Autocrypt-Setup-Message").is_null() {
|
||||
@@ -196,7 +201,10 @@ pub unsafe fn dc_mimeparser_parse(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
optional_field = dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Content");
|
||||
optional_field = dc_mimeparser_lookup_optional_field(
|
||||
mimeparser,
|
||||
b"Chat-Content\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
if !optional_field.is_null() && !(*optional_field).fld_value.is_null() {
|
||||
if strcmp(
|
||||
(*optional_field).fld_value,
|
||||
@@ -304,7 +312,11 @@ pub unsafe fn dc_mimeparser_parse(
|
||||
}
|
||||
if mimeparser.parts.len() == 1 {
|
||||
if mimeparser.parts[0].type_0 == 40i32 {
|
||||
if !dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Voice-Message").is_null()
|
||||
if !dc_mimeparser_lookup_optional_field(
|
||||
mimeparser,
|
||||
b"Chat-Voice-Message\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
.is_null()
|
||||
{
|
||||
let part_mut = &mut mimeparser.parts[0];
|
||||
part_mut.type_0 = 41i32
|
||||
@@ -312,7 +324,10 @@ pub unsafe fn dc_mimeparser_parse(
|
||||
}
|
||||
let part = &mimeparser.parts[0];
|
||||
if part.type_0 == 40i32 || part.type_0 == 41i32 || part.type_0 == 50i32 {
|
||||
let field_0 = dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Duration");
|
||||
let field_0 = dc_mimeparser_lookup_optional_field(
|
||||
mimeparser,
|
||||
b"Chat-Duration\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
if !field_0.is_null() {
|
||||
let duration_ms: libc::c_int = dc_atoi_null_is_0((*field_0).fld_value);
|
||||
if duration_ms > 0i32 && duration_ms < 24i32 * 60i32 * 60i32 * 1000i32 {
|
||||
@@ -323,8 +338,10 @@ pub unsafe fn dc_mimeparser_parse(
|
||||
}
|
||||
}
|
||||
if 0 == mimeparser.decrypting_failed {
|
||||
let dn_field: *const mailimf_optional_field =
|
||||
dc_mimeparser_lookup_optional_field(mimeparser, "Chat-Disposition-Notification-To");
|
||||
let dn_field: *const mailimf_optional_field = dc_mimeparser_lookup_optional_field(
|
||||
mimeparser,
|
||||
b"Chat-Disposition-Notification-To\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
if !dn_field.is_null() && dc_mimeparser_get_last_nonmeta(mimeparser).is_some() {
|
||||
let mut mb_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list;
|
||||
let mut index_0: size_t = 0i32 as size_t;
|
||||
@@ -442,11 +459,11 @@ pub fn dc_mimeparser_lookup_field(
|
||||
|
||||
pub unsafe fn dc_mimeparser_lookup_optional_field(
|
||||
mimeparser: &dc_mimeparser_t,
|
||||
field_name: &str,
|
||||
field_name: *const libc::c_char,
|
||||
) -> *mut mailimf_optional_field {
|
||||
let field = mimeparser
|
||||
.header
|
||||
.get(field_name)
|
||||
.get(as_str(field_name))
|
||||
.map(|v| *v)
|
||||
.unwrap_or_else(|| std::ptr::null_mut());
|
||||
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int {
|
||||
@@ -1095,7 +1112,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
|
||||
/* must not be free()'d */
|
||||
let mut decoded_data: *const libc::c_char = 0 as *const libc::c_char;
|
||||
let mut decoded_data_bytes = 0;
|
||||
let mut simplifier: Option<Simplify> = None;
|
||||
let mut simplifier: Option<dc_simplify_t> = None;
|
||||
if !(mime.is_null() || (*mime).mm_data.mm_single.is_null()) {
|
||||
mime_type = mailmime_get_mime_type(mime, &mut msg_type, &mut raw_mime);
|
||||
mime_data = (*mime).mm_data.mm_single;
|
||||
@@ -1117,7 +1134,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
|
||||
match mime_type {
|
||||
60 | 70 => {
|
||||
if simplifier.is_none() {
|
||||
simplifier = Some(Simplify::new());
|
||||
simplifier = Some(dc_simplify_t::new());
|
||||
}
|
||||
/* get from `Content-Type: text/...; charset=utf-8`; must not be free()'d */
|
||||
let charset = mailmime_content_charset_get((*mime).mm_content_type);
|
||||
@@ -1167,7 +1184,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
|
||||
/* check header directly as is_send_by_messenger is not yet set up */
|
||||
let is_msgrmsg = (!dc_mimeparser_lookup_optional_field(
|
||||
&mimeparser,
|
||||
"Chat-Version",
|
||||
b"Chat-Version\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
.is_null())
|
||||
as libc::c_int;
|
||||
@@ -1175,7 +1192,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
|
||||
let simplified_txt = simplifier.unwrap().simplify(
|
||||
decoded_data,
|
||||
decoded_data_bytes as libc::c_int,
|
||||
mime_type == 70i32,
|
||||
if mime_type == 70i32 { 1i32 } else { 0i32 },
|
||||
is_msgrmsg,
|
||||
);
|
||||
if !simplified_txt.is_null()
|
||||
@@ -1191,7 +1208,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
|
||||
} else {
|
||||
free(simplified_txt as *mut libc::c_void);
|
||||
}
|
||||
if simplifier.unwrap().is_forwarded {
|
||||
if 0 != simplifier.unwrap().is_forwarded {
|
||||
mimeparser.is_forwarded = 1i32
|
||||
}
|
||||
current_block = 10261677128829721533;
|
||||
@@ -1379,7 +1396,11 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
|
||||
free(file_suffix as *mut libc::c_void);
|
||||
free(desired_filename as *mut libc::c_void);
|
||||
free(raw_mime as *mut libc::c_void);
|
||||
(mimeparser.parts.len() > old_part_count) as libc::c_int
|
||||
return if mimeparser.parts.len() > old_part_count {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
@@ -1415,15 +1436,16 @@ unsafe fn do_add_single_file_part(
|
||||
part.param.set(Param::File, as_str(pathNfilename));
|
||||
part.param.set(Param::MimeType, as_str(raw_mime));
|
||||
if mime_type == 80 {
|
||||
assert!(!decoded_data.is_null(), "invalid image data");
|
||||
let data = std::slice::from_raw_parts(
|
||||
decoded_data as *const u8,
|
||||
decoded_data_bytes as usize,
|
||||
);
|
||||
|
||||
if let Ok((width, height)) = dc_get_filemeta(data) {
|
||||
part.param.set_int(Param::Width, width as i32);
|
||||
part.param.set_int(Param::Height, height as i32);
|
||||
let mut w = 0;
|
||||
let mut h = 0;
|
||||
if 0 != dc_get_filemeta(
|
||||
decoded_data as *const libc::c_void,
|
||||
decoded_data_bytes,
|
||||
&mut w,
|
||||
&mut h,
|
||||
) {
|
||||
part.param.set_int(Param::Width, w as i32);
|
||||
part.param.set_int(Param::Height, h as i32);
|
||||
}
|
||||
}
|
||||
do_add_single_part(parser, part);
|
||||
@@ -1530,8 +1552,10 @@ pub unsafe fn dc_mimeparser_is_mailinglist_message(mimeparser: &dc_mimeparser_t)
|
||||
if !dc_mimeparser_lookup_field(&mimeparser, "List-Id").is_null() {
|
||||
return 1i32;
|
||||
}
|
||||
let precedence: *mut mailimf_optional_field =
|
||||
dc_mimeparser_lookup_optional_field(mimeparser, "Precedence");
|
||||
let precedence: *mut mailimf_optional_field = dc_mimeparser_lookup_optional_field(
|
||||
mimeparser,
|
||||
b"Precedence\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
if !precedence.is_null() {
|
||||
if strcasecmp(
|
||||
(*precedence).fld_value,
|
||||
|
||||
@@ -27,13 +27,13 @@ pub unsafe fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u3
|
||||
}
|
||||
|
||||
if dc_is_mvbox(context, folder) {
|
||||
dc_update_msg_move_state(context, (*msg).rfc724_mid, MoveState::Stay);
|
||||
dc_update_msg_move_state(context, (*msg).rfc724_mid, DC_MOVE_STATE_STAY);
|
||||
}
|
||||
|
||||
// 1 = dc message, 2 = reply to dc message
|
||||
if 0 != (*msg).is_dc_message {
|
||||
dc_job_add(context, 200, (*msg).id as libc::c_int, Params::new(), 0);
|
||||
dc_update_msg_move_state(context, (*msg).rfc724_mid, MoveState::Moving);
|
||||
dc_update_msg_move_state(context, (*msg).rfc724_mid, DC_MOVE_STATE_MOVING);
|
||||
}
|
||||
|
||||
dc_msg_unref(msg);
|
||||
|
||||
190
src/dc_msg.rs
190
src/dc_msg.rs
@@ -20,11 +20,12 @@ use std::ptr;
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
pub struct dc_msg_t<'a> {
|
||||
pub magic: uint32_t,
|
||||
pub id: uint32_t,
|
||||
pub from_id: uint32_t,
|
||||
pub to_id: uint32_t,
|
||||
pub chat_id: uint32_t,
|
||||
pub move_state: MoveState,
|
||||
pub move_state: dc_move_state_t,
|
||||
pub type_0: Viewtype,
|
||||
pub state: libc::c_int,
|
||||
pub hidden: libc::c_int,
|
||||
@@ -35,7 +36,7 @@ pub struct dc_msg_t<'a> {
|
||||
pub context: &'a Context,
|
||||
pub rfc724_mid: *mut libc::c_char,
|
||||
pub in_reply_to: *mut libc::c_char,
|
||||
pub server_folder: Option<String>,
|
||||
pub server_folder: *mut libc::c_char,
|
||||
pub server_uid: uint32_t,
|
||||
pub is_dc_message: libc::c_int,
|
||||
pub starred: libc::c_int,
|
||||
@@ -167,7 +168,7 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
|
||||
ret += &format!(
|
||||
"\nFile: {}, {}, bytes\n",
|
||||
as_str(p),
|
||||
dc_get_filebytes(context, as_path(p)) as libc::c_int,
|
||||
dc_get_filebytes(context, p) as libc::c_int,
|
||||
);
|
||||
}
|
||||
free(p as *mut libc::c_void);
|
||||
@@ -193,12 +194,14 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
|
||||
ret += &format!("\n{}\n", rawtxt);
|
||||
}
|
||||
if !(*msg).rfc724_mid.is_null() && 0 != *(*msg).rfc724_mid.offset(0) as libc::c_int {
|
||||
ret += &format!("\nMessage-ID: {}", as_str((*msg).rfc724_mid));
|
||||
ret += &format!("\nMessage-ID: {}", (*msg).rfc724_mid as libc::c_int);
|
||||
}
|
||||
if let Some(ref server_folder) = (*msg).server_folder {
|
||||
if server_folder != "" {
|
||||
ret += &format!("\nLast seen as: {}/{}", server_folder, (*msg).server_uid);
|
||||
}
|
||||
if !(*msg).server_folder.is_null() && 0 != *(*msg).server_folder.offset(0) as libc::c_int {
|
||||
ret += &format!(
|
||||
"\nLast seen as: {}/{}",
|
||||
to_string((*msg).server_folder),
|
||||
(*msg).server_uid as libc::c_int,
|
||||
);
|
||||
}
|
||||
|
||||
dc_msg_unref(msg);
|
||||
@@ -221,11 +224,12 @@ pub unsafe fn dc_msg_new_untyped<'a>(context: &'a Context) -> *mut dc_msg_t<'a>
|
||||
// approx. max. length returned by dc_get_msg_info()
|
||||
pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut dc_msg_t<'a> {
|
||||
let msg = dc_msg_t {
|
||||
magic: 0x11561156,
|
||||
id: 0,
|
||||
from_id: 0,
|
||||
to_id: 0,
|
||||
chat_id: 0,
|
||||
move_state: MoveState::Undefined,
|
||||
move_state: 0,
|
||||
type_0: viewtype,
|
||||
state: 0,
|
||||
hidden: 0,
|
||||
@@ -236,7 +240,7 @@ pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut d
|
||||
context,
|
||||
rfc724_mid: std::ptr::null_mut(),
|
||||
in_reply_to: std::ptr::null_mut(),
|
||||
server_folder: None,
|
||||
server_folder: std::ptr::null_mut(),
|
||||
server_uid: 0,
|
||||
is_dc_message: 0,
|
||||
starred: 0,
|
||||
@@ -248,22 +252,25 @@ pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut d
|
||||
Box::into_raw(Box::new(msg))
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_unref(msg: *mut dc_msg_t) {
|
||||
if msg.is_null() {
|
||||
pub unsafe fn dc_msg_unref(mut msg: *mut dc_msg_t) {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return;
|
||||
}
|
||||
dc_msg_empty(msg);
|
||||
(*msg).magic = 0i32 as uint32_t;
|
||||
Box::from_raw(msg);
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return;
|
||||
}
|
||||
free((*msg).rfc724_mid as *mut libc::c_void);
|
||||
(*msg).rfc724_mid = 0 as *mut libc::c_char;
|
||||
free((*msg).in_reply_to as *mut libc::c_void);
|
||||
(*msg).in_reply_to = 0 as *mut libc::c_char;
|
||||
free((*msg).server_folder as *mut libc::c_void);
|
||||
(*msg).server_folder = 0 as *mut libc::c_char;
|
||||
(*msg).param = Params::new();
|
||||
(*msg).hidden = 0i32;
|
||||
}
|
||||
@@ -271,7 +278,7 @@ pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) {
|
||||
pub unsafe fn dc_msg_get_filemime(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
let mut ret = 0 as *mut libc::c_char;
|
||||
|
||||
if !msg.is_null() {
|
||||
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
|
||||
match (*msg).param.get(Param::MimeType) {
|
||||
Some(m) => {
|
||||
ret = m.strdup();
|
||||
@@ -355,7 +362,7 @@ pub unsafe fn dc_msg_guess_msgtype_from_suffix(
|
||||
pub unsafe fn dc_msg_get_file(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
let mut file_abs = 0 as *mut libc::c_char;
|
||||
|
||||
if !msg.is_null() {
|
||||
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
|
||||
if let Some(file_rel) = (*msg).param.get(Param::File) {
|
||||
let file_rel_c = CString::yolo(file_rel);
|
||||
file_abs = dc_get_abs_path((*msg).context, file_rel_c.as_ptr());
|
||||
@@ -378,7 +385,7 @@ pub unsafe fn dc_msg_get_file(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
* @return 1=Message has location bound to it, 0=No location bound to message.
|
||||
*/
|
||||
pub unsafe fn dc_msg_has_location(msg: *const dc_msg_t) -> bool {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -407,7 +414,10 @@ pub unsafe fn dc_msg_set_location(
|
||||
latitude: libc::c_double,
|
||||
longitude: libc::c_double,
|
||||
) {
|
||||
if msg.is_null() || (latitude == 0.0 && longitude == 0.0) {
|
||||
if msg.is_null()
|
||||
|| (*msg).magic != 0x11561156i32 as libc::c_uint
|
||||
|| (latitude == 0.0 && longitude == 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -416,14 +426,14 @@ pub unsafe fn dc_msg_set_location(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_timestamp(msg: *const dc_msg_t) -> i64 {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
if 0 != (*msg).timestamp_sent {
|
||||
return if 0 != (*msg).timestamp_sent {
|
||||
(*msg).timestamp_sent
|
||||
} else {
|
||||
(*msg).timestamp_sort
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id: u32) -> bool {
|
||||
@@ -450,7 +460,7 @@ pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id:
|
||||
Some(s) => s.strdup(),
|
||||
None => std::ptr::null_mut(),
|
||||
};
|
||||
(*msg).server_folder = row.get::<_, Option<String>>(3)?;
|
||||
(*msg).server_folder = row.get::<_, String>(3)?.strdup();
|
||||
(*msg).server_uid = row.get(4)?;
|
||||
(*msg).move_state = row.get(5)?;
|
||||
(*msg).chat_id = row.get(6)?;
|
||||
@@ -462,21 +472,7 @@ pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id:
|
||||
(*msg).type_0 = row.get(12)?;
|
||||
(*msg).state = row.get(13)?;
|
||||
(*msg).is_dc_message = row.get(14)?;
|
||||
|
||||
let text;
|
||||
if let rusqlite::types::ValueRef::Text(buf) = row.get_raw(15) {
|
||||
if let Ok(t) = String::from_utf8(buf.to_vec()) {
|
||||
text = t;
|
||||
} else {
|
||||
warn!(context, 0, "dc_msg_load_from_db: could not get text column as non-lossy utf8 id {}", id);
|
||||
text = String::from_utf8_lossy(buf).into_owned();
|
||||
}
|
||||
} else {
|
||||
warn!(context, 0, "dc_msg_load_from_db: could not get text column for id {}", id);
|
||||
text = "[ Could not read from db ]".to_string();
|
||||
}
|
||||
(*msg).text = Some(text);
|
||||
|
||||
(*msg).text = row.get::<_, Option<String>>(15)?;
|
||||
(*msg).param = row.get::<_, String>(16)?.parse().unwrap_or_default();
|
||||
(*msg).starred = row.get(17)?;
|
||||
(*msg).hidden = row.get(18)?;
|
||||
@@ -492,18 +488,11 @@ pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id:
|
||||
free(ptr.cast());
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
|
||||
if let Err(e) = res {
|
||||
warn!(
|
||||
context,
|
||||
0, "Error in msg_load_from_db for id {} because of {}", id, e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
true
|
||||
res.is_ok()
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_mime_headers(context: &Context, msg_id: uint32_t) -> *mut libc::c_char {
|
||||
@@ -639,13 +628,12 @@ pub fn dc_star_msgs(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_get_msg<'a>(context: &'a Context, msg_id: uint32_t) -> *mut dc_msg_t<'a> {
|
||||
let mut success = false;
|
||||
let mut success: libc::c_int = 0i32;
|
||||
let obj: *mut dc_msg_t = dc_msg_new_untyped(context);
|
||||
if dc_msg_load_from_db(obj, context, msg_id) {
|
||||
success = true
|
||||
success = 1i32
|
||||
}
|
||||
|
||||
if success {
|
||||
if 0 != success {
|
||||
obj
|
||||
} else {
|
||||
dc_msg_unref(obj);
|
||||
@@ -654,7 +642,7 @@ pub unsafe fn dc_get_msg<'a>(context: &'a Context, msg_id: uint32_t) -> *mut dc_
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_id(msg: *const dc_msg_t) -> uint32_t {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0i32 as uint32_t;
|
||||
}
|
||||
|
||||
@@ -662,7 +650,7 @@ pub unsafe fn dc_msg_get_id(msg: *const dc_msg_t) -> uint32_t {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_from_id(msg: *const dc_msg_t) -> uint32_t {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0i32 as uint32_t;
|
||||
}
|
||||
|
||||
@@ -670,7 +658,7 @@ pub unsafe fn dc_msg_get_from_id(msg: *const dc_msg_t) -> uint32_t {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_chat_id(msg: *const dc_msg_t) -> uint32_t {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0i32 as uint32_t;
|
||||
}
|
||||
return if 0 != (*msg).chat_blocked {
|
||||
@@ -681,7 +669,7 @@ pub unsafe fn dc_msg_get_chat_id(msg: *const dc_msg_t) -> uint32_t {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_viewtype(msg: *const dc_msg_t) -> Viewtype {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return Viewtype::Unknown;
|
||||
}
|
||||
|
||||
@@ -689,7 +677,7 @@ pub unsafe fn dc_msg_get_viewtype(msg: *const dc_msg_t) -> Viewtype {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_state(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0i32;
|
||||
}
|
||||
|
||||
@@ -697,7 +685,7 @@ pub unsafe fn dc_msg_get_state(msg: *const dc_msg_t) -> libc::c_int {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_received_timestamp(msg: *const dc_msg_t) -> i64 {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -705,7 +693,7 @@ pub unsafe fn dc_msg_get_received_timestamp(msg: *const dc_msg_t) -> i64 {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_sort_timestamp(msg: *const dc_msg_t) -> i64 {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -713,7 +701,7 @@ pub unsafe fn dc_msg_get_sort_timestamp(msg: *const dc_msg_t) -> i64 {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_text(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return dc_strdup(0 as *const libc::c_char);
|
||||
}
|
||||
if let Some(ref text) = (*msg).text {
|
||||
@@ -727,7 +715,7 @@ pub unsafe fn dc_msg_get_text(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
pub unsafe fn dc_msg_get_filename(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
let mut ret = 0 as *mut libc::c_char;
|
||||
|
||||
if !msg.is_null() {
|
||||
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
|
||||
if let Some(file) = (*msg).param.get(Param::File) {
|
||||
let file_c = CString::yolo(file);
|
||||
ret = dc_get_filename(file_c.as_ptr());
|
||||
@@ -741,17 +729,20 @@ pub unsafe fn dc_msg_get_filename(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_filebytes(msg: *const dc_msg_t) -> uint64_t {
|
||||
if !msg.is_null() {
|
||||
let mut ret = 0;
|
||||
|
||||
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
|
||||
if let Some(file) = (*msg).param.get(Param::File) {
|
||||
return dc_get_filebytes((*msg).context, &file);
|
||||
let file_c = CString::yolo(file);
|
||||
ret = dc_get_filebytes((*msg).context, file_c.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_width(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -759,7 +750,7 @@ pub unsafe fn dc_msg_get_width(msg: *const dc_msg_t) -> libc::c_int {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_height(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -767,7 +758,7 @@ pub unsafe fn dc_msg_get_height(msg: *const dc_msg_t) -> libc::c_int {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_get_duration(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -776,7 +767,7 @@ pub unsafe fn dc_msg_get_duration(msg: *const dc_msg_t) -> libc::c_int {
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_msg_get_showpadlock(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
if (*msg)
|
||||
@@ -795,29 +786,35 @@ pub unsafe fn dc_msg_get_summary<'a>(
|
||||
msg: *mut dc_msg_t<'a>,
|
||||
mut chat: *const Chat<'a>,
|
||||
) -> *mut dc_lot_t {
|
||||
let mut ok_to_continue = true;
|
||||
let current_block: u64;
|
||||
let ret: *mut dc_lot_t = dc_lot_new();
|
||||
let mut chat_to_delete: *mut Chat = 0 as *mut Chat;
|
||||
|
||||
if !msg.is_null() {
|
||||
if !(msg.is_null() || (*msg).magic != 0x11561156 as libc::c_uint) {
|
||||
if chat.is_null() {
|
||||
chat_to_delete = dc_get_chat((*msg).context, (*msg).chat_id);
|
||||
if chat_to_delete.is_null() {
|
||||
ok_to_continue = false;
|
||||
current_block = 15204159476013091401;
|
||||
} else {
|
||||
chat = chat_to_delete;
|
||||
current_block = 7815301370352969686;
|
||||
}
|
||||
} else {
|
||||
current_block = 7815301370352969686;
|
||||
}
|
||||
if ok_to_continue {
|
||||
let contact = if (*msg).from_id != DC_CONTACT_ID_SELF as libc::c_uint
|
||||
&& ((*chat).type_0 == 120 || (*chat).type_0 == 130)
|
||||
{
|
||||
Contact::get_by_id((*chat).context, (*msg).from_id).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match current_block {
|
||||
15204159476013091401 => {}
|
||||
_ => {
|
||||
let contact = if (*msg).from_id != DC_CONTACT_ID_SELF as libc::c_uint
|
||||
&& ((*chat).type_0 == 120 || (*chat).type_0 == 130)
|
||||
{
|
||||
Contact::get_by_id((*chat).context, (*msg).from_id).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
dc_lot_fill(ret, msg, chat, contact.as_ref(), (*msg).context);
|
||||
dc_lot_fill(ret, msg, chat, contact.as_ref(), (*msg).context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,7 +827,7 @@ pub unsafe fn dc_msg_get_summarytext(
|
||||
msg: *mut dc_msg_t,
|
||||
approx_characters: libc::c_int,
|
||||
) -> *mut libc::c_char {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return dc_strdup(0 as *const libc::c_char);
|
||||
}
|
||||
|
||||
@@ -941,7 +938,7 @@ pub unsafe fn dc_msg_has_deviating_timestamp(msg: *const dc_msg_t) -> libc::c_in
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_msg_is_sent(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
if (*msg).state >= DC_STATE_OUT_DELIVERED {
|
||||
@@ -952,7 +949,7 @@ pub unsafe fn dc_msg_is_sent(msg: *const dc_msg_t) -> libc::c_int {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_is_starred(msg: *const dc_msg_t) -> bool {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return false;
|
||||
}
|
||||
0 != (*msg).starred
|
||||
@@ -960,7 +957,7 @@ pub unsafe fn dc_msg_is_starred(msg: *const dc_msg_t) -> bool {
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_msg_is_forwarded(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
if 0 != (*msg).param.get_int(Param::Forwarded).unwrap_or_default() {
|
||||
@@ -972,7 +969,7 @@ pub unsafe fn dc_msg_is_forwarded(msg: *const dc_msg_t) -> libc::c_int {
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_msg_is_info(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
let cmd = (*msg).param.get_int(Param::Cmd).unwrap_or_default();
|
||||
@@ -988,7 +985,7 @@ pub unsafe fn dc_msg_is_info(msg: *const dc_msg_t) -> libc::c_int {
|
||||
|
||||
// TODO should return bool /rtn
|
||||
pub unsafe fn dc_msg_is_increation(msg: *const dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1000,7 +997,10 @@ pub unsafe fn dc_msg_is_increation(msg: *const dc_msg_t) -> libc::c_int {
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_is_setupmessage(msg: *const dc_msg_t) -> bool {
|
||||
if msg.is_null() || (*msg).type_0 != Viewtype::File {
|
||||
if msg.is_null()
|
||||
|| (*msg).magic != 0x11561156i32 as libc::c_uint
|
||||
|| (*msg).type_0 != Viewtype::File
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1048,15 +1048,15 @@ pub unsafe fn dc_msg_get_setupcodebegin(msg: *const dc_msg_t) -> *mut libc::c_ch
|
||||
}
|
||||
free(filename as *mut libc::c_void);
|
||||
free(buf as *mut libc::c_void);
|
||||
if !ret.is_null() {
|
||||
return if !ret.is_null() {
|
||||
ret
|
||||
} else {
|
||||
dc_strdup(0 as *const libc::c_char)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_set_text(mut msg: *mut dc_msg_t, text: *const libc::c_char) {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return;
|
||||
}
|
||||
(*msg).text = if text.is_null() {
|
||||
@@ -1071,7 +1071,7 @@ pub unsafe fn dc_msg_set_file(
|
||||
file: *const libc::c_char,
|
||||
filemime: *const libc::c_char,
|
||||
) {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return;
|
||||
}
|
||||
if !file.is_null() {
|
||||
@@ -1083,7 +1083,7 @@ pub unsafe fn dc_msg_set_file(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_set_dimension(msg: *mut dc_msg_t, width: libc::c_int, height: libc::c_int) {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return;
|
||||
}
|
||||
(*msg).param.set_int(Param::Width, width);
|
||||
@@ -1091,7 +1091,7 @@ pub unsafe fn dc_msg_set_dimension(msg: *mut dc_msg_t, width: libc::c_int, heigh
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_set_duration(msg: *mut dc_msg_t, duration: libc::c_int) {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return;
|
||||
}
|
||||
(*msg).param.set_int(Param::Duration, duration);
|
||||
@@ -1103,7 +1103,7 @@ pub unsafe fn dc_msg_latefiling_mediasize(
|
||||
height: libc::c_int,
|
||||
duration: libc::c_int,
|
||||
) {
|
||||
if !msg.is_null() {
|
||||
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
|
||||
if width > 0 && height > 0 {
|
||||
(*msg).param.set_int(Param::Width, width);
|
||||
(*msg).param.set_int(Param::Height, height);
|
||||
@@ -1116,7 +1116,7 @@ pub unsafe fn dc_msg_latefiling_mediasize(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_msg_save_param_to_disk(msg: *mut dc_msg_t) -> bool {
|
||||
if msg.is_null() {
|
||||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1187,7 +1187,7 @@ pub unsafe fn dc_msg_exists(context: &Context, msg_id: uint32_t) -> libc::c_int
|
||||
pub fn dc_update_msg_move_state(
|
||||
context: &Context,
|
||||
rfc724_mid: *const libc::c_char,
|
||||
state: MoveState,
|
||||
state: dc_move_state_t,
|
||||
) -> bool {
|
||||
// we update the move_state for all messages belonging to a given Message-ID
|
||||
// so that the state stay intact when parts are deleted
|
||||
@@ -1201,9 +1201,9 @@ pub fn dc_update_msg_move_state(
|
||||
}
|
||||
|
||||
fn msgstate_can_fail(state: i32) -> bool {
|
||||
DC_STATE_OUT_PREPARING == state
|
||||
return DC_STATE_OUT_PREPARING == state
|
||||
|| DC_STATE_OUT_PENDING == state
|
||||
|| DC_STATE_OUT_DELIVERED == state
|
||||
|| DC_STATE_OUT_DELIVERED == state;
|
||||
}
|
||||
|
||||
pub unsafe fn dc_set_msg_failed(context: &Context, msg_id: uint32_t, error: *const libc::c_char) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ use crate::aheader::EncryptPreference;
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_array::*;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_configure::*;
|
||||
use crate::dc_e2ee::*;
|
||||
@@ -41,7 +42,7 @@ pub unsafe fn dc_get_securejoin_qr(
|
||||
let mut group_name_urlencoded = 0 as *mut libc::c_char;
|
||||
let mut qr: Option<String> = None;
|
||||
|
||||
dc_ensure_secret_key_exists(context).ok();
|
||||
dc_ensure_secret_key_exists(context);
|
||||
invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id);
|
||||
if invitenumber.is_null() {
|
||||
invitenumber = dc_create_id().strdup();
|
||||
@@ -148,7 +149,7 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
|
||||
let mut join_vg: libc::c_int = 0i32;
|
||||
let mut qr_scan: *mut dc_lot_t = 0 as *mut dc_lot_t;
|
||||
info!(context, 0, "Requesting secure-join ...",);
|
||||
dc_ensure_secret_key_exists(context).ok();
|
||||
dc_ensure_secret_key_exists(context);
|
||||
ongoing_allocated = dc_alloc_ongoing(context);
|
||||
if !(ongoing_allocated == 0i32) {
|
||||
qr_scan = dc_check_qr(context, qr);
|
||||
@@ -295,12 +296,14 @@ unsafe fn send_handshake_msg(
|
||||
}
|
||||
|
||||
unsafe fn chat_id_2_contact_id(context: &Context, contact_chat_id: uint32_t) -> uint32_t {
|
||||
let contacts = dc_get_chat_contacts(context, contact_chat_id);
|
||||
if contacts.len() == 1 {
|
||||
contacts[0]
|
||||
} else {
|
||||
0
|
||||
let mut contact_id: uint32_t = 0i32 as uint32_t;
|
||||
let contacts: *mut dc_array_t = dc_get_chat_contacts(context, contact_chat_id);
|
||||
if !(dc_array_get_cnt(contacts) != 1) {
|
||||
contact_id = dc_array_get_id(contacts, 0i32 as size_t)
|
||||
}
|
||||
dc_array_unref(contacts);
|
||||
|
||||
contact_id
|
||||
}
|
||||
|
||||
unsafe fn fingerprint_equals_sender(
|
||||
@@ -314,8 +317,8 @@ unsafe fn fingerprint_equals_sender(
|
||||
let mut fingerprint_equal: libc::c_int = 0i32;
|
||||
let contacts = dc_get_chat_contacts(context, contact_chat_id);
|
||||
|
||||
if contacts.len() == 1 {
|
||||
if let Ok(contact) = Contact::load_from_db(context, contacts[0]) {
|
||||
if !(dc_array_get_cnt(contacts) != 1) {
|
||||
if let Ok(contact) = Contact::load_from_db(context, dc_array_get_id(contacts, 0)) {
|
||||
if let Some(peerstate) = Peerstate::from_addr(context, &context.sql, contact.get_addr())
|
||||
{
|
||||
let fingerprint_normalized = dc_normalize_fingerprint(as_str(fingerprint));
|
||||
@@ -329,6 +332,7 @@ unsafe fn fingerprint_equals_sender(
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
dc_array_unref(contacts);
|
||||
|
||||
fingerprint_equal
|
||||
}
|
||||
@@ -442,7 +446,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
grpid = dc_strdup((*scan).text2)
|
||||
}
|
||||
}
|
||||
if !encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) {
|
||||
if 0 == encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) {
|
||||
could_not_establish_secure_connection(
|
||||
context,
|
||||
contact_chat_id,
|
||||
@@ -518,7 +522,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
b"Fingerprint not provided.\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
current_block = 4378276786830486580;
|
||||
} else if !encrypted_and_signed(mimeparser, fingerprint) {
|
||||
} else if 0 == encrypted_and_signed(mimeparser, fingerprint) {
|
||||
could_not_establish_secure_connection(
|
||||
context,
|
||||
contact_chat_id,
|
||||
@@ -664,7 +668,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
}
|
||||
}
|
||||
if 0 != vg_expect_encrypted {
|
||||
if !encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) {
|
||||
if 0 == encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) {
|
||||
could_not_establish_secure_connection(
|
||||
context,
|
||||
contact_chat_id,
|
||||
@@ -883,21 +887,22 @@ unsafe fn mark_peer_as_verified(
|
||||
* Tools: Misc.
|
||||
******************************************************************************/
|
||||
|
||||
// TODO should return bool
|
||||
unsafe fn encrypted_and_signed(
|
||||
mimeparser: &dc_mimeparser_t,
|
||||
expected_fingerprint: *const libc::c_char,
|
||||
) -> bool {
|
||||
) -> libc::c_int {
|
||||
if 0 == mimeparser.e2ee_helper.encrypted {
|
||||
warn!(mimeparser.context, 0, "Message not encrypted.",);
|
||||
return false;
|
||||
return 0i32;
|
||||
}
|
||||
if mimeparser.e2ee_helper.signatures.len() <= 0 {
|
||||
warn!(mimeparser.context, 0, "Message not signed.",);
|
||||
return false;
|
||||
return 0i32;
|
||||
}
|
||||
if expected_fingerprint.is_null() {
|
||||
warn!(mimeparser.context, 0, "Fingerprint for comparison missing.",);
|
||||
return false;
|
||||
return 0i32;
|
||||
}
|
||||
if !mimeparser
|
||||
.e2ee_helper
|
||||
@@ -910,10 +915,10 @@ unsafe fn encrypted_and_signed(
|
||||
"Message does not match expected fingerprint {}.",
|
||||
as_str(expected_fingerprint),
|
||||
);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
true
|
||||
1
|
||||
}
|
||||
|
||||
pub unsafe fn dc_handle_degrade_event(context: &Context, peerstate: &Peerstate) {
|
||||
|
||||
@@ -3,18 +3,19 @@ use crate::dc_tools::*;
|
||||
use crate::x::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Simplify {
|
||||
pub is_forwarded: bool,
|
||||
pub is_cut_at_begin: bool,
|
||||
pub is_cut_at_end: bool,
|
||||
#[repr(C)]
|
||||
pub struct dc_simplify_t {
|
||||
pub is_forwarded: libc::c_int,
|
||||
pub is_cut_at_begin: libc::c_int,
|
||||
pub is_cut_at_end: libc::c_int,
|
||||
}
|
||||
|
||||
impl Simplify {
|
||||
impl dc_simplify_t {
|
||||
pub fn new() -> Self {
|
||||
Simplify {
|
||||
is_forwarded: false,
|
||||
is_cut_at_begin: false,
|
||||
is_cut_at_end: false,
|
||||
dc_simplify_t {
|
||||
is_forwarded: 0,
|
||||
is_cut_at_begin: 0,
|
||||
is_cut_at_end: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +26,7 @@ impl Simplify {
|
||||
&mut self,
|
||||
in_unterminated: *const libc::c_char,
|
||||
in_bytes: libc::c_int,
|
||||
is_html: bool,
|
||||
is_html: libc::c_int,
|
||||
is_msgrmsg: libc::c_int,
|
||||
) -> *mut libc::c_char {
|
||||
if in_bytes <= 0 {
|
||||
@@ -35,9 +36,9 @@ impl Simplify {
|
||||
/* create a copy of the given buffer */
|
||||
let mut out: *mut libc::c_char;
|
||||
let mut temp: *mut libc::c_char;
|
||||
self.is_forwarded = false;
|
||||
self.is_cut_at_begin = false;
|
||||
self.is_cut_at_end = false;
|
||||
self.is_forwarded = 0i32;
|
||||
self.is_cut_at_begin = 0i32;
|
||||
self.is_cut_at_end = 0i32;
|
||||
out = strndup(
|
||||
in_unterminated as *mut libc::c_char,
|
||||
in_bytes as libc::c_ulong,
|
||||
@@ -45,7 +46,7 @@ impl Simplify {
|
||||
if out.is_null() {
|
||||
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
|
||||
}
|
||||
if is_html {
|
||||
if 0 != is_html {
|
||||
temp = dc_dehtml(out);
|
||||
if !temp.is_null() {
|
||||
free(out as *mut libc::c_void);
|
||||
@@ -95,7 +96,7 @@ impl Simplify {
|
||||
|| strcmp(line, b"----\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
{
|
||||
footer_mark = 1i32;
|
||||
self.is_cut_at_end = true
|
||||
self.is_cut_at_end = 1i32
|
||||
}
|
||||
if 0 != footer_mark {
|
||||
l_last = l;
|
||||
@@ -114,7 +115,7 @@ impl Simplify {
|
||||
&& strncmp(line1, b"From: \x00" as *const u8 as *const libc::c_char, 6) == 0i32
|
||||
&& *line2.offset(0isize) as libc::c_int == 0i32
|
||||
{
|
||||
self.is_forwarded = true;
|
||||
self.is_forwarded = 1i32;
|
||||
l_first += 3
|
||||
}
|
||||
}
|
||||
@@ -127,7 +128,7 @@ impl Simplify {
|
||||
|| strncmp(line, b"~~~~~\x00" as *const u8 as *const libc::c_char, 5) == 0i32
|
||||
{
|
||||
l_last = l;
|
||||
self.is_cut_at_end = true;
|
||||
self.is_cut_at_end = 1i32;
|
||||
/* done */
|
||||
break;
|
||||
}
|
||||
@@ -144,7 +145,7 @@ impl Simplify {
|
||||
}
|
||||
if l_lastQuotedLine.is_some() {
|
||||
l_last = l_lastQuotedLine.unwrap();
|
||||
self.is_cut_at_end = true;
|
||||
self.is_cut_at_end = 1i32;
|
||||
if l_last > 1 {
|
||||
if is_empty_line(lines[l_last - 1]) {
|
||||
l_last -= 1
|
||||
@@ -179,12 +180,12 @@ impl Simplify {
|
||||
}
|
||||
if l_lastQuotedLine_0.is_some() {
|
||||
l_first = l_lastQuotedLine_0.unwrap() + 1;
|
||||
self.is_cut_at_begin = true
|
||||
self.is_cut_at_begin = 1i32
|
||||
}
|
||||
}
|
||||
/* re-create buffer from the remaining lines */
|
||||
let mut ret = String::new();
|
||||
if self.is_cut_at_begin {
|
||||
if 0 != self.is_cut_at_begin {
|
||||
ret += "[...]";
|
||||
}
|
||||
/* we write empty lines only in case and non-empty line follows */
|
||||
@@ -210,7 +211,7 @@ impl Simplify {
|
||||
pending_linebreaks = 1i32
|
||||
}
|
||||
}
|
||||
if self.is_cut_at_end && (!self.is_cut_at_begin || 0 != content_lines_added) {
|
||||
if 0 != self.is_cut_at_end && (0 == self.is_cut_at_begin || 0 != content_lines_added) {
|
||||
ret += " [...]";
|
||||
}
|
||||
dc_free_splitted_lines(lines);
|
||||
@@ -267,11 +268,11 @@ mod tests {
|
||||
#[test]
|
||||
fn test_simplify_trim() {
|
||||
unsafe {
|
||||
let mut simplify = Simplify::new();
|
||||
let mut simplify = dc_simplify_t::new();
|
||||
let html: *const libc::c_char =
|
||||
b"\r\r\nline1<br>\r\n\r\n\r\rline2\n\r\x00" as *const u8 as *const libc::c_char;
|
||||
let plain: *mut libc::c_char =
|
||||
simplify.simplify(html, strlen(html) as libc::c_int, true, 0);
|
||||
simplify.simplify(html, strlen(html) as libc::c_int, 1, 0);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr(plain as *const libc::c_char)
|
||||
@@ -287,11 +288,11 @@ mod tests {
|
||||
#[test]
|
||||
fn test_simplify_parse_href() {
|
||||
unsafe {
|
||||
let mut simplify = Simplify::new();
|
||||
let mut simplify = dc_simplify_t::new();
|
||||
let html: *const libc::c_char =
|
||||
b"<a href=url>text</a\x00" as *const u8 as *const libc::c_char;
|
||||
let plain: *mut libc::c_char =
|
||||
simplify.simplify(html, strlen(html) as libc::c_int, true, 0);
|
||||
simplify.simplify(html, strlen(html) as libc::c_int, 1, 0);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr(plain as *const libc::c_char)
|
||||
@@ -307,12 +308,12 @@ mod tests {
|
||||
#[test]
|
||||
fn test_simplify_bold_text() {
|
||||
unsafe {
|
||||
let mut simplify = Simplify::new();
|
||||
let mut simplify = dc_simplify_t::new();
|
||||
let html: *const libc::c_char =
|
||||
b"<!DOCTYPE name [<!DOCTYPE ...>]><!-- comment -->text <b><?php echo ... ?>bold</b><![CDATA[<>]]>\x00"
|
||||
as *const u8 as *const libc::c_char;
|
||||
let plain: *mut libc::c_char =
|
||||
simplify.simplify(html, strlen(html) as libc::c_int, true, 0);
|
||||
simplify.simplify(html, strlen(html) as libc::c_int, 1, 0);
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr(plain as *const libc::c_char)
|
||||
@@ -328,12 +329,12 @@ mod tests {
|
||||
#[test]
|
||||
fn test_simplify_html_encoded() {
|
||||
unsafe {
|
||||
let mut simplify = Simplify::new();
|
||||
let mut simplify = dc_simplify_t::new();
|
||||
let html: *const libc::c_char =
|
||||
b"<>"'& äÄöÖüÜß fooÆçÇ ♦&noent;‎‏‌‍\x00"
|
||||
as *const u8 as *const libc::c_char;
|
||||
let plain: *mut libc::c_char =
|
||||
simplify.simplify(html, strlen(html) as libc::c_int, true, 0);
|
||||
simplify.simplify(html, strlen(html) as libc::c_int, 1, 0);
|
||||
|
||||
assert_eq!(
|
||||
strcmp(plain,
|
||||
|
||||
@@ -691,11 +691,11 @@ pub unsafe fn dc_decode_ext_header(to_decode: *const libc::c_char) -> *mut libc:
|
||||
}
|
||||
}
|
||||
free(charset as *mut libc::c_void);
|
||||
if !decoded.is_null() {
|
||||
return if !decoded.is_null() {
|
||||
decoded
|
||||
} else {
|
||||
dc_strdup(to_decode)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
unsafe fn print_hex(target: *mut libc::c_char, cur: *const libc::c_char) {
|
||||
|
||||
607
src/dc_tools.rs
607
src/dc_tools.rs
File diff suppressed because it is too large
Load Diff
@@ -18,8 +18,6 @@ pub enum Error {
|
||||
Io(std::io::Error),
|
||||
#[fail(display = "{:?}", _0)]
|
||||
Message(String),
|
||||
#[fail(display = "{:?}", _0)]
|
||||
Image(image_meta::ImageError),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
@@ -48,12 +46,6 @@ impl From<std::io::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<image_meta::ImageError> for Error {
|
||||
fn from(err: image_meta::ImageError) -> Error {
|
||||
Error::Image(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! bail {
|
||||
($e:expr) => {
|
||||
|
||||
99
src/imap.rs
99
src/imap.rs
@@ -1,9 +1,6 @@
|
||||
use std::ffi::CString;
|
||||
use std::net;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, Condvar, Mutex, RwLock,
|
||||
};
|
||||
use std::sync::{Arc, Condvar, Mutex, RwLock};
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use crate::constants::*;
|
||||
@@ -21,9 +18,9 @@ pub const DC_ALREADY_DONE: usize = 2;
|
||||
pub const DC_RETRY_LATER: usize = 1;
|
||||
pub const DC_FAILED: usize = 0;
|
||||
|
||||
const PREFETCH_FLAGS: &str = "(UID ENVELOPE)";
|
||||
const BODY_FLAGS: &str = "(FLAGS BODY.PEEK[])";
|
||||
const FETCH_FLAGS: &str = "(FLAGS)";
|
||||
const PREFETCH_FLAGS: &'static str = "(UID ENVELOPE)";
|
||||
const BODY_FLAGS: &'static str = "(FLAGS BODY.PEEK[])";
|
||||
const FETCH_FLAGS: &'static str = "(FLAGS)";
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Imap {
|
||||
@@ -38,8 +35,6 @@ pub struct Imap {
|
||||
session: Arc<Mutex<Option<Session>>>,
|
||||
stream: Arc<RwLock<Option<net::TcpStream>>>,
|
||||
connected: Arc<Mutex<bool>>,
|
||||
|
||||
should_reconnect: AtomicBool,
|
||||
}
|
||||
|
||||
struct OAuth2 {
|
||||
@@ -204,8 +199,8 @@ impl Session {
|
||||
|
||||
pub fn create<S: AsRef<str>>(&mut self, mailbox_name: S) -> imap::error::Result<()> {
|
||||
match self {
|
||||
Session::Secure(i) => i.create(mailbox_name),
|
||||
Session::Insecure(i) => i.create(mailbox_name),
|
||||
Session::Secure(i) => i.subscribe(mailbox_name),
|
||||
Session::Insecure(i) => i.subscribe(mailbox_name),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,8 +260,8 @@ impl Session {
|
||||
|
||||
pub fn idle(&mut self) -> imap::error::Result<IdleHandle> {
|
||||
match self {
|
||||
Session::Secure(i) => i.idle().map(IdleHandle::Secure),
|
||||
Session::Insecure(i) => i.idle().map(IdleHandle::Insecure),
|
||||
Session::Secure(i) => i.idle().map(|h| IdleHandle::Secure(h)),
|
||||
Session::Insecure(i) => i.idle().map(|h| IdleHandle::Insecure(h)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,6 +313,7 @@ pub struct ImapConfig {
|
||||
pub selected_folder: Option<String>,
|
||||
pub selected_mailbox: Option<imap::types::Mailbox>,
|
||||
pub selected_folder_needs_expunge: bool,
|
||||
pub should_reconnect: bool,
|
||||
pub can_idle: bool,
|
||||
pub has_xlist: bool,
|
||||
pub imap_delimiter: char,
|
||||
@@ -336,6 +332,7 @@ impl Default for ImapConfig {
|
||||
selected_folder: None,
|
||||
selected_mailbox: None,
|
||||
selected_folder_needs_expunge: false,
|
||||
should_reconnect: false,
|
||||
can_idle: false,
|
||||
has_xlist: false,
|
||||
imap_delimiter: '.',
|
||||
@@ -363,7 +360,6 @@ impl Imap {
|
||||
precheck_imf,
|
||||
receive_imf,
|
||||
connected: Arc::new(Mutex::new(false)),
|
||||
should_reconnect: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,7 +368,7 @@ impl Imap {
|
||||
}
|
||||
|
||||
pub fn should_reconnect(&self) -> bool {
|
||||
self.should_reconnect.load(Ordering::Relaxed)
|
||||
self.config.read().unwrap().should_reconnect
|
||||
}
|
||||
|
||||
fn setup_handle_if_needed(&self, context: &Context) -> bool {
|
||||
@@ -385,7 +381,7 @@ impl Imap {
|
||||
}
|
||||
|
||||
if self.is_connected() && self.stream.read().unwrap().is_some() {
|
||||
self.should_reconnect.store(false, Ordering::Relaxed);
|
||||
self.config.write().unwrap().should_reconnect = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -455,7 +451,7 @@ impl Imap {
|
||||
}
|
||||
};
|
||||
|
||||
self.should_reconnect.store(false, Ordering::Relaxed);
|
||||
self.config.write().unwrap().should_reconnect = false;
|
||||
|
||||
match login_res {
|
||||
Ok((session, stream)) => {
|
||||
@@ -543,7 +539,7 @@ impl Imap {
|
||||
let mut config = self.config.write().unwrap();
|
||||
config.addr = addr.to_string();
|
||||
config.imap_server = imap_server.to_string();
|
||||
config.imap_port = imap_port;
|
||||
config.imap_port = imap_port.into();
|
||||
config.imap_user = imap_user.to_string();
|
||||
config.imap_pw = imap_pw.to_string();
|
||||
config.server_flags = server_flags;
|
||||
@@ -554,12 +550,14 @@ impl Imap {
|
||||
return false;
|
||||
}
|
||||
|
||||
let (teardown, can_idle, has_xlist) = match &mut *self.session.lock().unwrap() {
|
||||
let teardown: bool;
|
||||
|
||||
match &mut *self.session.lock().unwrap() {
|
||||
Some(ref mut session) => {
|
||||
if let Ok(caps) = session.capabilities() {
|
||||
if !context.sql.is_open() {
|
||||
warn!(context, 0, "IMAP-LOGIN as {} ok but ABORTING", lp.mail_user,);
|
||||
(true, false, false)
|
||||
teardown = true;
|
||||
} else {
|
||||
let can_idle = caps.has("IDLE");
|
||||
let has_xlist = caps.has("XLIST");
|
||||
@@ -576,23 +574,24 @@ impl Imap {
|
||||
lp.mail_user,
|
||||
caps_list,
|
||||
);
|
||||
(false, can_idle, has_xlist)
|
||||
self.config.write().unwrap().can_idle = can_idle;
|
||||
self.config.write().unwrap().has_xlist = has_xlist;
|
||||
*self.connected.lock().unwrap() = true;
|
||||
teardown = false;
|
||||
}
|
||||
} else {
|
||||
(true, false, false)
|
||||
teardown = true;
|
||||
}
|
||||
}
|
||||
None => (true, false, false),
|
||||
};
|
||||
|
||||
None => {
|
||||
teardown = true;
|
||||
}
|
||||
}
|
||||
if teardown {
|
||||
self.unsetup_handle(context);
|
||||
self.free_connect_params();
|
||||
false
|
||||
} else {
|
||||
self.config.write().unwrap().can_idle = can_idle;
|
||||
self.config.write().unwrap().has_xlist = has_xlist;
|
||||
*self.connected.lock().unwrap() = true;
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -690,8 +689,9 @@ impl Imap {
|
||||
err
|
||||
);
|
||||
|
||||
self.config.write().unwrap().selected_folder = None;
|
||||
self.should_reconnect.store(true, Ordering::Relaxed);
|
||||
let mut config = self.config.write().unwrap();
|
||||
config.selected_folder = None;
|
||||
config.should_reconnect = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -777,7 +777,7 @@ impl Imap {
|
||||
match session.fetch(set, PREFETCH_FLAGS) {
|
||||
Ok(list) => list,
|
||||
Err(_err) => {
|
||||
self.should_reconnect.store(true, Ordering::Relaxed);
|
||||
self.config.write().unwrap().should_reconnect = true;
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
@@ -822,7 +822,7 @@ impl Imap {
|
||||
match session.uid_fetch(set, PREFETCH_FLAGS) {
|
||||
Ok(list) => list,
|
||||
Err(err) => {
|
||||
warn!(context, 0, "failed to fetch uids: {}", err);
|
||||
eprintln!("fetch err: {:?}", err);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -928,13 +928,15 @@ impl Imap {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut retry_later = false;
|
||||
|
||||
let set = format!("{}", server_uid);
|
||||
|
||||
let msgs = if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_fetch(set, BODY_FLAGS) {
|
||||
Ok(msgs) => msgs,
|
||||
Err(err) => {
|
||||
self.should_reconnect.store(true, Ordering::Relaxed);
|
||||
self.config.write().unwrap().should_reconnect = true;
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
@@ -944,11 +946,17 @@ impl Imap {
|
||||
self.should_reconnect(),
|
||||
err
|
||||
);
|
||||
return 0;
|
||||
|
||||
if self.should_reconnect() {
|
||||
// maybe we should also retry on other errors, however, we should check this carefully, as this may result in a dead lock!
|
||||
retry_later = true;
|
||||
}
|
||||
|
||||
return if retry_later { 0 } else { 1 };
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 1;
|
||||
return if retry_later { 0 } else { 1 };
|
||||
};
|
||||
|
||||
if msgs.is_empty() {
|
||||
@@ -996,7 +1004,11 @@ impl Imap {
|
||||
}
|
||||
}
|
||||
|
||||
1
|
||||
if retry_later {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn idle(&self, context: &Context) {
|
||||
@@ -1061,7 +1073,7 @@ impl Imap {
|
||||
context,
|
||||
0, "IMAP-IDLE wait cancelled, we will reconnect soon."
|
||||
);
|
||||
self.should_reconnect.store(true, Ordering::Relaxed);
|
||||
self.config.write().unwrap().should_reconnect = true;
|
||||
}
|
||||
_ => {
|
||||
warn!(context, 0, "IMAP-IDLE returns unknown value: {}", err);
|
||||
@@ -1564,23 +1576,20 @@ impl Imap {
|
||||
info!(context, 0, "MVBOX-folder created.",);
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("create error: {:?}", err);
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot create MVBOX-folder, using trying INBOX subfolder. ({})",
|
||||
err
|
||||
0, "Cannot create MVBOX-folder, using trying INBOX subfolder."
|
||||
);
|
||||
|
||||
match session.create(&fallback_folder) {
|
||||
Ok(_) => {
|
||||
mvbox_folder = Some(fallback_folder);
|
||||
info!(
|
||||
context,
|
||||
0, "MVBOX-folder created as INBOX subfolder. ({})", err
|
||||
);
|
||||
info!(context, 0, "MVBOX-folder created as INBOX subfolder.",);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(context, 0, "Cannot create MVBOX-folder. ({})", err);
|
||||
eprintln!("create error: {:?}", err);
|
||||
warn!(context, 0, "Cannot create MVBOX-folder.",);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ impl Key {
|
||||
}
|
||||
|
||||
pub fn from_slice(bytes: &[u8], key_type: KeyType) -> Option<Self> {
|
||||
if bytes.is_empty() {
|
||||
if 0 == bytes.len() {
|
||||
return None;
|
||||
}
|
||||
let res: Result<Key, _> = match key_type {
|
||||
@@ -283,7 +283,7 @@ impl Key {
|
||||
Key::Public(_) => None,
|
||||
Key::Secret(k) => {
|
||||
let pub_key = k.public_key();
|
||||
pub_key.sign(k, || "".into()).map(Key::Public).ok()
|
||||
pub_key.sign(k, || "".into()).map(|k| Key::Public(k)).ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
#![deny(clippy::correctness)]
|
||||
// TODO: make all of these errors, such that clippy actually passes.
|
||||
#![warn(clippy::all, clippy::perf, clippy::not_unsafe_ptr_arg_deref)]
|
||||
// This is nice, but for now just annoying.
|
||||
#![allow(clippy::unreadable_literal)]
|
||||
#![feature(ptr_wrapping_offset_from)]
|
||||
#![feature(c_variadic, ptr_wrapping_offset_from, ptr_cast)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate failure_derive;
|
||||
|
||||
@@ -166,6 +166,7 @@ impl<'a> Peerstate<'a> {
|
||||
|
||||
pub fn from_addr(context: &'a Context, _sql: &Sql, addr: &str) -> Option<Self> {
|
||||
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE addr=? COLLATE NOCASE;";
|
||||
|
||||
Self::from_stmt(context, query, &[addr])
|
||||
}
|
||||
|
||||
@@ -190,11 +191,6 @@ impl<'a> Peerstate<'a> {
|
||||
context
|
||||
.sql
|
||||
.query_row(query, params, |row| {
|
||||
/* all the above queries start with this: SELECT
|
||||
addr, last_seen, last_seen_autocrypt, prefer_encrypted,
|
||||
public_key, gossip_timestamp, gossip_key, public_key_fingerprint,
|
||||
gossip_key_fingerprint, verified_key, verified_key_fingerprint
|
||||
*/
|
||||
let mut res = Self::new(context);
|
||||
|
||||
res.addr = Some(row.get(0)?);
|
||||
@@ -202,34 +198,13 @@ impl<'a> Peerstate<'a> {
|
||||
res.last_seen_autocrypt = row.get(2)?;
|
||||
res.prefer_encrypt = EncryptPreference::from_i32(row.get(3)?).unwrap_or_default();
|
||||
res.gossip_timestamp = row.get(5)?;
|
||||
let pkf: String = row.get(7)?;
|
||||
res.public_key_fingerprint = if pkf.is_empty() { None } else { Some(pkf) };
|
||||
let gkf: String = row.get(8)?;
|
||||
res.gossip_key_fingerprint = if gkf.is_empty() { None } else { Some(gkf) };
|
||||
let vkf: String = row.get(10)?;
|
||||
res.verified_key_fingerprint = if vkf.is_empty() { None } else { Some(vkf) };
|
||||
|
||||
res.public_key_fingerprint = row.get(7)?;
|
||||
if res
|
||||
.public_key_fingerprint
|
||||
.as_ref()
|
||||
.map(|s| s.is_empty())
|
||||
.unwrap_or_default()
|
||||
{
|
||||
res.public_key_fingerprint = None;
|
||||
}
|
||||
res.gossip_key_fingerprint = row.get(8)?;
|
||||
if res
|
||||
.gossip_key_fingerprint
|
||||
.as_ref()
|
||||
.map(|s| s.is_empty())
|
||||
.unwrap_or_default()
|
||||
{
|
||||
res.gossip_key_fingerprint = None;
|
||||
}
|
||||
res.verified_key_fingerprint = row.get(10)?;
|
||||
if res
|
||||
.verified_key_fingerprint
|
||||
.as_ref()
|
||||
.map(|s| s.is_empty())
|
||||
.unwrap_or_default()
|
||||
{
|
||||
res.verified_key_fingerprint = None;
|
||||
}
|
||||
res.public_key = row
|
||||
.get(4)
|
||||
.ok()
|
||||
@@ -242,8 +217,7 @@ impl<'a> Peerstate<'a> {
|
||||
.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() {
|
||||
res.verified_key = if vk == res.gossip_key {
|
||||
VerifiedKey::Gossip
|
||||
} else if vk == res.public_key {
|
||||
VerifiedKey::Public
|
||||
@@ -448,7 +422,6 @@ impl<'a> Peerstate<'a> {
|
||||
&self.addr,
|
||||
],
|
||||
).is_ok();
|
||||
assert_eq!(success, true);
|
||||
} else if self.to_save == Some(ToSave::Timestamps) {
|
||||
success = sql::execute(
|
||||
self.context,
|
||||
@@ -525,40 +498,6 @@ mod tests {
|
||||
assert_eq!(peerstate, peerstate_new);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peerstate_with_empty_gossip_key_save_to_db() {
|
||||
let ctx = crate::test_utils::dummy_context();
|
||||
let addr = "hello@mail.com";
|
||||
|
||||
let pub_key = crate::key::Key::from_base64("xsBNBFztUVkBCADYaQl/UOUpRPd32nLRzx8eU0eI+jQEnG+g5anjYA+3oct1rROGl5SygjMULDKdaUy27O3o9Srsti0YjA7uxZnavIqhSopJhFidqY1M1wA9JZa/duucZdNwUGbjGIRsS/4Cjr5+3svscK24hVYub1dvDWXpwUTnj3K6xOEnJdoM+MhCqtSD5+zcJhFc9vyZm9ZTGWUxAhKh0iJTcCD8V6CQ3XZ2z9GruwzZT/FTFovWrz7m3TUI2OdSSHh0eZLRGEoxMCT/vzflAFGAr8ijCaRsEIfqP6FW8uQWnFTqkjxEUCZG6XkeFHB84aj5jqYG/1KCLjL5vEKwfl1tz/WnPhY7ABEBAAHNEDxoZWxsb0BtYWlsLmNvbT7CwIkEEAEIADMCGQEFAlztUVoCGwMECwkIBwYVCAkKCwIDFgIBFiEEgMjHGVbvLXe6ioRROg8oKCvye7gACgkQOg8oKCvye7ijAwf+PTsuawUax9cNPn1bN90H+g9qyHZJMEwKXtUnNaXJxPW3iB7ThhpCiCzsZwP7+l7ArS8tmLeNDw2bENtcf1XCv4wovP2fdXOP3QOUUFX/GdakcTwv7DzC7CO0grB1HtaPhGw/6UX2o2cx2i9xiUf4Givq2MfCbgAW5zloH6WXGPb6yLQYJXxqDIphr4+uZDb+bMAyWHN/DUkAjHrV8nnVki7PMHqzzZpwglalxMX8RGeiGZE39ALJKL/Og87DMFah87/yoxQWGoS7Wqv0XDcCPKoTCPrpk8pOe2KEsq/lz215nefHd4aRpfUX5YCYa8HPvvfPQbGF73uvyQw5w7qjis7ATQRc7VFZAQgAt8ONdnX6KEEQ5Jw6ilJ+LBtY44SP5t0I3eK+goKepgIiKhjGDa+Mntyi4jdhH+HO6kvK5SHMh2sPp4rRO/WKHJwWFySyM1OdyiywhyH0J9R5rBY4vPHsJjf6vSKJdWLWT+ho1fNet2IIC+jVCYli91MAMbRvk6EKVj1nCc+67giOahXEkHt6xxkeCGlOvbw8hxGj1A8+AC1BLms/OR3oc4JMi9O3kq6uG0z9tlUEerac9HVwcjoO1XLe+hJhoT5H+TbnGjPuhuURP3pFiIKHpbRYgUfdSAY0dTObO7t4I5y/drPOrCTnWrBUg2wXAECUhpRKow9/ai2YemLv9KqhhwARAQABwsB2BBgBCAAgBQJc7VFaAhsMFiEEgMjHGVbvLXe6ioRROg8oKCvye7gACgkQOg8oKCvye7jmyggAhs4QzCzIbT2OsAReBxkxtm0AI+g1HZ1KFKof5NDHfgv9C/Qu1I8mKEjlZzA4qFyPmLqntgwJ0RuFy6gLbljZBNCFO7vB478AhYtnWjuKZmA40HUPwcB1hEJ31c42akzfUbioY1TLLepngdsJg7Cm8O+rhI9+1WRA66haJDgFs793SVUDyJh8f9NX50l5zR87/bsV30CFSw0q4OSSy9VI/z+2g5khn1LnuuOrCfFnYIPYtJED1BfkXkosxGlgbzy79VvGmI9d23x4atDK7oBPCzIj+lP8sytJ0u3HOguXi9OgDitKy+Pt1r8gH8frdktMJr5Ts6DW+tIn2vR23KR8aA==", KeyType::Public).unwrap();
|
||||
|
||||
let mut peerstate = Peerstate {
|
||||
context: &ctx.ctx,
|
||||
addr: Some(addr.into()),
|
||||
last_seen: 10,
|
||||
last_seen_autocrypt: 11,
|
||||
prefer_encrypt: EncryptPreference::Mutual,
|
||||
public_key: Some(pub_key.clone()),
|
||||
public_key_fingerprint: Some(pub_key.fingerprint()),
|
||||
gossip_key: None,
|
||||
gossip_timestamp: 12,
|
||||
gossip_key_fingerprint: 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), "failed to save");
|
||||
|
||||
let peerstate_new = Peerstate::from_addr(&ctx.ctx, &ctx.ctx.sql, addr.into())
|
||||
.expect("failed to load peerstate from db");
|
||||
|
||||
// clear to_save, as that is not persissted
|
||||
peerstate.to_save = None;
|
||||
assert_eq!(peerstate, peerstate_new);
|
||||
}
|
||||
|
||||
// TODO: don't copy this from stress.rs
|
||||
#[allow(dead_code)]
|
||||
struct TestContext {
|
||||
|
||||
13
src/pgp.rs
13
src/pgp.rs
@@ -2,7 +2,6 @@ use std::collections::HashSet;
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CStr;
|
||||
use std::io::Cursor;
|
||||
use std::ptr;
|
||||
|
||||
use pgp::composed::{
|
||||
Deserializable, KeyType as PgpKeyType, Message, SecretKeyParamsBuilder, SignedPublicKey,
|
||||
@@ -30,19 +29,19 @@ pub unsafe fn dc_split_armored_data(
|
||||
let mut line: *mut libc::c_char = buf;
|
||||
let mut p1: *mut libc::c_char = buf;
|
||||
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();
|
||||
let mut headerline: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
let mut base64: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
if !ret_headerline.is_null() {
|
||||
*ret_headerline = 0 as *const libc::c_char
|
||||
}
|
||||
if !ret_setupcodebegin.is_null() {
|
||||
*ret_setupcodebegin = ptr::null_mut();
|
||||
*ret_setupcodebegin = 0 as *const libc::c_char
|
||||
}
|
||||
if !ret_preferencrypt.is_null() {
|
||||
*ret_preferencrypt = ptr::null();
|
||||
*ret_preferencrypt = 0 as *const libc::c_char
|
||||
}
|
||||
if !ret_base64.is_null() {
|
||||
*ret_base64 = ptr::null();
|
||||
*ret_base64 = 0 as *const libc::c_char
|
||||
}
|
||||
if !(buf.is_null() || ret_headerline.is_null()) {
|
||||
dc_remove_cr_chars(buf);
|
||||
@@ -144,7 +143,7 @@ pub fn dc_pgp_create_keypair(addr: impl AsRef<str>) -> Option<(Key, Key)> {
|
||||
.key_type(PgpKeyType::Rsa(2048))
|
||||
.can_create_certificates(true)
|
||||
.can_sign(true)
|
||||
.primary_user_id(user_id)
|
||||
.primary_user_id(user_id.into())
|
||||
.passphrase(None)
|
||||
.preferred_symmetric_algorithms(smallvec![
|
||||
SymmetricKeyAlgorithm::AES256,
|
||||
|
||||
21
src/sql.rs
21
src/sql.rs
@@ -4,6 +4,7 @@ use std::sync::{Arc, RwLock};
|
||||
use rusqlite::{Connection, OpenFlags, Statement, NO_PARAMS};
|
||||
use thread_local_object::ThreadLocal;
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::{Error, Result};
|
||||
@@ -286,7 +287,7 @@ impl Sql {
|
||||
|
||||
fn table_exists(conn: &Connection, name: impl AsRef<str>) -> Result<bool> {
|
||||
let mut exists = false;
|
||||
conn.pragma(None, "table_info", &name.as_ref().to_string(), |_row| {
|
||||
conn.pragma(None, "table_info", &format!("{}", name.as_ref()), |_row| {
|
||||
// will only be executed if the info was found
|
||||
exists = true;
|
||||
Ok(())
|
||||
@@ -688,6 +689,10 @@ fn open(
|
||||
"ALTER TABLE msgs ADD COLUMN move_state INTEGER DEFAULT 1;",
|
||||
params![],
|
||||
)?;
|
||||
assert_eq!(DC_MOVE_STATE_UNDEFINED as libc::c_int, 0);
|
||||
assert_eq!(DC_MOVE_STATE_PENDING as libc::c_int, 1);
|
||||
assert_eq!(DC_MOVE_STATE_STAY as libc::c_int, 2);
|
||||
assert_eq!(DC_MOVE_STATE_MOVING as libc::c_int, 3);
|
||||
|
||||
dbversion = 48;
|
||||
sql.set_config_int(context, "dbversion", 48)?;
|
||||
@@ -830,7 +835,7 @@ where
|
||||
&err,
|
||||
querystr.as_ref()
|
||||
);
|
||||
Err(err)
|
||||
Err(err.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1003,10 +1008,10 @@ pub fn housekeeping(context: &Context) {
|
||||
let name_f = entry.file_name();
|
||||
let name_s = name_f.to_string_lossy();
|
||||
|
||||
if is_file_in_use(&files_in_use, None, &name_s)
|
||||
|| is_file_in_use(&files_in_use, Some(".increation"), &name_s)
|
||||
|| is_file_in_use(&files_in_use, Some(".waveform"), &name_s)
|
||||
|| is_file_in_use(&files_in_use, Some("-preview.jpg"), &name_s)
|
||||
if is_file_in_use(&mut files_in_use, None, &name_s)
|
||||
|| is_file_in_use(&mut files_in_use, Some(".increation"), &name_s)
|
||||
|| is_file_in_use(&mut files_in_use, Some(".waveform"), &name_s)
|
||||
|| is_file_in_use(&mut files_in_use, Some("-preview.jpg"), &name_s)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1042,8 +1047,8 @@ pub fn housekeeping(context: &Context) {
|
||||
unreferenced_count,
|
||||
entry.file_name()
|
||||
);
|
||||
let path = entry.path();
|
||||
dc_delete_file(context, path);
|
||||
let path = entry.path().to_c_string().unwrap();
|
||||
dc_delete_file(context, path.as_ptr());
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
@@ -2,15 +2,9 @@
|
||||
//!
|
||||
//! This module is only compiled for test runs.
|
||||
|
||||
use std::ffi::CStr;
|
||||
|
||||
use libc::uintptr_t;
|
||||
use tempfile::{tempdir, TempDir};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::constants::{Event, KeyType};
|
||||
use crate::context::{dc_context_new, dc_open, Context};
|
||||
use crate::key;
|
||||
use crate::types::dc_callback_t;
|
||||
|
||||
/// A Context and temporary directory.
|
||||
@@ -50,127 +44,3 @@ pub fn test_context(cb: Option<dc_callback_t>) -> TestContext {
|
||||
pub fn dummy_context() -> TestContext {
|
||||
test_context(None)
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn logging_cb(
|
||||
_ctx: &Context,
|
||||
evt: Event,
|
||||
_d1: uintptr_t,
|
||||
d2: uintptr_t,
|
||||
) -> uintptr_t {
|
||||
let to_str = |x| CStr::from_ptr(x as *const libc::c_char).to_str().unwrap();
|
||||
match evt {
|
||||
Event::INFO => println!("I: {}", to_str(d2)),
|
||||
Event::WARNING => println!("W: {}", to_str(d2)),
|
||||
Event::ERROR => println!("E: {}", to_str(d2)),
|
||||
_ => (),
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
/// Creates Alice with a pre-generated keypair.
|
||||
///
|
||||
/// Returns the address of the keypair created (alice@example.org).
|
||||
pub fn configure_alice_keypair(ctx: &Context) -> String {
|
||||
let addr = String::from("alice@example.org");
|
||||
ctx.set_config(Config::ConfiguredAddr, Some(&addr)).unwrap();
|
||||
|
||||
// The keypair was created using:
|
||||
// let (public, private) = crate::pgp::dc_pgp_create_keypair("alice@example.com")
|
||||
// .unwrap();
|
||||
// println!("{}", public.to_base64(64));
|
||||
// println!("{}", private.to_base64(64));
|
||||
let public = key::Key::from_base64(
|
||||
concat!(
|
||||
"xsBNBF086ewBCACmJKuoxIO6T87yi4Q3MyNpMch3Y8KrtHDQyUszU36eqM3Pmd1l",
|
||||
"FrbcCd8ZWo2pq6OJSwsM/jjRGn1zo2YOaQeJRRrC+KrKGqSUtRSYQBPrPjE2YjSX",
|
||||
"AMbu8jBI6VVUhHeghriBkK79PY9O/oRhIJC0p14IJe6CQ6OI2fTmTUHF9i/nJ3G4",
|
||||
"Wb3/K1bU3yVfyPZjTZQPYPvvh03vxHULKurtYkX5DTEMSWsF4qzLMps+l87VuLV9",
|
||||
"iQnbN7YMRLHHx2KkX5Ivi7JCefhCa54M0K3bDCCxuVWAM5wjQwNZjzR+WL+dYchw",
|
||||
"oFvuF8NrlzjM9dSv+2rn+J7f99ijSXarzPC7ABEBAAHNEzxhbGljZUBleGFtcGxl",
|
||||
"LmNvbT7CwIkEEAEIADMCGQEFAl086fgCGwMECwkIBwYVCAkKCwIDFgIBFiEE+iai",
|
||||
"x4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcei3ogf/cruUmQ+th52TFHTHdkw9",
|
||||
"OHUl3MrXtZ7QmHyOAFvbXE/6n5Eeh+eZoF8MWWV72m14Wbs+vTcNQkFVTdOPptkK",
|
||||
"A8e4cJqwDOHsyAnvQXZ7WNje9+BMzcoipIUawHP4ORFaPDsKLZQ0b4wBbKn8ziea",
|
||||
"6zjGF0/qljTdoxTtsYpv5wXYuhwbYklrLOqgSa5M7LXUe7E3g9mbg+9iX1GuB8m6",
|
||||
"GkquJN814Y+xny4xhZzGOfue6SeP12jJMNSjSP7416dRq7794VGnkkW9V/7oFEUK",
|
||||
"u5wO9FFbgDySOSlEjByGejSGuBmho0iJSjcPjZ7EY/j3M3orq4dpza5C82OeSvxD",
|
||||
"Fc7ATQRdPOnsAQgA5oLxXRLnyugzOmNCy7dxV3JrDZscA6JNlJlDWIShT0YSs+zG",
|
||||
"9JzDeQql+sYXgUSxOoIayItuXtnFn7tstwGoOnYvadm/e5/7V5fKAQRtCtdN51av",
|
||||
"62n18Venlm0yNKpROPcZ6M/sc4m6uU6YRZ/a1idal8VGY0wLKlghjIBuIiBoVQ/R",
|
||||
"noW+/fhmwIg08dQ5m8hQe3GEOZEeLrTWL/9awPlXK7Y+DmJOoR4qbHWEcRfbzS6q",
|
||||
"4zW8vk2ztB8ngwbnqYy8zrN1DCICN1gYdlU++uVw6Bb1XfY8Cdldh1VLKpF35mAm",
|
||||
"jxLZfVDcoObFH3Cv2GB7BEYxv86KC2Y6T74Q/wARAQABwsB2BBgBCAAgBQJdPOn4",
|
||||
"AhsMFiEE+iaix4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcegLxwf/dXshJnoW",
|
||||
"qEnRsf6rVb9/Mc66ti+NVQLfNd275dybh/QIJdK3NmSxdnTPIEJRVspJywJoupwX",
|
||||
"FNrnHG2Ff6QPvHqI+/oNu986r9d7Z1oQibbLHKt8t6kpOfg/xGxotagJuiCQvR9m",
|
||||
"MjD1DqsdB37SjDxGupZOOJSXWi6KX60IE+uM+QOBfeOZziQwuFmA5wV6RDXIeYJf",
|
||||
"qrcbeXeR1d0nfNpPHQR1gBiqmxNb6KBbdXD2+EXW60axC7D2b1APmzMlammDliPw",
|
||||
"sK9U1rc9nuquEBvGDOJf4K+Dzn+mDCqRpP6uAuQ7RKHyim4uyN0wwKObzPqgJCGw",
|
||||
"jTglkixw+aSTXw=="
|
||||
),
|
||||
KeyType::Public,
|
||||
)
|
||||
.unwrap();
|
||||
let private = key::Key::from_base64(
|
||||
concat!(
|
||||
"xcLYBF086ewBCACmJKuoxIO6T87yi4Q3MyNpMch3Y8KrtHDQyUszU36eqM3Pmd1l",
|
||||
"FrbcCd8ZWo2pq6OJSwsM/jjRGn1zo2YOaQeJRRrC+KrKGqSUtRSYQBPrPjE2YjSX",
|
||||
"AMbu8jBI6VVUhHeghriBkK79PY9O/oRhIJC0p14IJe6CQ6OI2fTmTUHF9i/nJ3G4",
|
||||
"Wb3/K1bU3yVfyPZjTZQPYPvvh03vxHULKurtYkX5DTEMSWsF4qzLMps+l87VuLV9",
|
||||
"iQnbN7YMRLHHx2KkX5Ivi7JCefhCa54M0K3bDCCxuVWAM5wjQwNZjzR+WL+dYchw",
|
||||
"oFvuF8NrlzjM9dSv+2rn+J7f99ijSXarzPC7ABEBAAEACAChqzVOuErmVRqvcYtq",
|
||||
"m1xt1H+ZjX20z5Sn1fhTLYAcq236AWMqJvwxCXoKlc8bt2UfB+Ls9cQb1YcVq353",
|
||||
"r0QiExiDeK3YlCxqd/peXJwFYTNKFC3QcnUhtpG9oS/jWjN+BRotGbjtu6Vj3M68",
|
||||
"JJAq+mHJ0/9OyrqrREvGfo7uLZt7iMGemDlrDakvrbIyZrPLgay+nZ3dEFKeOQ6F",
|
||||
"FrU05jyUVdoHBy0Tqx/6VpFUX9+IHcMHL2lTJB0nynBj+XZ/G4aX3WYoo3YlixHb",
|
||||
"Iu35fGFA0TChoGaGPzqcI/kg2Z+b/BryG9NM3LA2cO8iGrGXAE1nPFp91jmCrQ3V",
|
||||
"WushBADERP+uojjjfdO5J+RkmcFe9mFYDdtkhN+kV+LdePjiNNtcXMBhasstio0S",
|
||||
"ut0GKnE7DFRhX7mkN9w2apJ2ooeFeVVWot18eSdp6Rzh6/1Z7TmhYFJ3oUxxLbnQ",
|
||||
"sWIXIec1SzqWBFJUCn3IP0mCnJktFg/uGW6yLs01r5ds52uSBQQA2LSWiTwk9tEm",
|
||||
"dr9mz3tHnmrkyGiyKhKGM1Z7Rch63D5yQc1s4kUMBlyuLL2QtM/e4dtaz2JAkO8k",
|
||||
"QrYCnNgJ+2roTAK3kDZgYtymjdvK3HpQNtjVo7dds5RJVb6U618phZwU5WNFAEJW",
|
||||
"yyImmycGfjLv+18cW/3mq0QVZejkM78D/2kHaIeJAowtBOFY2zDrKyDRoBHaUSgj",
|
||||
"5BjGoviRC5rYihWDEyYDQ6mBJQstAD0Ty3MYzyUxl6ruB/BMWnMDFq5+TqtdBzu3",
|
||||
"jCtZ8OEyH8A5Kdo68Wzo/PGxzMtusOdNj9+3PBmSq4yibJxbLSrn59aVUYpGLjeG",
|
||||
"Kyvm9OTKkrOGN27NEzxhbGljZUBleGFtcGxlLmNvbT7CwIkEEAEIADMCGQEFAl08",
|
||||
"6fgCGwMECwkIBwYVCAkKCwIDFgIBFiEE+iaix4d0doj87Q0ek6DcNkbrcegACgkQ",
|
||||
"k6DcNkbrcei3ogf/cruUmQ+th52TFHTHdkw9OHUl3MrXtZ7QmHyOAFvbXE/6n5Ee",
|
||||
"h+eZoF8MWWV72m14Wbs+vTcNQkFVTdOPptkKA8e4cJqwDOHsyAnvQXZ7WNje9+BM",
|
||||
"zcoipIUawHP4ORFaPDsKLZQ0b4wBbKn8ziea6zjGF0/qljTdoxTtsYpv5wXYuhwb",
|
||||
"YklrLOqgSa5M7LXUe7E3g9mbg+9iX1GuB8m6GkquJN814Y+xny4xhZzGOfue6SeP",
|
||||
"12jJMNSjSP7416dRq7794VGnkkW9V/7oFEUKu5wO9FFbgDySOSlEjByGejSGuBmh",
|
||||
"o0iJSjcPjZ7EY/j3M3orq4dpza5C82OeSvxDFcfC2ARdPOnsAQgA5oLxXRLnyugz",
|
||||
"OmNCy7dxV3JrDZscA6JNlJlDWIShT0YSs+zG9JzDeQql+sYXgUSxOoIayItuXtnF",
|
||||
"n7tstwGoOnYvadm/e5/7V5fKAQRtCtdN51av62n18Venlm0yNKpROPcZ6M/sc4m6",
|
||||
"uU6YRZ/a1idal8VGY0wLKlghjIBuIiBoVQ/RnoW+/fhmwIg08dQ5m8hQe3GEOZEe",
|
||||
"LrTWL/9awPlXK7Y+DmJOoR4qbHWEcRfbzS6q4zW8vk2ztB8ngwbnqYy8zrN1DCIC",
|
||||
"N1gYdlU++uVw6Bb1XfY8Cdldh1VLKpF35mAmjxLZfVDcoObFH3Cv2GB7BEYxv86K",
|
||||
"C2Y6T74Q/wARAQABAAgAhSvFEYZoj1sSrXrHDjZOrryViGjCCH9t3pmkxLDrGIdd",
|
||||
"KsFyN8ORUo6KUZS745yx3yFnI9EZ1IZvm9aF+jxk2lGJFtgLvfoxFOvGckwCSy8T",
|
||||
"/MCiJZkz01hWo5s2VCLJheWL/GqTKjS5wXDcm+y8Wtilh+UawycdlDsSNr/D4MZL",
|
||||
"j3Chq9K03l5UIR8DcC7SavNi55R2oGOfboXsdvwOlrNZdCkZOlXDI4ZKFwbDHCtp",
|
||||
"Do5FS30hnJi2TecUPZWB1CaGFWnevINd4ikugVjcAoZj/QAIvfrOCgqisF/Ylg9u",
|
||||
"RMUPBapmcJUueILwd0iQqvGG0aCqtchvSmlg15/lQQQA9G1NNjNAH+NQrXvDJFJe",
|
||||
"/V1U3F3pz7jCjQa69c0dxSBUeNX1pG8XXD6tSkkd4Ni1mzZGcZXOmVUM6cA9I7RH",
|
||||
"95RqV+QIfnXVneCRrlCjV8m6OBlkivkESXc3nW5wtCIfw7oKg9w1xuVNUaAlbCt9",
|
||||
"QVLaxXJiY7ad0f5U9XJ1+w8EAPFs+M/+GZK1wOZYBL1vo7x0gL9ZggmjC4B+viBJ",
|
||||
"8Q60mqTrphYFsbXHuwKV0g9aIoZMucKyEE0QLR7imttiLEz1nD8bfEScbGy9ZG//",
|
||||
"wRfyJmCVAjA0pQ6LtB93d70PSVzzJrMHgbLKrDuSd6RChl7n9BIEdVyk7LEph0Yg",
|
||||
"9UsRBADm6DvpKL+P3lQ0eLTfAgcQTOqLZDYmI3PvqqSkHb1kHChqOXXs8hGOSSwK",
|
||||
"Gjcd4CZeNOGWR42rZyRhVgtkt6iYviIaVAWUfme6K+sLQBCeyMlmEGtykAA+LmPB",
|
||||
"f4zdyUNADfoxgZF3EKHf6I3nlVn5cdT+o/9vjdY2XAOwcls1RzaFwsB2BBgBCAAg",
|
||||
"BQJdPOn4AhsMFiEE+iaix4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcegLxwf/",
|
||||
"dXshJnoWqEnRsf6rVb9/Mc66ti+NVQLfNd275dybh/QIJdK3NmSxdnTPIEJRVspJ",
|
||||
"ywJoupwXFNrnHG2Ff6QPvHqI+/oNu986r9d7Z1oQibbLHKt8t6kpOfg/xGxotagJ",
|
||||
"uiCQvR9mMjD1DqsdB37SjDxGupZOOJSXWi6KX60IE+uM+QOBfeOZziQwuFmA5wV6",
|
||||
"RDXIeYJfqrcbeXeR1d0nfNpPHQR1gBiqmxNb6KBbdXD2+EXW60axC7D2b1APmzMl",
|
||||
"ammDliPwsK9U1rc9nuquEBvGDOJf4K+Dzn+mDCqRpP6uAuQ7RKHyim4uyN0wwKOb",
|
||||
"zPqgJCGwjTglkixw+aSTXw=="
|
||||
),
|
||||
KeyType::Private,
|
||||
)
|
||||
.unwrap();
|
||||
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
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ pub use rusqlite::ffi::*;
|
||||
pub type dc_callback_t =
|
||||
unsafe extern "C" fn(_: &Context, _: Event, _: uintptr_t, _: uintptr_t) -> uintptr_t;
|
||||
|
||||
pub type dc_move_state_t = u32;
|
||||
|
||||
pub type dc_receive_imf_t = unsafe fn(
|
||||
_: &Context,
|
||||
_: *const libc::c_char,
|
||||
|
||||
148
tests/stress.rs
148
tests/stress.rs
@@ -10,6 +10,7 @@ use deltachat::config;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::contact::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_array::*;
|
||||
use deltachat::dc_chat::*;
|
||||
use deltachat::dc_configure::*;
|
||||
use deltachat::dc_imex::*;
|
||||
@@ -56,15 +57,39 @@ unsafe fn stress_functions(context: &Context) {
|
||||
);
|
||||
|
||||
if 0 != dc_is_open(context) {
|
||||
if dc_file_exist(context, "$BLOBDIR/foobar")
|
||||
|| dc_file_exist(context, "$BLOBDIR/dada")
|
||||
|| dc_file_exist(context, "$BLOBDIR/foobar.dadada")
|
||||
|| dc_file_exist(context, "$BLOBDIR/foobar-folder")
|
||||
if 0 != dc_file_exist(
|
||||
context,
|
||||
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
|
||||
) || 0
|
||||
!= dc_file_exist(
|
||||
context,
|
||||
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
|| 0 != dc_file_exist(
|
||||
context,
|
||||
b"$BLOBDIR/foobar.dadada\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
|| 0 != dc_file_exist(
|
||||
context,
|
||||
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
{
|
||||
dc_delete_file(context, "$BLOBDIR/foobar");
|
||||
dc_delete_file(context, "$BLOBDIR/dada");
|
||||
dc_delete_file(context, "$BLOBDIR/foobar.dadada");
|
||||
dc_delete_file(context, "$BLOBDIR/foobar-folder");
|
||||
dc_delete_file(
|
||||
context,
|
||||
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
dc_delete_file(
|
||||
context,
|
||||
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
dc_delete_file(
|
||||
context,
|
||||
b"$BLOBDIR/foobar.dadada\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
dc_delete_file(
|
||||
context,
|
||||
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
}
|
||||
dc_write_file(
|
||||
context,
|
||||
@@ -72,10 +97,25 @@ unsafe fn stress_functions(context: &Context) {
|
||||
b"content\x00" as *const u8 as *const libc::c_char as *const libc::c_void,
|
||||
7i32 as size_t,
|
||||
);
|
||||
assert!(dc_file_exist(context, "$BLOBDIR/foobar",));
|
||||
assert!(!dc_file_exist(context, "$BLOBDIR/foobarx"));
|
||||
assert_ne!(
|
||||
0,
|
||||
dc_file_exist(
|
||||
context,
|
||||
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
dc_get_filebytes(context, "$BLOBDIR/foobar",),
|
||||
0,
|
||||
dc_file_exist(
|
||||
context,
|
||||
b"$BLOBDIR/foobarx\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
dc_get_filebytes(
|
||||
context,
|
||||
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
|
||||
),
|
||||
7i32 as libc::c_ulonglong
|
||||
);
|
||||
|
||||
@@ -93,10 +133,23 @@ unsafe fn stress_functions(context: &Context) {
|
||||
context,
|
||||
b"/BLOBDIR/fofo\x00" as *const u8 as *const libc::c_char,
|
||||
));
|
||||
assert!(dc_file_exist(context, as_path(abs_path)));
|
||||
assert_ne!(0, dc_file_exist(context, abs_path));
|
||||
free(abs_path as *mut libc::c_void);
|
||||
assert!(dc_copy_file(context, "$BLOBDIR/foobar", "$BLOBDIR/dada",));
|
||||
assert_eq!(dc_get_filebytes(context, "$BLOBDIR/dada",), 7);
|
||||
assert_ne!(
|
||||
0,
|
||||
dc_copy_file(
|
||||
context,
|
||||
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
|
||||
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
dc_get_filebytes(
|
||||
context,
|
||||
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
|
||||
),
|
||||
7
|
||||
);
|
||||
|
||||
let mut buf: *mut libc::c_void = 0 as *mut libc::c_void;
|
||||
let mut buf_bytes: size_t = 0;
|
||||
@@ -117,11 +170,41 @@ unsafe fn stress_functions(context: &Context) {
|
||||
);
|
||||
|
||||
free(buf as *mut _);
|
||||
assert!(dc_delete_file(context, "$BLOBDIR/foobar"));
|
||||
assert!(dc_delete_file(context, "$BLOBDIR/dada"));
|
||||
assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder"));
|
||||
assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",));
|
||||
assert!(dc_delete_file(context, "$BLOBDIR/foobar-folder"));
|
||||
assert_ne!(
|
||||
0,
|
||||
dc_delete_file(
|
||||
context,
|
||||
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
);
|
||||
assert_ne!(
|
||||
0,
|
||||
dc_delete_file(
|
||||
context,
|
||||
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
);
|
||||
assert_ne!(
|
||||
0,
|
||||
dc_create_folder(
|
||||
context,
|
||||
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
);
|
||||
assert_ne!(
|
||||
0,
|
||||
dc_file_exist(
|
||||
context,
|
||||
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
);
|
||||
assert_ne!(
|
||||
0,
|
||||
dc_delete_file(
|
||||
context,
|
||||
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
|
||||
)
|
||||
);
|
||||
let fn0: *mut libc::c_char = dc_get_fine_pathNfilename(
|
||||
context,
|
||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
||||
@@ -154,7 +237,7 @@ unsafe fn stress_functions(context: &Context) {
|
||||
),
|
||||
0
|
||||
);
|
||||
assert!(dc_delete_file(context, as_path(fn0)));
|
||||
assert_ne!(0, dc_delete_file(context, fn0));
|
||||
free(fn0 as *mut libc::c_void);
|
||||
free(fn1 as *mut libc::c_void);
|
||||
}
|
||||
@@ -742,14 +825,22 @@ fn test_dc_mimeparser_with_context() {
|
||||
"inner-subject",
|
||||
);
|
||||
|
||||
let mut of: *mut mailimf_optional_field =
|
||||
dc_mimeparser_lookup_optional_field(&mimeparser, "X-Special-A");
|
||||
let mut of: *mut mailimf_optional_field = dc_mimeparser_lookup_optional_field(
|
||||
&mimeparser,
|
||||
b"X-Special-A\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
assert_eq!(as_str((*of).fld_value as *const libc::c_char), "special-a",);
|
||||
|
||||
of = dc_mimeparser_lookup_optional_field(&mimeparser, "Foo");
|
||||
of = dc_mimeparser_lookup_optional_field(
|
||||
&mimeparser,
|
||||
b"Foo\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
assert_eq!(as_str((*of).fld_value as *const libc::c_char), "Bar",);
|
||||
|
||||
of = dc_mimeparser_lookup_optional_field(&mimeparser, "Chat-Version");
|
||||
of = dc_mimeparser_lookup_optional_field(
|
||||
&mimeparser,
|
||||
b"Chat-Version\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
assert_eq!(as_str((*of).fld_value as *const libc::c_char), "1.0",);
|
||||
assert_eq!(mimeparser.parts.len(), 1);
|
||||
|
||||
@@ -800,16 +891,19 @@ fn test_get_contacts() {
|
||||
unsafe {
|
||||
let context = create_test_context();
|
||||
let contacts = Contact::get_all(&context.ctx, 0, Some("some2")).unwrap();
|
||||
assert_eq!(contacts.len(), 0);
|
||||
assert_eq!(dc_array_get_cnt(contacts), 0);
|
||||
dc_array_unref(contacts);
|
||||
|
||||
let id = Contact::create(&context.ctx, "bob", "bob@mail.de").unwrap();
|
||||
assert_ne!(id, 0);
|
||||
|
||||
let contacts = Contact::get_all(&context.ctx, 0, Some("bob")).unwrap();
|
||||
assert_eq!(contacts.len(), 1);
|
||||
assert_eq!(dc_array_get_cnt(contacts), 1);
|
||||
dc_array_unref(contacts);
|
||||
|
||||
let contacts = Contact::get_all(&context.ctx, 0, Some("alice")).unwrap();
|
||||
assert_eq!(contacts.len(), 0);
|
||||
assert_eq!(dc_array_get_cnt(contacts), 0);
|
||||
dc_array_unref(contacts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user