Skip to content

Commit

Permalink
Merge tag 'v1.123.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
link2xt committed Sep 22, 2023
2 parents 061d091 + aa78e82 commit 59a3bc0
Show file tree
Hide file tree
Showing 20 changed files with 191 additions and 118 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## [1.123.0] - 2023-09-22

### API-Changes

- Make it possible to import secret key from a file with `DC_IMEX_IMPORT_SELF_KEYS`.
- [**breaking**] Make `dc_jsonrpc_blocking_call` accept JSON-RPC request.

### Fixes

- `lookup_chat_by_reply()`: Skip not fully downloaded and undecipherable messages ([#4676](https://github.com/deltachat/deltachat-core-rust/pull/4676)).
- `lookup_chat_by_reply()`: Skip undecipherable parent messages created by older versions ([#4676](https://github.com/deltachat/deltachat-core-rust/pull/4676)).
- imex: Use "default" in the filename of the default key.

### Miscellaneous Tasks

- Update OpenSSL from 3.1.2 to 3.1.3.

## [1.122.0] - 2023-09-12

### API-Changes
Expand Down Expand Up @@ -2816,3 +2833,4 @@ https://github.com/deltachat/deltachat-core-rust/pulls?q=is%3Apr+is%3Aclosed
[1.120.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.119.1...v1.120.0
[1.121.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.120.0...v1.121.0
[1.122.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.121.0...v1.122.0
[1.123.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.122.0...v1.123.0
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "deltachat"
version = "1.122.0"
version = "1.123.0"
edition = "2021"
license = "MPL-2.0"
rust-version = "1.67"
Expand Down
2 changes: 1 addition & 1 deletion deltachat-ffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "deltachat_ffi"
version = "1.122.0"
version = "1.123.0"
description = "Deltachat FFI"
edition = "2018"
readme = "README.md"
Expand Down
8 changes: 4 additions & 4 deletions deltachat-ffi/deltachat.h
Original file line number Diff line number Diff line change
Expand Up @@ -2273,6 +2273,7 @@ dc_contact_t* dc_get_contact (dc_context_t* context, uint32_t co
*
* - **DC_IMEX_IMPORT_SELF_KEYS** (2) - Import private keys found in the directory given as `param1`.
* The last imported key is made the default keys unless its name contains the string `legacy`. Public keys are not imported.
* If `param1` is a filename, import the private key from the file and make it the default.
*
* While dc_imex() returns immediately, the started job may take a while,
* you can stop it using dc_stop_ongoing_process(). During execution of the job,
Expand Down Expand Up @@ -5770,12 +5771,11 @@ char* dc_jsonrpc_next_response(dc_jsonrpc_instance_t* jsonrpc_instance);
*
* @memberof dc_jsonrpc_instance_t
* @param jsonrpc_instance jsonrpc instance as returned from dc_jsonrpc_init().
* @param method JSON-RPC method name, e.g. `check_email_validity`.
* @param params JSON-RPC method parameters, e.g. `["[email protected]"]`.
* @param input JSON-RPC request.
* @return JSON-RPC response as string, must be freed using dc_str_unref() after usage.
* On error, NULL is returned.
* If there is no response, NULL is returned.
*/
char* dc_jsonrpc_blocking_call(dc_jsonrpc_instance_t* jsonrpc_instance, const char *method, const char *params);
char* dc_jsonrpc_blocking_call(dc_jsonrpc_instance_t* jsonrpc_instance, const char *input);

/**
* @class dc_event_emitter_t
Expand Down
25 changes: 12 additions & 13 deletions deltachat-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4986,7 +4986,7 @@ pub unsafe extern "C" fn dc_accounts_get_event_emitter(
#[cfg(feature = "jsonrpc")]
mod jsonrpc {
use deltachat_jsonrpc::api::CommandApi;
use deltachat_jsonrpc::yerpc::{OutReceiver, RpcClient, RpcServer, RpcSession};
use deltachat_jsonrpc::yerpc::{OutReceiver, RpcClient, RpcSession};

use super::*;

Expand Down Expand Up @@ -5062,25 +5062,24 @@ mod jsonrpc {
#[no_mangle]
pub unsafe extern "C" fn dc_jsonrpc_blocking_call(
jsonrpc_instance: *mut dc_jsonrpc_instance_t,
method: *const libc::c_char,
params: *const libc::c_char,
input: *const libc::c_char,
) -> *mut libc::c_char {
if jsonrpc_instance.is_null() {
eprintln!("ignoring careless call to dc_jsonrpc_blocking_call()");
return ptr::null_mut();
}
let api = &*jsonrpc_instance;
let method = to_string_lossy(method);
let params = to_string_lossy(params);
let params: Option<yerpc::Params> = match serde_json::from_str(&params) {
Ok(params) => Some(params),
Err(_) => None,
};
let params = params.map(yerpc::Params::into_value).unwrap_or_default();
let res = block_on(api.handle.server().handle_request(method, params));
let input = to_string_lossy(input);
let res = block_on(api.handle.process_incoming(&input));
match res {
Ok(res) => res.to_string().strdup(),
Err(_) => ptr::null_mut(),
Some(message) => {
if let Ok(message) = serde_json::to_string(&message) {
message.strdup()
} else {
ptr::null_mut()
}
}
None => ptr::null_mut(),
}
}
}
2 changes: 1 addition & 1 deletion deltachat-jsonrpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "deltachat-jsonrpc"
version = "1.122.0"
version = "1.123.0"
description = "DeltaChat JSON-RPC API"
edition = "2021"
default-run = "deltachat-jsonrpc-server"
Expand Down
2 changes: 2 additions & 0 deletions deltachat-jsonrpc/src/api/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ pub enum DownloadState {
Done,
Available,
Failure,
Undecipherable,
InProgress,
}

Expand All @@ -327,6 +328,7 @@ impl From<download::DownloadState> for DownloadState {
download::DownloadState::Done => DownloadState::Done,
download::DownloadState::Available => DownloadState::Available,
download::DownloadState::Failure => DownloadState::Failure,
download::DownloadState::Undecipherable => DownloadState::Undecipherable,
download::DownloadState::InProgress => DownloadState::InProgress,
}
}
Expand Down
2 changes: 1 addition & 1 deletion deltachat-jsonrpc/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,5 @@
},
"type": "module",
"types": "dist/deltachat.d.ts",
"version": "1.122.0"
"version": "1.123.0"
}
2 changes: 1 addition & 1 deletion deltachat-repl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "deltachat-repl"
version = "1.122.0"
version = "1.123.0"
license = "MPL-2.0"
edition = "2021"

Expand Down
1 change: 1 addition & 0 deletions deltachat-repl/src/cmdline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ async fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: &Message) {
DownloadState::Available => " [⬇ Download available]",
DownloadState::InProgress => " [⬇ Download in progress...]️",
DownloadState::Failure => " [⬇ Download failed]",
DownloadState::Undecipherable => " [⬇ Decryption failed]",
};

let temp2 = timestamp_to_str(msg.get_timestamp());
Expand Down
2 changes: 1 addition & 1 deletion deltachat-rpc-server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "deltachat-rpc-server"
version = "1.122.0"
version = "1.123.0"
description = "DeltaChat JSON-RPC server"
edition = "2021"
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,5 @@
"test:mocha": "mocha -r esm node/test/test.js --growl --reporter=spec --bail --exit"
},
"types": "node/dist/index.d.ts",
"version": "1.122.0"
"version": "1.123.0"
}
29 changes: 23 additions & 6 deletions python/tests/test_4_lowlevel.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
from queue import Queue

import deltachat as dc
Expand Down Expand Up @@ -227,10 +228,26 @@ def test_jsonrpc_blocking_call(tmp_path):
lib.dc_accounts_unref,
)
jsonrpc = ffi.gc(lib.dc_jsonrpc_init(accounts), lib.dc_jsonrpc_unref)
res = from_optional_dc_charpointer(
lib.dc_jsonrpc_blocking_call(jsonrpc, b"check_email_validity", b'["[email protected]"]'),
res = json.loads(
from_optional_dc_charpointer(
lib.dc_jsonrpc_blocking_call(
jsonrpc,
json.dumps(
{"jsonrpc": "2.0", "method": "check_email_validity", "params": ["[email protected]"], "id": "123"},
).encode("utf-8"),
),
),
)
assert res == "true"

res = from_optional_dc_charpointer(lib.dc_jsonrpc_blocking_call(jsonrpc, b"check_email_validity", b'["alice"]'))
assert res == "false"
assert res == {"jsonrpc": "2.0", "id": "123", "result": True}

res = json.loads(
from_optional_dc_charpointer(
lib.dc_jsonrpc_blocking_call(
jsonrpc,
json.dumps(
{"jsonrpc": "2.0", "method": "check_email_validity", "params": ["alice"], "id": "456"},
).encode("utf-8"),
),
),
)
assert res == {"jsonrpc": "2.0", "id": "456", "result": False}
2 changes: 1 addition & 1 deletion release-date.in
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2023-09-12
2023-09-22
47 changes: 17 additions & 30 deletions src/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::constants::{
use crate::contact::{Contact, ContactId, Origin, VerifiedStatus};
use crate::context::Context;
use crate::debug_logging::maybe_set_logging_xdc;
use crate::download::DownloadState;
use crate::ephemeral::Timer as EphemeralTimer;
use crate::events::EventType;
use crate::html::new_html_mimepart;
Expand Down Expand Up @@ -1052,11 +1053,14 @@ impl ChatId {
T: Send + 'static,
{
let sql = &context.sql;
// Do not reply to not fully downloaded messages. Such a message could be a group chat
// message that we assigned to 1:1 chat.
let query = format!(
"SELECT {fields} \
FROM msgs WHERE chat_id=? AND state NOT IN (?, ?) AND NOT hidden \
FROM msgs WHERE chat_id=? AND state NOT IN (?, ?) AND NOT hidden AND download_state={} \
ORDER BY timestamp DESC, id DESC \
LIMIT 1;"
LIMIT 1;",
DownloadState::Done as u32,
);
let row = sql
.query_row_optional(
Expand All @@ -1081,34 +1085,17 @@ impl ChatId {
self,
context: &Context,
) -> Result<Option<(String, String, String)>> {
if let Some((rfc724_mid, mime_in_reply_to, mime_references, error)) = self
.parent_query(
context,
"rfc724_mid, mime_in_reply_to, mime_references, error",
|row: &rusqlite::Row| {
let rfc724_mid: String = row.get(0)?;
let mime_in_reply_to: String = row.get(1)?;
let mime_references: String = row.get(2)?;
let error: String = row.get(3)?;
Ok((rfc724_mid, mime_in_reply_to, mime_references, error))
},
)
.await?
{
if !error.is_empty() {
// Do not reply to error messages.
//
// An error message could be a group chat message that we failed to decrypt and
// assigned to 1:1 chat. A reply to it will show up as a reply to group message
// on the other side. To avoid such situations, it is better not to reply to
// error messages at all.
Ok(None)
} else {
Ok(Some((rfc724_mid, mime_in_reply_to, mime_references)))
}
} else {
Ok(None)
}
self.parent_query(
context,
"rfc724_mid, mime_in_reply_to, mime_references",
|row: &rusqlite::Row| {
let rfc724_mid: String = row.get(0)?;
let mime_in_reply_to: String = row.get(1)?;
let mime_references: String = row.get(2)?;
Ok((rfc724_mid, mime_in_reply_to, mime_references))
},
)
.await
}

/// Returns multi-line text summary of encryption preferences of all chat contacts.
Expand Down
7 changes: 6 additions & 1 deletion src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ pub enum DownloadState {
/// Failed to fully download the message.
Failure = 20,

/// Undecipherable message.
Undecipherable = 30,

/// Full download of the message is in progress.
InProgress = 1000,
}
Expand All @@ -80,7 +83,9 @@ impl MsgId {
pub async fn download_full(self, context: &Context) -> Result<()> {
let msg = Message::load_from_db(context, self).await?;
match msg.download_state() {
DownloadState::Done => return Err(anyhow!("Nothing to download.")),
DownloadState::Done | DownloadState::Undecipherable => {
return Err(anyhow!("Nothing to download."))
}
DownloadState::InProgress => return Err(anyhow!("Download already in progress.")),
DownloadState::Available | DownloadState::Failure => {
self.update_download_state(context, DownloadState::InProgress)
Expand Down
Loading

0 comments on commit 59a3bc0

Please sign in to comment.