Compare commits

..

4 Commits

59 changed files with 4500 additions and 4036 deletions

View File

@@ -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
View File

@@ -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"

View File

@@ -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]]

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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/

View File

@@ -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

View File

@@ -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"]

View File

@@ -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*);
/**

View File

@@ -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)

View File

@@ -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"

View File

@@ -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()
}

View File

@@ -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.");
}

View File

@@ -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)?,
}

View File

@@ -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

View File

@@ -37,3 +37,16 @@ Message
.. autoclass:: deltachat.message.Message
:members:
MessageType
------------
.. autoclass:: deltachat.message.MessageType
:members:
MessageState
------------
.. autoclass:: deltachat.message.MessageState
:members:

View File

@@ -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.

View File

@@ -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([

View File

@@ -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':

View File

@@ -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:

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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 "$@"

View File

@@ -1 +1 @@
nightly-2019-08-13
nightly-2019-07-10

View File

@@ -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 {

View File

@@ -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),
}

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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);
}
}

View File

@@ -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) };
}
}

View File

@@ -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,
)
};

File diff suppressed because it is too large Load Diff

View File

@@ -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,

View File

@@ -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());
}
}
}

View File

@@ -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, &param1_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>"));

View File

@@ -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) {

View File

@@ -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)
},

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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

View File

@@ -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) {

View File

@@ -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"&lt;&gt;&quot;&apos;&amp; &auml;&Auml;&ouml;&Ouml;&uuml;&Uuml;&szlig; foo&AElig;&ccedil;&Ccedil; &diams;&noent;&lrm;&rlm;&zwnj;&zwj;\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,

View File

@@ -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) {

File diff suppressed because it is too large Load Diff

View File

@@ -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) => {

View File

@@ -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.",);
}
}
}

View File

@@ -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()
}
}
}

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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) => {

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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);
}
}