void Client::updateClientSettingsInfo(QString const& currentFileName) { ui.lblClientIni->setText(currentFileName); if (clientConfiguration != nullptr) { if (!contactRegistry->hasIdentity(clientConfiguration->getClientIdentity())) { IdentityContact* iContact = new IdentityContact(clientConfiguration->getClientIdentity(), clientConfiguration->getClientLongTermKeyPair()); iContact->setNickname("You"); contactRegistry->addIdentity(iContact); } contactRegistry->setSelfContact(contactRegistry->getIdentity(clientConfiguration->getClientIdentity())); } }
void Client::listContactsOnDoubleClick(QListWidgetItem* item) { ContactListWidgetItem* clwi = dynamic_cast<ContactListWidgetItem*>(item); if (clwi != nullptr) { ChatTab* tab = nullptr; if (clwi->getContact()->getContactType() == Contact::ContactType::CONTACT_IDENTITY) { IdentityContact* ic = dynamic_cast<IdentityContact*>(clwi->getContact()); tab = MessageCenter::getInstance()->ensureTabOpenForIdentityContact(ic->getContactId()); } else if (clwi->getContact()->getContactType() == Contact::ContactType::CONTACT_GROUP) { GroupContact* gc = dynamic_cast<GroupContact*>(clwi->getContact()); tab = MessageCenter::getInstance()->ensureTabOpenForGroupContact(gc->getGroupId()); } else { LOGGER()->warn("Could not determine the type of element the user double clicked on in the contacts list."); return; } if (tab != nullptr) { ui.tabWidget->setCurrentWidget(tab); } else { LOGGER()->warn("Could not open tab for user or group the user double clicked on in the contacts list."); } } }
void ContactRegistry::fromFile(QString const& filename, bool dryRun) { if (!QFile::exists(filename)) { throw IllegalArgumentException() << QString("Could not open the specified contacts file as it does not exist: %1").arg(filename).toStdString(); } QFile inputFile(filename); if (!inputFile.open(QFile::ReadOnly | QFile::Text)) { throw IllegalArgumentException() << QString("Could not open the specified contacts file for reading: %1").arg(filename).toStdString(); } QRegExp commentRegExp("^\\s*#.*$", Qt::CaseInsensitive, QRegExp::RegExp2); QRegExp identityRegExp("^\\s*([A-Z0-9]{8})\\s*:\\s*([a-fA-F0-9]{64})\\s*(?::\\s*(.*)\\s*)?$", Qt::CaseInsensitive, QRegExp::RegExp2); QRegExp groupRegExp("^\\s*([a-fA-F0-9]{16})\\s*:\\s*([A-Z0-9]{8})\\s*:\\s*([A-Z0-9]{8}(?:\\s*,\\s*[A-Z0-9]{8})*)\\s*:\\s*(.*)\\s*$", Qt::CaseInsensitive, QRegExp::RegExp2); QTextStream in(&inputFile); in.setCodec("UTF-8"); // change the file codec to UTF-8. while (!in.atEnd()) { QString line = in.readLine().trimmed(); if (line.isEmpty() || commentRegExp.exactMatch(line)) { continue; } else if (identityRegExp.exactMatch(line)) { if (!dryRun) { accessMutex.lock(); ContactId const contactId(identityRegExp.cap(1)); IdentityContact* iContact = new IdentityContact(contactId, PublicKey::fromHexString(identityRegExp.cap(2))); if (!identityRegExp.cap(3).trimmed().isEmpty()) { // Nickname given. iContact->setNickname(identityRegExp.cap(3).trimmed()); } connectContact(iContact); identityToIdentityContactHashMap.insert(contactId, iContact); accessMutex.unlock(); } } else if (groupRegExp.exactMatch(line)) { if (!dryRun) { accessMutex.lock(); quint64 groupIdentity = IdentityHelper::groupIdByteArrayToUint64(QByteArray::fromHex(groupRegExp.cap(1).toLatin1())); quint64 groupOwner = IdentityHelper::identityStringToUint64(groupRegExp.cap(2)); GroupContact* gContact = new GroupContact(GroupId(groupOwner, groupIdentity)); if (!groupRegExp.cap(4).trimmed().isEmpty()) { gContact->setGroupName(groupRegExp.cap(4).trimmed()); } QStringList ids = groupRegExp.cap(3).split(',', QString::SkipEmptyParts); if (ids.size() == 0) { throw IllegalArgumentException() << QString("Invalid or ill-formated line in contacts file \"%1\".\nProblematic line: %2").arg(filename).arg(line).toStdString(); } QStringList::const_iterator it = ids.constBegin(); QStringList::const_iterator end = ids.constEnd(); for (; it != end; ++it) { QString trimmedId(it->trimmed()); ContactId const memberId(trimmedId); gContact->addMember(memberId); } connectContact(gContact); identityToGroupContactHashMap.insert(GroupId(groupOwner, groupIdentity), gContact); accessMutex.unlock(); } } else { throw IllegalArgumentException() << QString("Invalid or ill-formated line in contacts file \"%1\".\nProblematic line: %2").arg(filename).arg(line).toStdString(); } } inputFile.close(); if (!dryRun) { emit identitiesChanged(); } }
void ContactRegistry::toFile(QString const& filename) const { QFile outputFile(filename); if (!outputFile.open(QFile::WriteOnly | QFile::Text)) { throw IllegalArgumentException() << QString("Could not open the specified contacts file for writing: %1").arg(filename).toStdString(); } QTextStream outStream(&outputFile); outStream.setCodec("UTF-8"); // change the file codec to UTF-8. outStream << "# This is a comment line.\n"; outStream << "# Format of this file: \n"; outStream << "# IDENTITY : PUBKEY : Nickname\n"; outStream << "# where \n"; outStream << "# - IDENTITY is an eight character ID of the form [A-Z0-9]{8} and stands for a users public id,\n"; outStream << "# - PUBKEY is an 64 character key of the form [a-fA-F0-9]{64} and stands for a users 32-Byte long-term public key,\n"; outStream << "# - Nickname is an optional screen-name for the given identity.\n"; outStream << "# GROUPID : GROUPOWNER : IDENTITY, IDENTITY, IDENTITY : Group Name\n"; outStream << "# where \n"; outStream << "# - IDENTITY is an eight character ID of the form [A-Z0-9]{8} and stands for a users public id,\n"; outStream << "# - GROUPID is an 16 character key of the form [a-fA-F0-9]{16} and stands for a groups unique identifier,\n"; outStream << "# - GROUPOWNER is an IDENTITY and stands for a groups creator and owner,\n"; outStream << "# - Group Name is the displayed title of the group.\n"; accessMutex.lock(); // Convert identityToIdentityContactHashMap into a QMap for sorted output. QMap<ContactId, IdentityContact*> sortedContactMap; QHash<ContactId, IdentityContact*>::const_iterator itContacts = identityToIdentityContactHashMap.constBegin(); QHash<ContactId, IdentityContact*>::const_iterator endContacts = identityToIdentityContactHashMap.constEnd(); for (; itContacts != endContacts; ++itContacts) { sortedContactMap.insert(itContacts.key(), itContacts.value()); } QMap<ContactId, IdentityContact*>::const_iterator itSortedContacts = sortedContactMap.constBegin(); QMap<ContactId, IdentityContact*>::const_iterator endSortedContacts = sortedContactMap.constEnd(); for (; itSortedContacts != endSortedContacts; ++itSortedContacts) { IdentityContact* ic = itSortedContacts.value(); QString nickname = ic->getNickname(); if (nickname.isNull() || nickname.isEmpty()) { nickname = ""; } outStream << ic->getContactId().toQString() << " : " << QString(ic->getPublicKey().getPublicKey().toHex()) << " : " << nickname << "\n"; } // Convert identityToGroupContactHashMap into a QMap for sorted output. QMap<GroupId, GroupContact*> sortedGroupMap; QHash<GroupId, GroupContact*>::const_iterator itGroups = identityToGroupContactHashMap.constBegin(); QHash<GroupId, GroupContact*>::const_iterator endGroups = identityToGroupContactHashMap.constEnd(); for (; itGroups != endGroups; ++itGroups) { sortedGroupMap.insert(itGroups.key(), itGroups.value()); } QMap<GroupId, GroupContact*>::const_iterator itSortedGroups = sortedGroupMap.constBegin(); QMap<GroupId, GroupContact*>::const_iterator endSortedGroups = sortedGroupMap.constEnd(); for (; itSortedGroups != endSortedGroups; ++itSortedGroups) { GroupContact* gc = itSortedGroups.value(); QSet<ContactId> const& members = gc->getGroupMembers(); QSet<ContactId>::const_iterator membersIt = members.constBegin(); QSet<ContactId>::const_iterator membersEnd = members.constEnd(); QStringList memberIds; for (; membersIt != membersEnd; ++membersIt) { memberIds.append(membersIt->toQString()); } memberIds.sort(Qt::CaseInsensitive); outStream << gc->getGroupId().toContactFileFormat() << " : " << memberIds.join(',') << " : " << gc->getContactName() << "\n"; } accessMutex.unlock(); outputFile.close(); }
void Client::listContactsOnContextMenu(QPoint const& pos) { QPoint globalPos = ui.listContacts->viewport()->mapToGlobal(pos); QListWidgetItem* listItem = ui.listContacts->itemAt(pos); ContactListWidgetItem* clwi = dynamic_cast<ContactListWidgetItem*>(listItem); if (clwi != nullptr) { QMenu listContactsContextMenu; QAction* actionHeadline = nullptr; QAction* actionEdit = nullptr; QAction* actionOpenClose = nullptr; QAction* actionRequestSync = nullptr; bool isChatWindowOpen = false; bool isIdentityContact = false; bool isGroupSelfOwned = false; ChatTab* tab = nullptr; if (clwi->getContact()->getContactType() == Contact::ContactType::CONTACT_IDENTITY) { IdentityContact* ic = dynamic_cast<IdentityContact*>(clwi->getContact()); isIdentityContact = true; actionHeadline = new QAction(QString("Identity: %1").arg(ic->getContactId().toQString()), &listContactsContextMenu); listContactsContextMenu.addAction(actionHeadline); actionEdit = new QAction("Edit Contact", &listContactsContextMenu); listContactsContextMenu.addAction(actionEdit); isChatWindowOpen = MessageCenter::getInstance()->hasTabOpenForIdentityContact(ic->getContactId()); if (isChatWindowOpen) { tab = MessageCenter::getInstance()->ensureTabOpenForIdentityContact(ic->getContactId()); actionOpenClose = new QAction("Close Chat Window", &listContactsContextMenu); } else { actionOpenClose = new QAction("Open Chat Window", &listContactsContextMenu); } listContactsContextMenu.addAction(actionOpenClose); } else { GroupContact* gc = dynamic_cast<GroupContact*>(clwi->getContact()); isIdentityContact = false; actionHeadline = new QAction(QString("Group: %1").arg(gc->getGroupId().toQString()), &listContactsContextMenu); listContactsContextMenu.addAction(actionHeadline); actionEdit = new QAction("Edit Group", &listContactsContextMenu); listContactsContextMenu.addAction(actionEdit); isChatWindowOpen = MessageCenter::getInstance()->hasTabOpenForGroupContact(gc->getGroupId()); if (isChatWindowOpen) { tab = MessageCenter::getInstance()->ensureTabOpenForGroupContact(gc->getGroupId()); actionOpenClose = new QAction("Close Chat Window", &listContactsContextMenu); } else { actionOpenClose = new QAction("Open Chat Window", &listContactsContextMenu); } listContactsContextMenu.addAction(actionOpenClose); if (gc->getGroupOwner() == ContactRegistry::getInstance()->getSelfContact()->getContactId()) { isGroupSelfOwned = true; actionRequestSync = new QAction("Force Group Sync", &listContactsContextMenu); } else { actionRequestSync = new QAction("Request Group Sync", &listContactsContextMenu); } listContactsContextMenu.addAction(actionRequestSync); if (protocolClient == nullptr || !protocolClient->getIsConnected()) { actionRequestSync->setDisabled(true); } } QAction* selectedItem = listContactsContextMenu.exec(globalPos); if (selectedItem != nullptr) { if (selectedItem == actionEdit) { showNotYetImplementedInfo(); } else if (selectedItem == actionOpenClose) { if (isChatWindowOpen) { if (isIdentityContact) { IdentityContact* ic = dynamic_cast<IdentityContact*>(clwi->getContact()); MessageCenter::getInstance()->closeTabForIdentityContact(ic->getContactId()); } else { GroupContact* gc = dynamic_cast<GroupContact*>(clwi->getContact()); MessageCenter::getInstance()->closeTabForGroupContact(gc->getGroupId()); } } else { if (isIdentityContact) { IdentityContact* ic = dynamic_cast<IdentityContact*>(clwi->getContact()); tab = MessageCenter::getInstance()->ensureTabOpenForIdentityContact(ic->getContactId()); } else { GroupContact* gc = dynamic_cast<GroupContact*>(clwi->getContact()); tab = MessageCenter::getInstance()->ensureTabOpenForGroupContact(gc->getGroupId()); } if (tab != nullptr) { ui.tabWidget->setCurrentWidget(tab); } } } else if (!isIdentityContact && (selectedItem == actionRequestSync) && (actionRequestSync != nullptr)) { if (protocolClient == nullptr || !protocolClient->getIsConnected()) { return; } GroupContact* gc = dynamic_cast<GroupContact*>(clwi->getContact()); if (isGroupSelfOwned) { QMetaObject::invokeMethod(protocolClient, "resendGroupSetup", Qt::QueuedConnection, Q_ARG(GroupId const&, gc->getGroupId())); } else { QMetaObject::invokeMethod(protocolClient, "requestGroupSync", Qt::QueuedConnection, Q_ARG(GroupId const&, gc->getGroupId())); } } }