Commit c2095923 authored by Guillaume Roguez's avatar Guillaume Roguez

fix the non-checked call to lrc ContactModel::getContact()

This method throws an std::out_of_range exception when
given URI argument doesn't exit in current Account.
This exception is almost not handled by the client,
resulting in application crashes.

Change-Id: I1aea181c238c15ab16d51b8477a7779ce3c82a03
Reviewed-by: Sébastien Blin's avatarSébastien Blin <sebastien.blin@savoirfairelinux.com>
parent a04f4422
......@@ -267,13 +267,17 @@ load_participants_images(ChatView *self)
// Contact
if (!priv->conversation_) return;
auto contactUri = priv->conversation_->participants.front();
auto& contact = priv->accountContainer_->info.contactModel->getContact(contactUri);
if (!contact.profileInfo.avatar.empty()) {
webkit_chat_container_set_sender_image(
WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
priv->accountContainer_->info.contactModel->getContactProfileId(contactUri),
contact.profileInfo.avatar
);
try{
auto& contact = priv->accountContainer_->info.contactModel->getContact(contactUri);
if (!contact.profileInfo.avatar.empty()) {
webkit_chat_container_set_sender_image(
WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
priv->accountContainer_->info.contactModel->getContactProfileId(contactUri),
contact.profileInfo.avatar
);
}
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
// For this account
......@@ -306,10 +310,14 @@ update_add_to_conversations(ChatView *self)
if (!priv->conversation_) return;
auto participant = priv->conversation_->participants[0];
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(participant);
if(contactInfo.profileInfo.type != lrc::api::profile::Type::TEMPORARY
&& contactInfo.profileInfo.type != lrc::api::profile::Type::PENDING)
gtk_widget_hide(priv->button_add_to_conversations);
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(participant);
if(contactInfo.profileInfo.type != lrc::api::profile::Type::TEMPORARY
&& contactInfo.profileInfo.type != lrc::api::profile::Type::PENDING)
gtk_widget_hide(priv->button_add_to_conversations);
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
static void
......@@ -319,15 +327,18 @@ update_contact_methods(ChatView *self)
ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
if (!priv->conversation_) return;
auto contactUri = priv->conversation_->participants.front();
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
auto bestId = std::string(contactInfo.registeredName).empty() ? contactInfo.profileInfo.uri : contactInfo.registeredName;
if (contactInfo.profileInfo.alias == bestId) {
gtk_widget_hide(priv->label_cm);
} else {
gtk_label_set_text(GTK_LABEL(priv->label_cm), bestId.c_str());
gtk_widget_show(priv->label_cm);
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
auto bestId = std::string(contactInfo.registeredName).empty() ? contactInfo.profileInfo.uri : contactInfo.registeredName;
if (contactInfo.profileInfo.alias == bestId) {
gtk_widget_hide(priv->label_cm);
} else {
gtk_label_set_text(GTK_LABEL(priv->label_cm), bestId.c_str());
gtk_widget_show(priv->label_cm);
}
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
static void
......@@ -337,10 +348,14 @@ update_name(ChatView *self)
ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
if (!priv->conversation_) return;
auto contactUri = priv->conversation_->participants.front();
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
auto alias = contactInfo.profileInfo.alias;
alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end());
gtk_label_set_text(GTK_LABEL(priv->label_peer), alias.c_str());
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
auto alias = contactInfo.profileInfo.alias;
alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end());
gtk_label_set_text(GTK_LABEL(priv->label_peer), alias.c_str());
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
static void
......@@ -379,22 +394,26 @@ webkit_chat_container_ready(ChatView* self)
if (!priv->conversation_) return;
auto contactUri = priv->conversation_->participants.front();
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
priv->isTemporary_ = contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY
|| contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING;
webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
auto bestName = contactInfo.profileInfo.alias;
if (bestName.empty())
bestName = contactInfo.registeredName;
if (bestName.empty())
bestName = contactInfo.profileInfo.uri;
bestName.erase(std::remove(bestName.begin(), bestName.end(), '\r'), bestName.end());
webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
(contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING),
bestName);
webkit_chat_disable_send_interaction(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
(contactInfo.profileInfo.type == lrc::api::profile::Type::SIP)
&& priv->conversation_->callId.empty());
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
priv->isTemporary_ = contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY
|| contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING;
webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
auto bestName = contactInfo.profileInfo.alias;
if (bestName.empty())
bestName = contactInfo.registeredName;
if (bestName.empty())
bestName = contactInfo.profileInfo.uri;
bestName.erase(std::remove(bestName.begin(), bestName.end(), '\r'), bestName.end());
webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
(contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING),
bestName);
webkit_chat_disable_send_interaction(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
(contactInfo.profileInfo.type == lrc::api::profile::Type::SIP)
&& priv->conversation_->callId.empty());
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
static void
......@@ -457,15 +476,19 @@ chat_view_update_temporary(ChatView* self, bool newValue)
webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
if (!priv->conversation_) return;
auto contactUri = priv->conversation_->participants.front();
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
auto bestName = contactInfo.profileInfo.alias;
if (bestName.empty())
bestName = contactInfo.registeredName;
if (bestName.empty())
bestName = contactInfo.profileInfo.uri;
webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
newValue,
bestName);
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
auto bestName = contactInfo.profileInfo.alias;
if (bestName.empty())
bestName = contactInfo.registeredName;
if (bestName.empty())
bestName = contactInfo.profileInfo.uri;
webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
newValue,
bestName);
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
bool
......
......@@ -160,46 +160,49 @@ update(GtkTreeSelection *selection, ConversationPopupMenu *self)
auto idx = gtk_tree_path_get_indices(path);
auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(idx[0]);
priv->row_ = idx[0];
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(conversation.participants.front());
if (contactInfo.profileInfo.uri.empty()) return;
// we always build a menu, however in some cases some or all of the conversations will be deactivated
// we prefer this to having an empty menu because GTK+ behaves weird in the empty menu case
auto place_call_conversation = gtk_menu_item_new_with_mnemonic(_("_Place call"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), place_call_conversation);
g_signal_connect(place_call_conversation, "activate", G_CALLBACK(place_call), priv);
auto copy_name = gtk_menu_item_new_with_mnemonic(_("_Copy name"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), copy_name);
g_signal_connect(copy_name, "activate", G_CALLBACK(copy_contact_info), priv);
if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY ||
contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING) {
// If we can add this conversation
auto add_conversation_conversation = gtk_menu_item_new_with_mnemonic(_("_Add to conversations"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), add_conversation_conversation);
g_signal_connect(add_conversation_conversation, "activate", G_CALLBACK(add_conversation), priv);
if (contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING) {
auto rm_conversation_item = gtk_menu_item_new_with_mnemonic(_("_Discard invitation"));
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(conversation.participants.front());
if (contactInfo.profileInfo.uri.empty()) return;
// we always build a menu, however in some cases some or all of the conversations will be deactivated
// we prefer this to having an empty menu because GTK+ behaves weird in the empty menu case
auto place_call_conversation = gtk_menu_item_new_with_mnemonic(_("_Place call"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), place_call_conversation);
g_signal_connect(place_call_conversation, "activate", G_CALLBACK(place_call), priv);
auto copy_name = gtk_menu_item_new_with_mnemonic(_("_Copy name"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), copy_name);
g_signal_connect(copy_name, "activate", G_CALLBACK(copy_contact_info), priv);
if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY ||
contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING) {
// If we can add this conversation
auto add_conversation_conversation = gtk_menu_item_new_with_mnemonic(_("_Add to conversations"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), add_conversation_conversation);
g_signal_connect(add_conversation_conversation, "activate", G_CALLBACK(add_conversation), priv);
if (contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING) {
auto rm_conversation_item = gtk_menu_item_new_with_mnemonic(_("_Discard invitation"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), rm_conversation_item);
g_signal_connect(rm_conversation_item, "activate", G_CALLBACK(remove_conversation), priv);
auto block_conversation_item = gtk_menu_item_new_with_mnemonic(_("_Block invitations"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), block_conversation_item);
g_signal_connect(block_conversation_item, "activate", G_CALLBACK(block_conversation), priv);
}
} else {
auto rm_history_conversation = gtk_menu_item_new_with_mnemonic(_("C_lear history"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), rm_history_conversation);
g_signal_connect(rm_history_conversation, "activate", G_CALLBACK(remove_history_conversation), priv);
auto rm_conversation_item = gtk_menu_item_new_with_mnemonic(_("_Remove conversation"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), rm_conversation_item);
g_signal_connect(rm_conversation_item, "activate", G_CALLBACK(remove_conversation), priv);
auto block_conversation_item = gtk_menu_item_new_with_mnemonic(_("_Block invitations"));
auto block_conversation_item = gtk_menu_item_new_with_mnemonic(_("_Block contact"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), block_conversation_item);
g_signal_connect(block_conversation_item, "activate", G_CALLBACK(block_conversation), priv);
}
} else {
auto rm_history_conversation = gtk_menu_item_new_with_mnemonic(_("C_lear history"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), rm_history_conversation);
g_signal_connect(rm_history_conversation, "activate", G_CALLBACK(remove_history_conversation), priv);
auto rm_conversation_item = gtk_menu_item_new_with_mnemonic(_("_Remove conversation"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), rm_conversation_item);
g_signal_connect(rm_conversation_item, "activate", G_CALLBACK(remove_conversation), priv);
auto block_conversation_item = gtk_menu_item_new_with_mnemonic(_("_Block contact"));
gtk_menu_shell_append(GTK_MENU_SHELL(self), block_conversation_item);
g_signal_connect(block_conversation_item, "activate", G_CALLBACK(block_conversation), priv);
}
/* show all conversations */
gtk_widget_show_all(GTK_WIDGET(self));
/* show all conversations */
gtk_widget_show_all(GTK_WIDGET(self));
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
static void
......
......@@ -240,21 +240,25 @@ create_and_fill_model(ConversationsView *self)
for (auto conversation : priv->accountContainer_->info.conversationModel->allFilteredConversations()) {
if (conversation.participants.empty()) break; // Should not
auto contactUri = conversation.participants.front();
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
auto lastMessage = conversation.interactions.empty() ? "" :
conversation.interactions.at(conversation.lastMessageUid).body;
std::replace(lastMessage.begin(), lastMessage.end(), '\n', ' ');
gtk_list_store_append (store, &iter);
auto alias = contactInfo.profileInfo.alias;
alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end());
gtk_list_store_set (store, &iter,
0 /* col # */ , conversation.uid.c_str() /* celldata */,
1 /* col # */ , alias.c_str() /* celldata */,
2 /* col # */ , contactInfo.profileInfo.uri.c_str() /* celldata */,
3 /* col # */ , contactInfo.registeredName.c_str() /* celldata */,
4 /* col # */ , contactInfo.profileInfo.avatar.c_str() /* celldata */,
5 /* col # */ , lastMessage.c_str() /* celldata */,
-1 /* end */);
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
auto lastMessage = conversation.interactions.empty() ? "" :
conversation.interactions.at(conversation.lastMessageUid).body;
std::replace(lastMessage.begin(), lastMessage.end(), '\n', ' ');
gtk_list_store_append (store, &iter);
auto alias = contactInfo.profileInfo.alias;
alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end());
gtk_list_store_set (store, &iter,
0 /* col # */ , conversation.uid.c_str() /* celldata */,
1 /* col # */ , alias.c_str() /* celldata */,
2 /* col # */ , contactInfo.profileInfo.uri.c_str() /* celldata */,
3 /* col # */ , contactInfo.registeredName.c_str() /* celldata */,
4 /* col # */ , contactInfo.profileInfo.avatar.c_str() /* celldata */,
5 /* col # */ , lastMessage.c_str() /* celldata */,
-1 /* end */);
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
return GTK_TREE_MODEL (store);
......
......@@ -765,15 +765,18 @@ update_name_and_photo(CurrentCallView *view)
std::shared_ptr<GdkPixbuf> image = var_i.value<std::shared_ptr<GdkPixbuf>>();
gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_peer), image.get());
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(priv->conversation_->participants.front());
auto name = contactInfo.profileInfo.alias;
gtk_label_set_text(GTK_LABEL(priv->label_name), name.c_str());
auto bestId = contactInfo.registeredName;
if (name != bestId) {
gtk_label_set_text(GTK_LABEL(priv->label_bestId), bestId.c_str());
gtk_widget_show(priv->label_bestId);
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(priv->conversation_->participants.front());
auto name = contactInfo.profileInfo.alias;
gtk_label_set_text(GTK_LABEL(priv->label_name), name.c_str());
auto bestId = contactInfo.registeredName;
if (name != bestId) {
gtk_label_set_text(GTK_LABEL(priv->label_bestId), bestId.c_str());
gtk_widget_show(priv->label_bestId);
}
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
......
......@@ -121,12 +121,16 @@ accept_incoming_call(G_GNUC_UNUSED GtkWidget *widget, ChatView *self)
{
auto priv = INCOMING_CALL_VIEW_GET_PRIVATE(self);
auto contactUri = priv->conversation_->participants[0];
auto contact = priv->accountContainer_->info.contactModel->getContact(contactUri);
// If the contact is pending, we should accept its request
if (contact.profileInfo.type == lrc::api::profile::Type::PENDING)
priv->accountContainer_->info.conversationModel->makePermanent(contactUri);
// Accept call
priv->accountContainer_->info.callModel->accept(priv->conversation_->callId);
try {
auto contact = priv->accountContainer_->info.contactModel->getContact(contactUri);
// If the contact is pending, we should accept its request
if (contact.profileInfo.type == lrc::api::profile::Type::PENDING)
priv->accountContainer_->info.conversationModel->makePermanent(contactUri);
// Accept call
priv->accountContainer_->info.callModel->accept(priv->conversation_->callId);
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
static void
......@@ -217,15 +221,19 @@ update_name_and_photo(IncomingCallView *view)
std::shared_ptr<GdkPixbuf> image = var_i.value<std::shared_ptr<GdkPixbuf>>();
gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_incoming), image.get());
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(priv->conversation_->participants.front());
try {
auto contactInfo = priv->accountContainer_->info.contactModel->getContact(priv->conversation_->participants.front());
auto name = contactInfo.profileInfo.alias;
gtk_label_set_text(GTK_LABEL(priv->label_name), name.c_str());
auto name = contactInfo.profileInfo.alias;
gtk_label_set_text(GTK_LABEL(priv->label_name), name.c_str());
auto bestId = contactInfo.registeredName;
if (name != bestId) {
gtk_label_set_text(GTK_LABEL(priv->label_bestId), bestId.c_str());
gtk_widget_show(priv->label_bestId);
auto bestId = contactInfo.registeredName;
if (name != bestId) {
gtk_label_set_text(GTK_LABEL(priv->label_bestId), bestId.c_str());
gtk_widget_show(priv->label_bestId);
}
} catch (const std::out_of_range&) {
// ContactModel::getContact() exception
}
}
......
......@@ -269,27 +269,27 @@ PixbufManipulator::conversationPhoto(const lrc::api::conversation::Info& convers
bool displayPresence)
{
auto contacts = conversationInfo.participants;
if (!contacts.empty())
{
// Get first contact photo
auto contactUri = contacts.front();
auto contactInfo = accountInfo.contactModel->getContact(contactUri);
auto contactPhoto = contactInfo.profileInfo.avatar;
auto bestName = contactInfo.profileInfo.alias.empty()? contactInfo.registeredName : contactInfo.profileInfo.alias;
auto unreadMessages = conversationInfo.unreadMessages;
if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY && contactInfo.profileInfo.uri.empty()) {
return QVariant::fromValue(scaleAndFrame(temporaryItemAvatar().get(), size, false, false, unreadMessages));
} else if (contactInfo.profileInfo.type == lrc::api::profile::Type::SIP) {
return QVariant::fromValue(scaleAndFrame(generateAvatar(bestName, "").get(), size, displayPresence, contactInfo.isPresent));
} else if (!contactPhoto.empty()) {
QByteArray byteArray(contactPhoto.c_str(), contactPhoto.length());
QVariant photo = personPhoto(byteArray);
return QVariant::fromValue(scaleAndFrame(photo.value<std::shared_ptr<GdkPixbuf>>().get(), size, displayPresence, contactInfo.isPresent, unreadMessages));
} else {
return QVariant::fromValue(scaleAndFrame(generateAvatar(bestName, contactInfo.profileInfo.uri).get(), size, displayPresence, contactInfo.isPresent, unreadMessages));
}
if (!contacts.empty()) {
try {
// Get first contact photo
auto contactUri = contacts.front();
auto contactInfo = accountInfo.contactModel->getContact(contactUri);
auto contactPhoto = contactInfo.profileInfo.avatar;
auto bestName = contactInfo.profileInfo.alias.empty()? contactInfo.registeredName : contactInfo.profileInfo.alias;
auto unreadMessages = conversationInfo.unreadMessages;
if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY && contactInfo.profileInfo.uri.empty()) {
return QVariant::fromValue(scaleAndFrame(temporaryItemAvatar().get(), size, false, false, unreadMessages));
} else if (contactInfo.profileInfo.type == lrc::api::profile::Type::SIP) {
return QVariant::fromValue(scaleAndFrame(generateAvatar(bestName, "").get(), size, displayPresence, contactInfo.isPresent));
} else if (!contactPhoto.empty()) {
QByteArray byteArray(contactPhoto.c_str(), contactPhoto.length());
QVariant photo = personPhoto(byteArray);
return QVariant::fromValue(scaleAndFrame(photo.value<std::shared_ptr<GdkPixbuf>>().get(), size, displayPresence, contactInfo.isPresent, unreadMessages));
} else {
return QVariant::fromValue(scaleAndFrame(generateAvatar(bestName, contactInfo.profileInfo.uri).get(), size, displayPresence, contactInfo.isPresent, unreadMessages));
}
} catch (...) {}
}
// should not
return QVariant::fromValue(scaleAndFrame(generateAvatar("", "").get(), size, displayPresence, false));
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment