Fix crash on NS_URI call when own server has no MAM; drop broken mam:1 "support"
fixes #1405
This commit is contained in:
parent
6e60cfcbbe
commit
2b9a0ccf7e
|
@ -90,11 +90,9 @@ public class Dino.HistorySync {
|
||||||
if (!is_muc_mam && !from_our_server) return;
|
if (!is_muc_mam && !from_our_server) return;
|
||||||
|
|
||||||
// Get the server time of the message and store it in `mam_times`
|
// Get the server time of the message and store it in `mam_times`
|
||||||
Xmpp.MessageArchiveManagement.Flag? mam_flag = stream != null ? stream.get_flag(Xmpp.MessageArchiveManagement.Flag.IDENTITY) : null;
|
string? id = message.stanza.get_deep_attribute(Xmpp.MessageArchiveManagement.NS_URI + ":result", "id");
|
||||||
if (mam_flag == null) return;
|
|
||||||
string? id = message.stanza.get_deep_attribute(mam_flag.ns_ver + ":result", "id");
|
|
||||||
if (id == null) return;
|
if (id == null) return;
|
||||||
StanzaNode? delay_node = message.stanza.get_deep_subnode(mam_flag.ns_ver + ":result", StanzaForwarding.NS_URI + ":forwarded", DelayedDelivery.NS_URI + ":delay");
|
StanzaNode? delay_node = message.stanza.get_deep_subnode(Xmpp.MessageArchiveManagement.NS_URI + ":result", StanzaForwarding.NS_URI + ":forwarded", DelayedDelivery.NS_URI + ":delay");
|
||||||
if (delay_node == null) {
|
if (delay_node == null) {
|
||||||
warning("MAM result did not contain delayed time %s", message.stanza.to_string());
|
warning("MAM result did not contain delayed time %s", message.stanza.to_string());
|
||||||
return;
|
return;
|
||||||
|
@ -104,7 +102,7 @@ public class Dino.HistorySync {
|
||||||
mam_times[account][id] = time;
|
mam_times[account][id] = time;
|
||||||
|
|
||||||
// Check if this is the target message
|
// Check if this is the target message
|
||||||
string? query_id = message.stanza.get_deep_attribute(mam_flag.ns_ver + ":result", mam_flag.ns_ver + ":queryid");
|
string? query_id = message.stanza.get_deep_attribute(Xmpp.MessageArchiveManagement.NS_URI + ":result", Xmpp.MessageArchiveManagement.NS_URI + ":queryid");
|
||||||
if (query_id != null && id == catchup_until_id[account]) {
|
if (query_id != null && id == catchup_until_id[account]) {
|
||||||
debug("[%s] Hitted range (id) %s", account.bare_jid.to_string(), id);
|
debug("[%s] Hitted range (id) %s", account.bare_jid.to_string(), id);
|
||||||
hitted_range[query_id] = -2;
|
hitted_range[query_id] = -2;
|
||||||
|
|
|
@ -170,19 +170,21 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
||||||
|
|
||||||
XmppStream? stream = stream_interactor.get_stream(account);
|
XmppStream? stream = stream_interactor.get_stream(account);
|
||||||
Xmpp.MessageArchiveManagement.MessageFlag? mam_message_flag = Xmpp.MessageArchiveManagement.MessageFlag.get_flag(message);
|
Xmpp.MessageArchiveManagement.MessageFlag? mam_message_flag = Xmpp.MessageArchiveManagement.MessageFlag.get_flag(message);
|
||||||
Xmpp.MessageArchiveManagement.Flag? mam_flag = stream != null ? stream.get_flag(Xmpp.MessageArchiveManagement.Flag.IDENTITY) : null;
|
|
||||||
EntityInfo entity_info = stream_interactor.get_module(EntityInfo.IDENTITY);
|
EntityInfo entity_info = stream_interactor.get_module(EntityInfo.IDENTITY);
|
||||||
if (mam_message_flag != null && mam_flag != null && mam_flag.ns_ver == Xmpp.MessageArchiveManagement.NS_URI_2 && mam_message_flag.mam_id != null) {
|
if (mam_message_flag != null && mam_message_flag.mam_id != null) {
|
||||||
|
bool server_does_mam = entity_info.has_feature_cached(account, account.bare_jid, Xmpp.MessageArchiveManagement.NS_URI);
|
||||||
|
if (server_does_mam) {
|
||||||
new_message.server_id = mam_message_flag.mam_id;
|
new_message.server_id = mam_message_flag.mam_id;
|
||||||
|
}
|
||||||
} else if (message.type_ == Xmpp.MessageStanza.TYPE_GROUPCHAT) {
|
} else if (message.type_ == Xmpp.MessageStanza.TYPE_GROUPCHAT) {
|
||||||
bool server_supports_sid = (yield entity_info.has_feature(account, new_message.counterpart.bare_jid, Xep.UniqueStableStanzaIDs.NS_URI)) ||
|
bool server_supports_sid = (yield entity_info.has_feature(account, new_message.counterpart.bare_jid, Xep.UniqueStableStanzaIDs.NS_URI)) ||
|
||||||
(yield entity_info.has_feature(account, new_message.counterpart.bare_jid, Xmpp.MessageArchiveManagement.NS_URI_2));
|
(yield entity_info.has_feature(account, new_message.counterpart.bare_jid, Xmpp.MessageArchiveManagement.NS_URI));
|
||||||
if (server_supports_sid) {
|
if (server_supports_sid) {
|
||||||
new_message.server_id = Xep.UniqueStableStanzaIDs.get_stanza_id(message, new_message.counterpart.bare_jid);
|
new_message.server_id = Xep.UniqueStableStanzaIDs.get_stanza_id(message, new_message.counterpart.bare_jid);
|
||||||
}
|
}
|
||||||
} else if (message.type_ == Xmpp.MessageStanza.TYPE_CHAT) {
|
} else if (message.type_ == Xmpp.MessageStanza.TYPE_CHAT) {
|
||||||
bool server_supports_sid = (yield entity_info.has_feature(account, account.bare_jid, Xep.UniqueStableStanzaIDs.NS_URI)) ||
|
bool server_supports_sid = (yield entity_info.has_feature(account, account.bare_jid, Xep.UniqueStableStanzaIDs.NS_URI)) ||
|
||||||
(yield entity_info.has_feature(account, account.bare_jid, Xmpp.MessageArchiveManagement.NS_URI_2));
|
(yield entity_info.has_feature(account, account.bare_jid, Xmpp.MessageArchiveManagement.NS_URI));
|
||||||
if (server_supports_sid) {
|
if (server_supports_sid) {
|
||||||
new_message.server_id = Xep.UniqueStableStanzaIDs.get_stanza_id(message, account.bare_jid);
|
new_message.server_id = Xep.UniqueStableStanzaIDs.get_stanza_id(message, account.bare_jid);
|
||||||
}
|
}
|
||||||
|
@ -378,7 +380,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
||||||
public override async bool run(Entities.Message message, Xmpp.MessageStanza stanza, Conversation conversation) {
|
public override async bool run(Entities.Message message, Xmpp.MessageStanza stanza, Conversation conversation) {
|
||||||
bool is_mam_message = Xmpp.MessageArchiveManagement.MessageFlag.get_flag(stanza) != null;
|
bool is_mam_message = Xmpp.MessageArchiveManagement.MessageFlag.get_flag(stanza) != null;
|
||||||
XmppStream? stream = stream_interactor.get_stream(conversation.account);
|
XmppStream? stream = stream_interactor.get_stream(conversation.account);
|
||||||
Xmpp.MessageArchiveManagement.Flag? mam_flag = stream != null ? stream.get_flag(Xmpp.MessageArchiveManagement.Flag.IDENTITY) : null;
|
Xmpp.MessageArchiveManagement.Flag mam_flag = Xmpp.MessageArchiveManagement.Flag.get_flag(stream);
|
||||||
if (is_mam_message || (mam_flag != null && mam_flag.cought_up == true)) {
|
if (is_mam_message || (mam_flag != null && mam_flag.cought_up == true)) {
|
||||||
conversation.account.mam_earliest_synced = message.local_time;
|
conversation.account.mam_earliest_synced = message.local_time;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class MucManager : StreamInteractionModule, Object {
|
||||||
|
|
||||||
bool receive_history = true;
|
bool receive_history = true;
|
||||||
EntityInfo entity_info = stream_interactor.get_module(EntityInfo.IDENTITY);
|
EntityInfo entity_info = stream_interactor.get_module(EntityInfo.IDENTITY);
|
||||||
bool can_do_mam = yield entity_info.has_feature(account, jid, Xmpp.MessageArchiveManagement.NS_URI_2);
|
bool can_do_mam = yield entity_info.has_feature(account, jid, Xmpp.MessageArchiveManagement.NS_URI);
|
||||||
if (can_do_mam) {
|
if (can_do_mam) {
|
||||||
receive_history = false;
|
receive_history = false;
|
||||||
history_since = null;
|
history_since = null;
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class Dino.Reactions : StreamInteractionModule, Object {
|
||||||
// The MUC server needs to 1) support stable stanza ids 2) either support occupant ids or be a private room (where we know real jids)
|
// The MUC server needs to 1) support stable stanza ids 2) either support occupant ids or be a private room (where we know real jids)
|
||||||
var entity_info = stream_interactor.get_module(EntityInfo.IDENTITY);
|
var entity_info = stream_interactor.get_module(EntityInfo.IDENTITY);
|
||||||
bool server_supports_sid = (entity_info.has_feature_cached(conversation.account, conversation.counterpart.bare_jid, Xep.UniqueStableStanzaIDs.NS_URI)) ||
|
bool server_supports_sid = (entity_info.has_feature_cached(conversation.account, conversation.counterpart.bare_jid, Xep.UniqueStableStanzaIDs.NS_URI)) ||
|
||||||
(entity_info.has_feature_cached(conversation.account, conversation.counterpart.bare_jid, Xmpp.MessageArchiveManagement.NS_URI_2));
|
(entity_info.has_feature_cached(conversation.account, conversation.counterpart.bare_jid, Xmpp.MessageArchiveManagement.NS_URI));
|
||||||
if (!server_supports_sid) return false;
|
if (!server_supports_sid) return false;
|
||||||
|
|
||||||
bool? supports_occupant_ids = entity_info.has_feature_cached(conversation.account, conversation.counterpart, Xep.OccupantIds.NS_URI);
|
bool? supports_occupant_ids = entity_info.has_feature_cached(conversation.account, conversation.counterpart, Xep.OccupantIds.NS_URI);
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace Xmpp.MessageArchiveManagement.V2 {
|
||||||
fields.add(field);
|
fields.add(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MessageArchiveManagement.create_base_query(stream, MessageArchiveManagement.NS_URI_2, mam_params.query_id, fields);
|
return MessageArchiveManagement.create_base_query(stream, mam_params.query_id, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async QueryResult query_archive(XmppStream stream, MamQueryParams mam_params, Cancellable? cancellable = null) {
|
public async QueryResult query_archive(XmppStream stream, MamQueryParams mam_params, Cancellable? cancellable = null) {
|
||||||
|
@ -67,14 +67,14 @@ namespace Xmpp.MessageArchiveManagement.V2 {
|
||||||
query_node.put_node(ResultSetManagement.create_set_rsm_node_before(mam_params.end_id));
|
query_node.put_node(ResultSetManagement.create_set_rsm_node_before(mam_params.end_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
return yield MessageArchiveManagement.query_archive(stream, MessageArchiveManagement.NS_URI_2, mam_params.mam_server, query_node, cancellable);
|
return yield MessageArchiveManagement.query_archive(stream, mam_params.mam_server, query_node, cancellable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async QueryResult page_through_results(XmppStream stream, MamQueryParams mam_params, QueryResult prev_result, Cancellable? cancellable = null) {
|
public async QueryResult page_through_results(XmppStream stream, MamQueryParams mam_params, QueryResult prev_result, Cancellable? cancellable = null) {
|
||||||
var query_node = create_base_query(stream, mam_params);
|
var query_node = create_base_query(stream, mam_params);
|
||||||
query_node.put_node(ResultSetManagement.create_set_rsm_node_before(prev_result.first));
|
query_node.put_node(ResultSetManagement.create_set_rsm_node_before(prev_result.first));
|
||||||
|
|
||||||
return yield MessageArchiveManagement.query_archive(stream, MessageArchiveManagement.NS_URI_2, mam_params.mam_server, query_node, cancellable);
|
return yield MessageArchiveManagement.query_archive(stream, mam_params.mam_server, query_node, cancellable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ using Xmpp.Xep;
|
||||||
namespace Xmpp.MessageArchiveManagement {
|
namespace Xmpp.MessageArchiveManagement {
|
||||||
|
|
||||||
public const string NS_URI = "urn:xmpp:mam:2";
|
public const string NS_URI = "urn:xmpp:mam:2";
|
||||||
public const string NS_URI_2 = "urn:xmpp:mam:2";
|
|
||||||
public const string NS_URI_1 = "urn:xmpp:mam:1";
|
|
||||||
|
|
||||||
public class QueryResult {
|
public class QueryResult {
|
||||||
public bool error { get; set; default=false; }
|
public bool error { get; set; default=false; }
|
||||||
|
@ -36,43 +34,33 @@ public class Module : XmppStreamModule {
|
||||||
|
|
||||||
private async void query_availability(XmppStream stream) {
|
private async void query_availability(XmppStream stream) {
|
||||||
Jid own_jid = stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid;
|
Jid own_jid = stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid;
|
||||||
|
bool mam_available = yield stream.get_module(ServiceDiscovery.Module.IDENTITY).has_entity_feature(stream, own_jid, NS_URI);
|
||||||
bool ver_2_available = yield stream.get_module(ServiceDiscovery.Module.IDENTITY).has_entity_feature(stream, own_jid, NS_URI);
|
if (mam_available) {
|
||||||
if (ver_2_available) {
|
|
||||||
stream.add_flag(new Flag(NS_URI));
|
|
||||||
feature_available(stream);
|
feature_available(stream);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ver_1_available = yield stream.get_module(ServiceDiscovery.Module.IDENTITY).has_entity_feature(stream, own_jid, NS_URI_1);
|
|
||||||
if (ver_1_available) {
|
|
||||||
stream.add_flag(new Flag(NS_URI_1));
|
|
||||||
feature_available(stream);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal StanzaNode create_base_query(XmppStream stream, string ns, string? queryid, Gee.List<DataForms.DataForm.Field> fields) {
|
internal StanzaNode create_base_query(XmppStream stream, string? queryid, Gee.List<DataForms.DataForm.Field> fields) {
|
||||||
DataForms.DataForm data_form = new DataForms.DataForm();
|
DataForms.DataForm data_form = new DataForms.DataForm();
|
||||||
|
|
||||||
DataForms.DataForm.HiddenField form_type_field = new DataForms.DataForm.HiddenField() { var="FORM_TYPE" };
|
DataForms.DataForm.HiddenField form_type_field = new DataForms.DataForm.HiddenField() { var="FORM_TYPE" };
|
||||||
form_type_field.set_value_string(NS_VER(stream));
|
form_type_field.set_value_string(NS_URI);
|
||||||
data_form.add_field(form_type_field);
|
data_form.add_field(form_type_field);
|
||||||
|
|
||||||
foreach (var field in fields) {
|
foreach (var field in fields) {
|
||||||
data_form.add_field(field);
|
data_form.add_field(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
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_URI).add_self_xmlns().put_node(data_form.get_submit_node());
|
||||||
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, Jid? mam_server, StanzaNode query_node, Cancellable? cancellable = null) {
|
||||||
|
|
||||||
var res = new QueryResult();
|
var res = new QueryResult();
|
||||||
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
Flag flag = Flag.get_flag(stream);
|
||||||
string? query_id = query_node.get_attribute("queryid");
|
string? query_id = query_node.get_attribute("queryid");
|
||||||
if (flag == null || query_id == null) { res.error = true; return res; }
|
if (flag == null || query_id == null) { res.error = true; return res; }
|
||||||
flag.active_query_ids.add(query_id);
|
flag.active_query_ids.add(query_id);
|
||||||
|
@ -83,7 +71,7 @@ public class Module : XmppStreamModule {
|
||||||
Iq.Stanza result_iq = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq, Priority.LOW, cancellable);
|
Iq.Stanza result_iq = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq, Priority.LOW, cancellable);
|
||||||
|
|
||||||
// Parse the response IQ into a QueryResult.
|
// Parse the response IQ into a QueryResult.
|
||||||
StanzaNode? fin_node = result_iq.stanza.get_subnode("fin", ns);
|
StanzaNode? fin_node = result_iq.stanza.get_subnode("fin", NS_URI);
|
||||||
if (fin_node == null) { res.malformed = true; return res; }
|
if (fin_node == null) { res.malformed = true; return res; }
|
||||||
|
|
||||||
StanzaNode? rsm_node = fin_node.get_subnode("set", Xmpp.ResultSetManagement.NS_URI);
|
StanzaNode? rsm_node = fin_node.get_subnode("set", Xmpp.ResultSetManagement.NS_URI);
|
||||||
|
@ -92,7 +80,7 @@ public class Module : XmppStreamModule {
|
||||||
res.first = rsm_node.get_deep_string_content("first");
|
res.first = rsm_node.get_deep_string_content("first");
|
||||||
res.last = rsm_node.get_deep_string_content("last");
|
res.last = rsm_node.get_deep_string_content("last");
|
||||||
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_URI);
|
||||||
|
|
||||||
Idle.add(() => {
|
Idle.add(() => {
|
||||||
flag.active_query_ids.remove(query_id);
|
flag.active_query_ids.remove(query_id);
|
||||||
|
@ -110,15 +98,14 @@ 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) {
|
||||||
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
Flag flag = Flag.get_flag(stream);
|
||||||
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_URI + ":result", StanzaForwarding.NS_URI + ":forwarded", Xmpp.NS_URI + ":message");
|
||||||
if (message_node != null) {
|
if (message_node != null) {
|
||||||
StanzaNode? forward_node = message.stanza.get_deep_subnode(NS_VER(stream) + ":result", StanzaForwarding.NS_URI + ":forwarded", DelayedDelivery.NS_URI + ":delay");
|
StanzaNode? forward_node = message.stanza.get_deep_subnode(NS_URI + ":result", StanzaForwarding.NS_URI + ":forwarded", DelayedDelivery.NS_URI + ":delay");
|
||||||
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_URI + ":result", NS_URI + ":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_URI + ":result", NS_URI + ":queryid");
|
||||||
|
|
||||||
if (query_id == null) {
|
if (query_id == null) {
|
||||||
warning("Received MAM message without queryid from %s, ignoring", message.from.to_string());
|
warning("Received MAM message without queryid from %s, ignoring", message.from.to_string());
|
||||||
|
@ -154,10 +141,14 @@ 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 Gee.Set<string> active_query_ids { get; set; default = new HashSet<string>(); }
|
||||||
public string ns_ver;
|
|
||||||
|
|
||||||
public Flag(string ns_ver) {
|
public static Flag get_flag(XmppStream stream) {
|
||||||
this.ns_ver = ns_ver;
|
Flag? flag = stream.get_flag(Flag.IDENTITY);
|
||||||
|
if (flag == null) {
|
||||||
|
flag = new Flag();
|
||||||
|
stream.add_flag(flag);
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string get_ns() { return NS_URI; }
|
public override string get_ns() { return NS_URI; }
|
||||||
|
@ -185,8 +176,4 @@ public class MessageFlag : Xmpp.MessageFlag {
|
||||||
public override string get_id() { return ID; }
|
public override string get_id() { return ID; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string NS_VER(XmppStream stream) {
|
|
||||||
return stream.get_flag(Flag.IDENTITY).ns_ver;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue