mirror of
https://github.com/dino/dino.git
synced 2025-07-04 00:02:11 -04:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
baf96d9d9f | ||
|
179c766d19 | ||
|
004824040d | ||
|
b6f9b54d76 | ||
|
1738bf8dc8 | ||
|
481a68fd89 | ||
|
89b9110fcb | ||
|
acf9c69470 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -7,7 +7,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: sudo apt-get update
|
- run: sudo apt-get update
|
||||||
- run: sudo apt-get remove libunwind-14-dev
|
- run: sudo apt-get remove libunwind-14-dev
|
||||||
- run: sudo apt-get install -y build-essential gettext cmake valac libgee-0.8-dev libsqlite3-dev libgtk-4-dev libnotify-dev libgpgme-dev libsoup2.4-dev libgcrypt20-dev libqrencode-dev libgspell-1-dev libnice-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libsrtp2-dev libwebrtc-audio-processing-dev libadwaita-1-dev
|
- run: sudo apt-get install -y build-essential gettext cmake valac libgee-0.8-dev libsqlite3-dev libgtk-4-dev libnotify-dev libgpgme-dev libsoup2.4-dev libgcrypt20-dev libqrencode-dev libnice-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libsrtp2-dev libwebrtc-audio-processing-dev libadwaita-1-dev
|
||||||
- run: ./configure --with-tests --with-libsignal-in-tree
|
- run: ./configure --with-tests --with-libsignal-in-tree
|
||||||
- run: make
|
- run: make
|
||||||
- run: build/xmpp-vala-test
|
- run: build/xmpp-vala-test
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
include(PkgConfigWithFallback)
|
|
||||||
find_pkg_config_with_fallback(Gspell
|
|
||||||
PKG_CONFIG_NAME gspell-1
|
|
||||||
LIB_NAMES gspell-1
|
|
||||||
INCLUDE_NAMES gspell.h
|
|
||||||
INCLUDE_DIR_SUFFIXES gspell-1 gspell-1/gspell
|
|
||||||
DEPENDS GTK3
|
|
||||||
)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(Gspell
|
|
||||||
REQUIRED_VARS Gspell_LIBRARY
|
|
||||||
VERSION_VAR Gspell_VERSION)
|
|
||||||
|
|
@ -7,7 +7,7 @@ using Dino.Entities;
|
|||||||
namespace Dino {
|
namespace Dino {
|
||||||
|
|
||||||
public class Database : Qlite.Database {
|
public class Database : Qlite.Database {
|
||||||
private const int VERSION = 25;
|
private const int VERSION = 26;
|
||||||
|
|
||||||
public class AccountTable : Table {
|
public class AccountTable : Table {
|
||||||
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
|
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
|
||||||
@ -93,6 +93,11 @@ public class Database : Qlite.Database {
|
|||||||
|
|
||||||
// deduplication
|
// deduplication
|
||||||
index("message_account_counterpart_stanzaid_idx", {account_id, counterpart_id, stanza_id});
|
index("message_account_counterpart_stanzaid_idx", {account_id, counterpart_id, stanza_id});
|
||||||
|
index("message_account_counterpart_serverid_idx", {account_id, counterpart_id, server_id});
|
||||||
|
|
||||||
|
// message by marked
|
||||||
|
index("message_account_marked_idx", {account_id, marked});
|
||||||
|
|
||||||
fts({body});
|
fts({body});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ public class Dino.HistorySync {
|
|||||||
if (current_row[db.mam_catchup.from_end]) return;
|
if (current_row[db.mam_catchup.from_end]) return;
|
||||||
|
|
||||||
debug("[%s] Fetching between ranges %s - %s", mam_server.to_string(), previous_row[db.mam_catchup.to_time].to_string(), current_row[db.mam_catchup.from_time].to_string());
|
debug("[%s] Fetching between ranges %s - %s", mam_server.to_string(), previous_row[db.mam_catchup.to_time].to_string(), current_row[db.mam_catchup.from_time].to_string());
|
||||||
current_row = yield fetch_between_ranges(account, mam_server, previous_row, current_row);
|
current_row = yield fetch_between_ranges(account, mam_server, previous_row, current_row, cancellable);
|
||||||
if (current_row == null) return;
|
if (current_row == null) return;
|
||||||
|
|
||||||
RowOption previous_row_opt = db.mam_catchup.select()
|
RowOption previous_row_opt = db.mam_catchup.select()
|
||||||
@ -214,13 +214,11 @@ public class Dino.HistorySync {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get PageResult.Duplicate, we still want to update the db row to the latest message.
|
|
||||||
|
|
||||||
// Catchup finished within first page. Update latest db entry.
|
// Catchup finished within first page. Update latest db entry.
|
||||||
if (latest_row_id != -1 &&
|
if (latest_row_id != -1 &&
|
||||||
page_result.page_result in new PageResult[] { PageResult.TargetReached, PageResult.NoMoreMessages, PageResult.Duplicate }) {
|
page_result.page_result in new PageResult[] { PageResult.TargetReached, PageResult.NoMoreMessages }) {
|
||||||
|
|
||||||
if (page_result.stanzas == null || page_result.stanzas.is_empty) return null;
|
if (page_result.stanzas == null) return null;
|
||||||
|
|
||||||
string latest_mam_id = page_result.query_result.last;
|
string latest_mam_id = page_result.query_result.last;
|
||||||
long latest_mam_time = (long) mam_times[account][latest_mam_id].to_unix();
|
long latest_mam_time = (long) mam_times[account][latest_mam_id].to_unix();
|
||||||
@ -272,7 +270,7 @@ public class Dino.HistorySync {
|
|||||||
** Merges the `earlier_range` db row into the `later_range` db row.
|
** Merges the `earlier_range` db row into the `later_range` db row.
|
||||||
** @return The resulting range comprising `earlier_range`, `later_rage`, and everything in between. null if fetching/merge failed.
|
** @return The resulting range comprising `earlier_range`, `later_rage`, and everything in between. null if fetching/merge failed.
|
||||||
**/
|
**/
|
||||||
private async Row? fetch_between_ranges(Account account, Jid mam_server, Row earlier_range, Row later_range) {
|
private async Row? fetch_between_ranges(Account account, Jid mam_server, Row earlier_range, Row later_range, Cancellable? cancellable = null) {
|
||||||
int later_range_id = (int) later_range[db.mam_catchup.id];
|
int later_range_id = (int) later_range[db.mam_catchup.id];
|
||||||
DateTime earliest_time = new DateTime.from_unix_utc(earlier_range[db.mam_catchup.to_time]);
|
DateTime earliest_time = new DateTime.from_unix_utc(earlier_range[db.mam_catchup.to_time]);
|
||||||
DateTime latest_time = new DateTime.from_unix_utc(later_range[db.mam_catchup.from_time]);
|
DateTime latest_time = new DateTime.from_unix_utc(later_range[db.mam_catchup.from_time]);
|
||||||
@ -282,9 +280,9 @@ public class Dino.HistorySync {
|
|||||||
earliest_time, earlier_range[db.mam_catchup.to_id],
|
earliest_time, earlier_range[db.mam_catchup.to_id],
|
||||||
latest_time, later_range[db.mam_catchup.from_id]);
|
latest_time, later_range[db.mam_catchup.from_id]);
|
||||||
|
|
||||||
PageRequestResult page_result = yield fetch_query(account, query_params, later_range_id);
|
PageRequestResult page_result = yield fetch_query(account, query_params, later_range_id, cancellable);
|
||||||
|
|
||||||
if (page_result.page_result == PageResult.TargetReached) {
|
if (page_result.page_result == PageResult.TargetReached || page_result.page_result == PageResult.NoMoreMessages) {
|
||||||
debug("[%s | %s] Merging range %i into %i", account.bare_jid.to_string(), mam_server.to_string(), earlier_range[db.mam_catchup.id], later_range_id);
|
debug("[%s | %s] Merging range %i into %i", account.bare_jid.to_string(), mam_server.to_string(), earlier_range[db.mam_catchup.id], later_range_id);
|
||||||
// Merge earlier range into later one.
|
// Merge earlier range into later one.
|
||||||
db.mam_catchup.update()
|
db.mam_catchup.update()
|
||||||
@ -330,9 +328,9 @@ public class Dino.HistorySync {
|
|||||||
PageRequestResult? page_result = null;
|
PageRequestResult? page_result = null;
|
||||||
do {
|
do {
|
||||||
page_result = yield get_mam_page(account, query_params, page_result, cancellable);
|
page_result = yield get_mam_page(account, query_params, page_result, cancellable);
|
||||||
debug("Page result %s %b", page_result.page_result.to_string(), page_result.stanzas == null);
|
debug("[%s | %s] Page result %s (got stanzas: %s)", account.bare_jid.to_string(), query_params.mam_server.to_string(), page_result.page_result.to_string(), (page_result.stanzas != null).to_string());
|
||||||
|
|
||||||
if (page_result.page_result == PageResult.Error || page_result.page_result == PageResult.Cancelled || page_result.stanzas == null) return page_result;
|
if (page_result.page_result == PageResult.Error || page_result.page_result == PageResult.Cancelled || page_result.query_result.first == null) return page_result;
|
||||||
|
|
||||||
string earliest_mam_id = page_result.query_result.first;
|
string earliest_mam_id = page_result.query_result.first;
|
||||||
long earliest_mam_time = (long)mam_times[account][earliest_mam_id].to_unix();
|
long earliest_mam_time = (long)mam_times[account][earliest_mam_id].to_unix();
|
||||||
@ -357,7 +355,6 @@ public class Dino.HistorySync {
|
|||||||
MorePagesAvailable,
|
MorePagesAvailable,
|
||||||
TargetReached,
|
TargetReached,
|
||||||
NoMoreMessages,
|
NoMoreMessages,
|
||||||
Duplicate,
|
|
||||||
Error,
|
Error,
|
||||||
Cancelled
|
Cancelled
|
||||||
}
|
}
|
||||||
@ -399,23 +396,25 @@ public class Dino.HistorySync {
|
|||||||
string query_id = query_params.query_id;
|
string query_id = query_params.query_id;
|
||||||
string? after_id = query_params.start_id;
|
string? after_id = query_params.start_id;
|
||||||
|
|
||||||
|
var stanzas_for_query = stanzas.has_key(query_id) && !stanzas[query_id].is_empty ? stanzas[query_id] : null;
|
||||||
if (cancellable != null && cancellable.is_cancelled()) {
|
if (cancellable != null && cancellable.is_cancelled()) {
|
||||||
return new PageRequestResult(PageResult.Cancelled, query_result, stanzas[query_id]);
|
stanzas.unset(query_id);
|
||||||
|
return new PageRequestResult(PageResult.Cancelled, query_result, stanzas_for_query);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stanzas.has_key(query_id) && !stanzas[query_id].is_empty) {
|
if (stanzas_for_query != null) {
|
||||||
|
|
||||||
// Check it we reached our target (from_id)
|
// Check it we reached our target (from_id)
|
||||||
foreach (Xmpp.MessageStanza message in stanzas[query_id]) {
|
foreach (Xmpp.MessageStanza message in stanzas_for_query) {
|
||||||
Xmpp.MessageArchiveManagement.MessageFlag? mam_message_flag = Xmpp.MessageArchiveManagement.MessageFlag.get_flag(message);
|
Xmpp.MessageArchiveManagement.MessageFlag? mam_message_flag = Xmpp.MessageArchiveManagement.MessageFlag.get_flag(message);
|
||||||
if (mam_message_flag != null && mam_message_flag.mam_id != null) {
|
if (mam_message_flag != null && mam_message_flag.mam_id != null) {
|
||||||
if (after_id != null && mam_message_flag.mam_id == after_id) {
|
if (after_id != null && mam_message_flag.mam_id == after_id) {
|
||||||
// Successfully fetched the whole range
|
// Successfully fetched the whole range
|
||||||
yield send_messages_back_into_pipeline(account, query_id, cancellable);
|
yield send_messages_back_into_pipeline(account, query_id, cancellable);
|
||||||
if (cancellable != null && cancellable.is_cancelled()) {
|
if (cancellable != null && cancellable.is_cancelled()) {
|
||||||
return new PageRequestResult(PageResult.Cancelled, query_result, stanzas[query_id]);
|
return new PageRequestResult(PageResult.Cancelled, query_result, stanzas_for_query);
|
||||||
}
|
}
|
||||||
return new PageRequestResult(PageResult.TargetReached, query_result, stanzas[query_id]);
|
return new PageRequestResult(PageResult.TargetReached, query_result, stanzas_for_query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,37 +422,9 @@ public class Dino.HistorySync {
|
|||||||
// Message got filtered out by xmpp-vala, but succesful range fetch nevertheless
|
// Message got filtered out by xmpp-vala, but succesful range fetch nevertheless
|
||||||
yield send_messages_back_into_pipeline(account, query_id);
|
yield send_messages_back_into_pipeline(account, query_id);
|
||||||
if (cancellable != null && cancellable.is_cancelled()) {
|
if (cancellable != null && cancellable.is_cancelled()) {
|
||||||
return new PageRequestResult(PageResult.Cancelled, query_result, stanzas[query_id]);
|
return new PageRequestResult(PageResult.Cancelled, query_result, stanzas_for_query);
|
||||||
}
|
}
|
||||||
return new PageRequestResult(PageResult.TargetReached, query_result, stanzas[query_id]);
|
return new PageRequestResult(PageResult.TargetReached, query_result, stanzas_for_query);
|
||||||
}
|
|
||||||
|
|
||||||
// Check for duplicates. Go through all messages and build a db query.
|
|
||||||
foreach (Xmpp.MessageStanza message in stanzas[query_id]) {
|
|
||||||
Xmpp.MessageArchiveManagement.MessageFlag? mam_message_flag = Xmpp.MessageArchiveManagement.MessageFlag.get_flag(message);
|
|
||||||
if (mam_message_flag != null && mam_message_flag.mam_id != null) {
|
|
||||||
if (selection == null) {
|
|
||||||
selection = @"$(db.message.server_id) = ?";
|
|
||||||
} else {
|
|
||||||
selection += @" OR $(db.message.server_id) = ?";
|
|
||||||
}
|
|
||||||
selection_args += mam_message_flag.mam_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var duplicates_qry = db.message.select()
|
|
||||||
.with(db.message.account_id, "=", account.id)
|
|
||||||
.where(selection, selection_args);
|
|
||||||
// We don't want messages from different MAM servers to interfere with each other.
|
|
||||||
if (!query_params.mam_server.equals_bare(account.bare_jid)) {
|
|
||||||
duplicates_qry.with(db.message.counterpart_id, "=", db.get_jid_id(query_params.mam_server));
|
|
||||||
} else {
|
|
||||||
duplicates_qry.with(db.message.type_, "=", Message.Type.CHAT);
|
|
||||||
}
|
|
||||||
var duplicates_count = duplicates_qry.count();
|
|
||||||
if (duplicates_count > 0) {
|
|
||||||
// We got a duplicate although we thought we have to catch up.
|
|
||||||
// There was a server bug where prosody would send all messages if it didn't know the after ID that was given
|
|
||||||
page_result = PageResult.Duplicate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +432,7 @@ public class Dino.HistorySync {
|
|||||||
if (cancellable != null && cancellable.is_cancelled()) {
|
if (cancellable != null && cancellable.is_cancelled()) {
|
||||||
page_result = PageResult.Cancelled;
|
page_result = PageResult.Cancelled;
|
||||||
}
|
}
|
||||||
return new PageRequestResult(page_result, query_result, stanzas.has_key(query_id) ? stanzas[query_id] : null);
|
return new PageRequestResult(page_result, query_result, stanzas_for_query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void send_messages_back_into_pipeline(Account account, string query_id, Cancellable? cancellable = null) {
|
private async void send_messages_back_into_pipeline(Account account, string query_id, Cancellable? cancellable = null) {
|
||||||
|
@ -5,7 +5,7 @@ GenericName=Jabber/XMPP Client
|
|||||||
Keywords=chat;talk;im;message;xmpp;jabber;
|
Keywords=chat;talk;im;message;xmpp;jabber;
|
||||||
Exec=dino %U
|
Exec=dino %U
|
||||||
Icon=im.dino.Dino
|
Icon=im.dino.Dino
|
||||||
StartupNotify=false
|
StartupNotify=true
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=GTK;Network;Chat;InstantMessaging;
|
Categories=GTK;Network;Chat;InstantMessaging;
|
||||||
|
@ -225,7 +225,21 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||||||
label.attributes = copy;
|
label.attributes = copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool update_read_pending = false;
|
||||||
|
private bool update_read_pending_force = false;
|
||||||
protected void update_read(bool force_update = false) {
|
protected void update_read(bool force_update = false) {
|
||||||
|
if (force_update) update_read_pending_force = true;
|
||||||
|
if (update_read_pending) return;
|
||||||
|
update_read_pending = true;
|
||||||
|
Idle.add(() => {
|
||||||
|
update_read_pending = false;
|
||||||
|
update_read_pending_force = false;
|
||||||
|
update_read_idle(update_read_pending_force);
|
||||||
|
return Source.REMOVE;
|
||||||
|
}, Priority.LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update_read_idle(bool force_update = false) {
|
||||||
int current_num_unread = stream_interactor.get_module(ChatInteraction.IDENTITY).get_num_unread(conversation);
|
int current_num_unread = stream_interactor.get_module(ChatInteraction.IDENTITY).get_num_unread(conversation);
|
||||||
if (num_unread == current_num_unread && !force_update) return;
|
if (num_unread == current_num_unread && !force_update) return;
|
||||||
num_unread = current_num_unread;
|
num_unread = current_num_unread;
|
||||||
|
@ -10,13 +10,16 @@ public class FileProvider : Dino.FileProvider, Object {
|
|||||||
|
|
||||||
private StreamInteractor stream_interactor;
|
private StreamInteractor stream_interactor;
|
||||||
private Dino.Database dino_db;
|
private Dino.Database dino_db;
|
||||||
|
private Soup.Session session;
|
||||||
private static Regex http_url_regex = /^https?:\/\/([^\s#]*)$/; // Spaces are invalid in URLs and we can't use fragments for downloads
|
private static Regex http_url_regex = /^https?:\/\/([^\s#]*)$/; // Spaces are invalid in URLs and we can't use fragments for downloads
|
||||||
private static Regex omemo_url_regex = /^aesgcm:\/\/(.*)#(([A-Fa-f0-9]{2}){48}|([A-Fa-f0-9]{2}){44})$/;
|
private static Regex omemo_url_regex = /^aesgcm:\/\/(.*)#(([A-Fa-f0-9]{2}){48}|([A-Fa-f0-9]{2}){44})$/;
|
||||||
|
|
||||||
public FileProvider(StreamInteractor stream_interactor, Dino.Database dino_db) {
|
public FileProvider(StreamInteractor stream_interactor, Dino.Database dino_db) {
|
||||||
this.stream_interactor = stream_interactor;
|
this.stream_interactor = stream_interactor;
|
||||||
this.dino_db = dino_db;
|
this.dino_db = dino_db;
|
||||||
|
this.session = new Soup.Session();
|
||||||
|
|
||||||
|
session.user_agent = @"Dino/$(Dino.get_short_version()) ";
|
||||||
stream_interactor.get_module(MessageProcessor.IDENTITY).received_pipeline.connect(new ReceivedMessageListener(this));
|
stream_interactor.get_module(MessageProcessor.IDENTITY).received_pipeline.connect(new ReceivedMessageListener(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,8 +117,6 @@ public class FileProvider : Dino.FileProvider, Object {
|
|||||||
HttpFileReceiveData? http_receive_data = receive_data as HttpFileReceiveData;
|
HttpFileReceiveData? http_receive_data = receive_data as HttpFileReceiveData;
|
||||||
if (http_receive_data == null) return file_meta;
|
if (http_receive_data == null) return file_meta;
|
||||||
|
|
||||||
var session = new Soup.Session();
|
|
||||||
session.user_agent = @"Dino/$(Dino.get_short_version()) ";
|
|
||||||
var head_message = new Soup.Message("HEAD", http_receive_data.url);
|
var head_message = new Soup.Message("HEAD", http_receive_data.url);
|
||||||
head_message.request_headers.append("Accept-Encoding", "identity");
|
head_message.request_headers.append("Accept-Encoding", "identity");
|
||||||
|
|
||||||
@ -150,8 +151,6 @@ public class FileProvider : Dino.FileProvider, Object {
|
|||||||
HttpFileReceiveData? http_receive_data = receive_data as HttpFileReceiveData;
|
HttpFileReceiveData? http_receive_data = receive_data as HttpFileReceiveData;
|
||||||
if (http_receive_data == null) assert(false);
|
if (http_receive_data == null) assert(false);
|
||||||
|
|
||||||
var session = new Soup.Session();
|
|
||||||
session.user_agent = @"Dino/$(Dino.get_short_version()) ";
|
|
||||||
var get_message = new Soup.Message("GET", http_receive_data.url);
|
var get_message = new Soup.Message("GET", http_receive_data.url);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -7,12 +7,15 @@ namespace Dino.Plugins.HttpFiles {
|
|||||||
public class HttpFileSender : FileSender, Object {
|
public class HttpFileSender : FileSender, Object {
|
||||||
private StreamInteractor stream_interactor;
|
private StreamInteractor stream_interactor;
|
||||||
private Database db;
|
private Database db;
|
||||||
|
private Soup.Session session;
|
||||||
private HashMap<Account, long> max_file_sizes = new HashMap<Account, long>(Account.hash_func, Account.equals_func);
|
private HashMap<Account, long> max_file_sizes = new HashMap<Account, long>(Account.hash_func, Account.equals_func);
|
||||||
|
|
||||||
public HttpFileSender(StreamInteractor stream_interactor, Database db) {
|
public HttpFileSender(StreamInteractor stream_interactor, Database db) {
|
||||||
this.stream_interactor = stream_interactor;
|
this.stream_interactor = stream_interactor;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
this.session = new Soup.Session();
|
||||||
|
|
||||||
|
session.user_agent = @"Dino/$(Dino.get_short_version()) ";
|
||||||
stream_interactor.stream_negotiated.connect(on_stream_negotiated);
|
stream_interactor.stream_negotiated.connect(on_stream_negotiated);
|
||||||
stream_interactor.get_module(MessageProcessor.IDENTITY).build_message_stanza.connect(check_add_oob);
|
stream_interactor.get_module(MessageProcessor.IDENTITY).build_message_stanza.connect(check_add_oob);
|
||||||
}
|
}
|
||||||
@ -90,8 +93,6 @@ public class HttpFileSender : FileSender, Object {
|
|||||||
Xmpp.XmppStream? stream = stream_interactor.get_stream(file_transfer.account);
|
Xmpp.XmppStream? stream = stream_interactor.get_stream(file_transfer.account);
|
||||||
if (stream == null) return;
|
if (stream == null) return;
|
||||||
|
|
||||||
var session = new Soup.Session();
|
|
||||||
session.user_agent = @"Dino/$(Dino.get_short_version()) ";
|
|
||||||
var put_message = new Soup.Message("PUT", file_send_data.url_up);
|
var put_message = new Soup.Message("PUT", file_send_data.url_up);
|
||||||
#if SOUP_3_0
|
#if SOUP_3_0
|
||||||
put_message.set_request_body(file_meta.mime_type, file_transfer.input_stream, (ssize_t) file_meta.size);
|
put_message.set_request_body(file_meta.mime_type, file_transfer.input_stream, (ssize_t) file_meta.size);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
private static extern unowned Gst.Video.Info gst_video_frame_get_video_info(Gst.Video.Frame frame);
|
private static extern unowned Gst.Video.Info gst_video_frame_get_video_info(Gst.Video.Frame frame);
|
||||||
|
[CCode (array_length_type = "size_t", type = "void*")]
|
||||||
private static extern unowned uint8[] gst_video_frame_get_data(Gst.Video.Frame frame);
|
private static extern unowned uint8[] gst_video_frame_get_data(Gst.Video.Frame frame);
|
||||||
|
|
||||||
public class Dino.Plugins.Rtp.Paintable : Gdk.Paintable, Object {
|
public class Dino.Plugins.Rtp.Paintable : Gdk.Paintable, Object {
|
||||||
|
@ -58,6 +58,10 @@ public class ReceivedPipelineListener : StanzaListener<MessageStanza> {
|
|||||||
warning("Received alleged carbon message from %s, ignoring", message.from.to_string());
|
warning("Received alleged carbon message from %s, ignoring", message.from.to_string());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (message_node == null) {
|
||||||
|
warning("Received a carbon message with no message subnode in jabber:client namespace from %s, ignoring", message.from.to_string());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (received_node != null) {
|
if (received_node != null) {
|
||||||
message.add_flag(new MessageFlag(MessageFlag.TYPE_RECEIVED));
|
message.add_flag(new MessageFlag(MessageFlag.TYPE_RECEIVED));
|
||||||
} else if (sent_node != null) {
|
} else if (sent_node != null) {
|
||||||
|
@ -11,8 +11,8 @@ public class QueryResult {
|
|||||||
public bool error { get; set; default=false; }
|
public bool error { get; set; default=false; }
|
||||||
public bool malformed { get; set; default=false; }
|
public bool malformed { get; set; default=false; }
|
||||||
public bool complete { get; set; default=false; }
|
public bool complete { get; set; default=false; }
|
||||||
public string first { get; set; }
|
public string? first { get; set; }
|
||||||
public string last { get; set; }
|
public string? last { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Module : XmppStreamModule {
|
public class Module : XmppStreamModule {
|
||||||
@ -65,16 +65,17 @@ public class Module : XmppStreamModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StanzaNode query_node = new StanzaNode.build("query", NS_VER(stream)).add_self_xmlns().put_node(data_form.get_submit_node());
|
StanzaNode query_node = new StanzaNode.build("query", NS_VER(stream)).add_self_xmlns().put_node(data_form.get_submit_node());
|
||||||
if (queryid != null) {
|
|
||||||
query_node.put_attribute("queryid", queryid);
|
query_node.put_attribute("queryid", queryid);
|
||||||
}
|
|
||||||
return query_node;
|
return query_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async QueryResult query_archive(XmppStream stream, string ns, Jid? mam_server, StanzaNode query_node, Cancellable? cancellable = null) {
|
internal async QueryResult query_archive(XmppStream stream, string ns, Jid? mam_server, StanzaNode query_node, Cancellable? cancellable = null) {
|
||||||
var res = new QueryResult();
|
|
||||||
|
|
||||||
if (stream.get_flag(Flag.IDENTITY) == null) { res.error = true; return res; }
|
var res = new QueryResult();
|
||||||
|
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
||||||
|
string? query_id = query_node.get_attribute("queryid");
|
||||||
|
if (flag == null || query_id == null) { res.error = true; return res; }
|
||||||
|
flag.active_query_ids.add(query_id);
|
||||||
|
|
||||||
// Build and send query
|
// Build and send query
|
||||||
Iq.Stanza iq = new Iq.Stanza.set(query_node) { to=mam_server };
|
Iq.Stanza iq = new Iq.Stanza.set(query_node) { to=mam_server };
|
||||||
@ -93,6 +94,11 @@ public class Module : XmppStreamModule {
|
|||||||
if ((res.first == null) != (res.last == null)) { res.malformed = true; return res; }
|
if ((res.first == null) != (res.last == null)) { res.malformed = true; return res; }
|
||||||
res.complete = fin_node.get_attribute_bool("complete", false, ns);
|
res.complete = fin_node.get_attribute_bool("complete", false, ns);
|
||||||
|
|
||||||
|
Idle.add(() => {
|
||||||
|
flag.active_query_ids.remove(query_id);
|
||||||
|
return Source.REMOVE;
|
||||||
|
}, Priority.LOW);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +110,8 @@ public class ReceivedPipelineListener : StanzaListener<MessageStanza> {
|
|||||||
public override string[] after_actions { get { return after_actions_const; } }
|
public override string[] after_actions { get { return after_actions_const; } }
|
||||||
|
|
||||||
public override async bool run(XmppStream stream, MessageStanza message) {
|
public override async bool run(XmppStream stream, MessageStanza message) {
|
||||||
if (stream.get_flag(Flag.IDENTITY) == null) return false;
|
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
||||||
|
if (flag == null) return false;
|
||||||
|
|
||||||
StanzaNode? message_node = message.stanza.get_deep_subnode(NS_VER(stream) + ":result", StanzaForwarding.NS_URI + ":forwarded", Xmpp.NS_URI + ":message");
|
StanzaNode? message_node = message.stanza.get_deep_subnode(NS_VER(stream) + ":result", StanzaForwarding.NS_URI + ":forwarded", Xmpp.NS_URI + ":message");
|
||||||
if (message_node != null) {
|
if (message_node != null) {
|
||||||
@ -112,6 +119,28 @@ public class ReceivedPipelineListener : StanzaListener<MessageStanza> {
|
|||||||
DateTime? datetime = DelayedDelivery.get_time_for_node(forward_node);
|
DateTime? datetime = DelayedDelivery.get_time_for_node(forward_node);
|
||||||
string? mam_id = message.stanza.get_deep_attribute(NS_VER(stream) + ":result", NS_VER(stream) + ":id");
|
string? mam_id = message.stanza.get_deep_attribute(NS_VER(stream) + ":result", NS_VER(stream) + ":id");
|
||||||
string? query_id = message.stanza.get_deep_attribute(NS_VER(stream) + ":result", NS_VER(stream) + ":queryid");
|
string? query_id = message.stanza.get_deep_attribute(NS_VER(stream) + ":result", NS_VER(stream) + ":queryid");
|
||||||
|
|
||||||
|
if (query_id == null) {
|
||||||
|
warning("Received MAM message without queryid from %s, ignoring", message.from.to_string());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flag.active_query_ids.contains(query_id)) {
|
||||||
|
warning("Received MAM message from %s with unknown query id %s, ignoring", message.from.to_string(), query_id ?? "<none>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Jid? inner_from = null;
|
||||||
|
try {
|
||||||
|
inner_from = new Jid(message_node.get_attribute("from"));
|
||||||
|
} catch (InvalidJidError e) {
|
||||||
|
warning("Received MAM message with invalid from attribute in forwarded message from %s, ignoring", message.from.to_string());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!message.from.equals(stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid) && !message.from.equals_bare(inner_from)) {
|
||||||
|
warning("Received MAM message from %s illegally impersonating %s, ignoring", message.from.to_string(), inner_from.to_string());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
message.add_flag(new MessageFlag(message.from, datetime, mam_id, query_id));
|
message.add_flag(new MessageFlag(message.from, datetime, mam_id, query_id));
|
||||||
|
|
||||||
message.stanza = message_node;
|
message.stanza = message_node;
|
||||||
@ -124,6 +153,7 @@ public class ReceivedPipelineListener : StanzaListener<MessageStanza> {
|
|||||||
public class Flag : XmppStreamFlag {
|
public class Flag : XmppStreamFlag {
|
||||||
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "message_archive_management");
|
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "message_archive_management");
|
||||||
public bool cought_up { get; set; default=false; }
|
public bool cought_up { get; set; default=false; }
|
||||||
|
public Gee.Set<string> active_query_ids { get; set; default = new HashSet<string>(); }
|
||||||
public string ns_ver;
|
public string ns_ver;
|
||||||
|
|
||||||
public Flag(string ns_ver) {
|
public Flag(string ns_ver) {
|
||||||
|
@ -68,6 +68,11 @@ public class Module : BookmarksProvider, XmppStreamModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void on_pupsub_item(XmppStream stream, Jid jid, string id, StanzaNode? node) {
|
private void on_pupsub_item(XmppStream stream, Jid jid, string id, StanzaNode? node) {
|
||||||
|
if (!jid.equals(stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid)) {
|
||||||
|
warning("Received alleged bookmarks:1 item from %s, ignoring", jid.to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Conference conference = parse_item_node(node, id);
|
Conference conference = parse_item_node(node, id);
|
||||||
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
||||||
if (flag != null) {
|
if (flag != null) {
|
||||||
@ -77,6 +82,11 @@ public class Module : BookmarksProvider, XmppStreamModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void on_pupsub_retract(XmppStream stream, Jid jid, string id) {
|
private void on_pupsub_retract(XmppStream stream, Jid jid, string id) {
|
||||||
|
if (!jid.equals(stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid)) {
|
||||||
|
warning("Received alleged bookmarks:1 retract from %s, ignoring", jid.to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Jid jid_parsed = new Jid(id);
|
Jid jid_parsed = new Jid(id);
|
||||||
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user