ToxId ToxDNS::resolveToxAddress(const QString &address, bool silent) { ToxId toxId; if (address.isEmpty()) { return toxId; } else if (ToxId::isToxId(address)) { toxId = ToxId(address); return toxId; } else { // If we're querying one of our pinned server, do a tox3 request directly QString servname = address.mid(address.indexOf('@')+1); for (const ToxDNS::tox3_server& pin : ToxDNS::pinnedServers) { if (servname == pin.name) { toxId = ToxId(queryTox3(pin, address, silent)); return toxId; } } // Otherwise try tox3 if we can get a pubkey or fallback to tox1 QByteArray pubkey = fetchLastTextRecord("_tox."+servname, true); if (!pubkey.isEmpty()) { pubkey = QByteArray::fromHex(pubkey); QByteArray servnameData = servname.toUtf8(); ToxDNS::tox3_server server; server.name = servnameData.data(); server.pubkey = (uint8_t*)pubkey.data(); toxId = ToxId(queryTox3(server, address, silent)); } else { #if TOX1_SILENT_FALLBACK toxId = ToxId::fromString(queryTox1(address, silent)); #elif TOX1_ASK_FALLBACK QMessageBox::StandardButton btn = QMessageBox::warning(nullptr, "qTox", tr("It appears that qTox has to use the old protocol to access DNS record of your friend's Tox ID.\n" "Unfortunately tox1 is not secure, and you are at risk of someone hijacking what is sent between you and ToxDNS service.\n" "Should tox1 be used anyway?\n" "If unsure, press 'No', so that request to ToxDNS service will not be made using unsecure protocol."), QMessageBox::Yes|QMessageBox::No, QMessageBox::No); if (btn == QMessageBox::Ok) toxId = ToxId(queryTox1(address, silent)); #else return toxId; #endif } return toxId; } }
END_TEST START_TEST(validationTest) { ck_assert(ToxId(testToxId).isValid()); ck_assert(!ToxId(publicKey).isValid()); ck_assert(!ToxId(corrupted).isValid()); QString deadbeef = "DEADBEEF"; ck_assert(!ToxId(deadbeef).isValid()); }
void AddFriendForm::deleteFriendRequest(const QString& toxId) { int size = Settings::getInstance().getFriendRequestSize(); for (int i = 0; i < size; ++i) { Settings::Request request = Settings::getInstance().getFriendRequest(i); if (ToxId(toxId) == ToxId(request.address)) { Settings::getInstance().removeFriendRequest(i); return; } } }
QString Settings::getFriendAdress(const QString &publicKey) const { QMutexLocker locker{&bigLock}; QString key = ToxId(publicKey).publicKey; auto it = friendLst.find(key); if (it != friendLst.end()) return it->addr; return QString(); }
void AddFriendForm::setIdFromClipboard() { QClipboard* clipboard = QApplication::clipboard(); QString id = clipboard->text().trimmed(); if (Core::getInstance()->isReady() && !id.isEmpty() && ToxId::isToxId(id)) { if (!ToxId(id).isSelf()) toxId.setText(id); } }
void AddFriendForm::setIdFromClipboard() { QClipboard* clipboard = QApplication::clipboard(); QString id = clipboard->text().trimmed(); const Core* core = Core::getInstance(); if (core->isReady() && !id.isEmpty() && ToxId::isToxId(id) && ToxId(id) == core->getSelfId()) { toxId.setText(id); } }
void ProfileForm::onRegisterButtonClicked() { QString name = bodyUI->toxmeUsername->text(); if (name.isEmpty()) return; bodyUI->toxmeRegisterButton->setEnabled(false); bodyUI->toxmeUpdateButton->setEnabled(false); bodyUI->toxmeRegisterButton->setText(tr("Register (processing)")); bodyUI->toxmeUpdateButton->setText(tr("Update (processing)")); QString id = toxId->text(); QString bio = bodyUI->toxmeBio->text(); QString server = bodyUI->toxmeServersList->currentText(); bool privacy = bodyUI->toxmePrivacy->isChecked(); Core* oldCore = Core::getInstance(); Toxme::ExecCode code = Toxme::ExecCode::Ok; QString response = Toxme::createAddress(code, server, ToxId(id), name, privacy, bio); Core* newCore = Core::getInstance(); // Make sure the user didn't logout (or logout and login) // before the request is finished, else qTox will crash. if (oldCore == newCore) { switch (code) { case Toxme::Updated: GUI::showInfo(tr("Done!"), tr("Account %1@%2 updated successfully").arg(name, server)); Settings::getInstance().setToxme(name, server, bio, privacy); showExistingToxme(); break; case Toxme::Ok: GUI::showInfo(tr("Done!"), tr("Successfully added %1@%2 to the database. Save your password") .arg(name, server)); Settings::getInstance().setToxme(name, server, bio, privacy, response); showExistingToxme(); break; default: QString errorMessage = Toxme::getErrorMessage(code); qWarning() << errorMessage; QString translated = Toxme::translateErrorMessage(code); GUI::showWarning(tr("Toxme error"), translated); } bodyUI->toxmeRegisterButton->setEnabled(true); bodyUI->toxmeUpdateButton->setEnabled(true); bodyUI->toxmeRegisterButton->setText(tr("Register")); bodyUI->toxmeUpdateButton->setText(tr("Update")); } }
ToxId Toxme::lookup(QString address) { // JSON injection ? address = address.trimmed(); address.replace('\\',"\\\\"); address.replace('"',"\""); const QString json{"{\"action\":3,\"name\":\""+address+"\"}"}; QString apiUrl = "https://" + address.split(QLatin1Char('@')).last() + "/api"; QNetworkReply::NetworkError error = QNetworkReply::NoError; QByteArray response = makeJsonRequest(apiUrl, json, error); if (error != QNetworkReply::NoError) return ToxId(); static const QByteArray pattern{"tox_id\""}; const int index = response.indexOf(pattern); if (index == -1) return ToxId(); response = response.mid(index+pattern.size()); const int idStart = response.indexOf('"'); if (idStart == -1) return ToxId(); response = response.mid(idStart+1); const int idEnd = response.indexOf('"'); if (idEnd == -1) return ToxId(); response.truncate(idEnd); return ToxId(response); }
/** * @brief Get the public key of a peer of a group */ ToxId Core::getGroupPeerToxId(int groupId, int peerId) const { ToxId peerToxId; uint8_t rawID[TOX_PUBLIC_KEY_SIZE]; int res = tox_group_peer_pubkey(tox, groupId, peerId, rawID); if (res == -1) { qWarning() << "getGroupPeerToxId: Unknown error"; return peerToxId; } peerToxId = ToxId(CUserId::toString(rawID)); return peerToxId; }
void Settings::updateFriendAdress(const QString &newAddr) { QMutexLocker locker{&bigLock}; QString key = ToxId(newAddr).publicKey; auto it = friendLst.find(key); if (it != friendLst.end()) { it->addr = newAddr; } else { friendProp fp; fp.addr = newAddr; fp.alias = ""; fp.note = ""; fp.autoAcceptDir = ""; friendLst[newAddr] = fp; } }
void ChatForm::loadHistory(QDateTime since, bool processUndelivered) { QDateTime now = historyBaselineDate.addMSecs(-1); if (since > now) return; if (!earliestMessage.isNull()) { if (earliestMessage < since) return; if (earliestMessage < now) { now = earliestMessage; now = now.addMSecs(-1); } } auto msgs = HistoryKeeper::getInstance()->getChatHistory(HistoryKeeper::ctSingle, f->getToxID().publicKey, since, now); ToxId storedPrevId = previousId; ToxId prevId; QList<ChatLine::Ptr> historyMessages; QDate lastDate(1,0,0); for (const auto &it : msgs) { // Show the date every new day QDateTime msgDateTime = it.timestamp.toLocalTime(); QDate msgDate = msgDateTime.date(); if (msgDate > lastDate) { lastDate = msgDate; historyMessages.append(ChatMessage::createChatInfoMessage(msgDate.toString(Settings::getInstance().getDateFormat()), ChatMessage::INFO, QDateTime())); } // Show each messages ToxId authorId = ToxId(it.sender); QString authorStr = authorId.isActiveProfile() ? Core::getInstance()->getUsername() : resolveToxID(authorId); bool isAction = it.message.startsWith("/me ", Qt::CaseInsensitive); ChatMessage::Ptr msg = ChatMessage::createChatMessage(authorStr, isAction ? it.message.right(it.message.length() - 4) : it.message, isAction ? ChatMessage::ACTION : ChatMessage::NORMAL, authorId.isActiveProfile(), QDateTime()); if (!isAction && (prevId == authorId) && (prevMsgDateTime.secsTo(msgDateTime) < getChatLog()->repNameAfter) ) msg->hideSender(); prevId = authorId; prevMsgDateTime = msgDateTime; if (it.isSent || !authorId.isActiveProfile()) { msg->markAsSent(msgDateTime); } else { if (processUndelivered) { int rec; if (!isAction) rec = Core::getInstance()->sendMessage(f->getFriendID(), msg->toString()); else rec = Core::getInstance()->sendAction(f->getFriendID(), msg->toString()); getOfflineMsgEngine()->registerReceipt(rec, it.id, msg); } } historyMessages.append(msg); } previousId = storedPrevId; int savedSliderPos = chatWidget->verticalScrollBar()->maximum() - chatWidget->verticalScrollBar()->value(); earliestMessage = since; chatWidget->insertChatlineOnTop(historyMessages); savedSliderPos = chatWidget->verticalScrollBar()->maximum() - savedSliderPos; chatWidget->verticalScrollBar()->setValue(savedSliderPos); }
/** * @brief Called when user clicks the bottom OK button, save all settings */ void AboutUser::onAcceptedClicked() { ToxId toxId = ToxId(ui->publicKey->text()); Settings::getInstance().setContactNote(toxId, ui->note->toPlainText()); Settings::getInstance().saveGlobal(); }
/** * @brief Returns our Tox ID */ ToxId Core::getSelfId() const { uint8_t friendAddress[TOX_ADDRESS_SIZE] = {0}; tox_self_get_address(tox, friendAddress); return ToxId(CFriendAddress::toString(friendAddress)); }
void Settings::loadPersonal(Profile* profile) { QMutexLocker locker{&bigLock}; QDir dir(getSettingsDirPath()); QString filePath = dir.filePath(globalSettingsFile); // load from a profile specific friend data list if possible QString tmp = dir.filePath(profile->getName() + ".ini"); if (QFile(tmp).exists()) // otherwise, filePath remains the global file filePath = tmp; qDebug()<<"Loading personal settings from"<<filePath; SettingsSerializer ps(filePath, profile->getPassword()); ps.load(); friendLst.clear(); ps.beginGroup("Privacy"); typingNotification = ps.value("typingNotification", true).toBool(); enableLogging = ps.value("enableLogging", true).toBool(); ps.endGroup(); ps.beginGroup("Friends"); int size = ps.beginReadArray("Friend"); friendLst.reserve(size); for (int i = 0; i < size; i ++) { ps.setArrayIndex(i); friendProp fp; fp.addr = ps.value("addr").toString(); fp.alias = ps.value("alias").toString(); fp.note = ps.value("note").toString(); fp.autoAcceptDir = ps.value("autoAcceptDir").toString(); fp.circleID = ps.value("circle", -1).toInt(); if (getEnableLogging()) fp.activity = ps.value("activity", QDate()).toDate(); friendLst[ToxId(fp.addr).publicKey] = fp; } ps.endArray(); ps.endGroup(); ps.beginGroup("General"); compactLayout = ps.value("compactLayout", true).toBool(); ps.endGroup(); ps.beginGroup("Circles"); size = ps.beginReadArray("Circle"); circleLst.clear(); circleLst.reserve(size); for (int i = 0; i < size; i ++) { ps.setArrayIndex(i); circleProp cp; cp.name = ps.value("name").toString(); cp.expanded = ps.value("expanded", true).toBool(); circleLst.push_back(cp); } ps.endArray(); ps.endGroup(); }
/** * @brief Check, that id is a valid Tox ID. * @param id Tox ID to check. * @return True if id is a valid Tox ID, false otherwise. * @note Validates the checksum. */ bool ToxId::isValidToxId(const QString& id) { return isToxId(id) && ToxId(id).isValid(); }
/** * @brief Returns our Tox ID */ ToxId Core::getSelfId() const { uint8_t friendId[TOX_ADDRESS_SIZE] = {0x00}; tox_self_get_address(tox, friendId); return ToxId(friendId, TOX_ADDRESS_SIZE); }