/* * Squawk messenger. * Copyright (C) 2019 Yury Gubich * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "message.h" #include "utils.h" Shared::Message::Message(Shared::Message::Type p_type): jFrom(), rFrom(), jTo(), rTo(), id(), body(), time(), thread(), type(p_type), outgoing(false), forwarded(false), state(State::delivered), edited(false), errorText(), originalMessage(), lastModified(), stanzaId(), attachPath(), encryption(EncryptionProtocol::none) {} Shared::Message::Message(): jFrom(), rFrom(), jTo(), rTo(), id(), body(), time(), thread(), type(Message::normal), outgoing(false), forwarded(false), state(State::delivered), edited(false), errorText(), originalMessage(), lastModified(), stanzaId(), attachPath(), encryption(EncryptionProtocol::none) {} QString Shared::Message::getBody() const { return body; } QString Shared::Message::getFrom() const { QString from = jFrom; if (rFrom.size() > 0) from += "/" + rFrom; return from; } QString Shared::Message::getTo() const { QString to = jTo; if (rTo.size() > 0) to += "/" + rTo; return to; } QString Shared::Message::getId() const { if (id.size() > 0) return id; else return stanzaId; } QDateTime Shared::Message::getTime() const { return time; } void Shared::Message::setBody(const QString& p_body) { body = p_body; } void Shared::Message::setFrom(const QString& from) { QStringList list = from.split("/"); if (list.size() == 1) { jFrom = from.toLower(); } else { jFrom = list.front().toLower(); rFrom = list.back(); } } void Shared::Message::setTo(const QString& to) { QStringList list = to.split("/"); if (list.size() == 1) { jTo = to.toLower(); } else { jTo = list.front().toLower(); rTo = list.back(); } } void Shared::Message::setId(const QString& p_id) { id = p_id; } void Shared::Message::setTime(const QDateTime& p_time) { time = p_time; } QString Shared::Message::getFromJid() const { return jFrom; } QString Shared::Message::getFromResource() const { return rFrom; } QString Shared::Message::getToJid() const { return jTo; } QString Shared::Message::getToResource() const { return rTo; } QString Shared::Message::getErrorText() const { return errorText; } QString Shared::Message::getPenPalJid() const { if (outgoing) return jTo; else return jFrom; } QString Shared::Message::getPenPalResource() const { if (outgoing) return rTo; else return rFrom; } Shared::Message::State Shared::Message::getState() const { return state; } bool Shared::Message::getEdited() const { return edited; } void Shared::Message::setFromJid(const QString& from) { jFrom = from.toLower(); } void Shared::Message::setFromResource(const QString& from) { rFrom = from; } void Shared::Message::setToJid(const QString& to) { jTo = to.toLower(); } void Shared::Message::setToResource(const QString& to) { rTo = to; } void Shared::Message::setErrorText(const QString& err) { if (state == State::error) errorText = err; } bool Shared::Message::getOutgoing() const { return outgoing; } void Shared::Message::setOutgoing(bool og) { outgoing = og; } bool Shared::Message::getForwarded() const { return forwarded; } void Shared::Message::generateRandomId() { id = generateUUID(); } QString Shared::Message::getThread() const { return thread; } void Shared::Message::setForwarded(bool fwd) { forwarded = fwd; } void Shared::Message::setThread(const QString& p_body) { thread = p_body; } QDateTime Shared::Message::getLastModified() const { return lastModified; } QString Shared::Message::getOriginalBody() const { return originalMessage; } Shared::Message::Type Shared::Message::getType() const { return type; } void Shared::Message::setType(Shared::Message::Type t) { type = t; } void Shared::Message::setState(Shared::Message::State p_state) { state = p_state; if (state != State::error) errorText = ""; } bool Shared::Message::serverStored() const { return state == State::delivered || state == State::sent; } void Shared::Message::setEdited(bool p_edited) { edited = p_edited; } Shared::EncryptionProtocol Shared::Message::getEncryption() const { return encryption; } void Shared::Message::setEncryption(EncryptionProtocol encryption) { Shared::Message::encryption = encryption; } void Shared::Message::setError(const QString& text) { state = State::error; errorText = text; } QDataStream& operator<<(QDataStream& out, const Shared::Message& info) { out << info.jFrom; out << info.rFrom; out << info.jTo; out << info.rTo; out << info.id; out << info.body; quint64 msecs = info.time.toMSecsSinceEpoch(); out << msecs; out << info.thread; out << (quint8)info.type; out << info.outgoing; out << info.forwarded; out << info.oob; out << (quint8)info.state; out << info.edited; if (info.state == Shared::Message::State::error) out << info.errorText; if (info.edited) { out << info.originalMessage; out << info.lastModified; } out << info.stanzaId; out << info.attachPath; out << (quint8)info.encryption; return out; } QDataStream & operator>>(QDataStream& in, Shared::Message& info) { in >> info.jFrom; in >> info.rFrom; in >> info.jTo; in >> info.rTo; in >> info.id; in >> info.body; quint64 msecs; in >> msecs; info.time = QDateTime::fromMSecsSinceEpoch(msecs); in >> info.thread; quint8 t; in >> t; info.type = static_cast(t); in >> info.outgoing; in >> info.forwarded; in >> info.oob; quint8 s; in >> s; info.state = static_cast(s); in >> info.edited; if (info.state == Shared::Message::State::error) in >> info.errorText; if (info.edited) { in >> info.originalMessage; in >> info.lastModified; } in >> info.stanzaId; in >> info.attachPath; quint8 e; in >> e; info.encryption = static_cast(e); return in; } bool Shared::Message::change(const QMap& data) { QMap::const_iterator itr = data.find("state"); if (itr != data.end()) setState(static_cast(itr.value().toUInt())); itr = data.find("outOfBandUrl"); if (itr != data.end()) setOutOfBandUrl(itr.value().toString()); itr = data.find("attachPath"); if (itr != data.end()) setAttachPath(itr.value().toString()); if (state == State::error) { itr = data.find("errorText"); if (itr != data.end()) setErrorText(itr.value().toString()); } bool idChanged = false; itr = data.find("id"); if (itr != data.end()) { QString newId = itr.value().toString(); if (id != newId) { setId(newId); idChanged = true; } } itr = data.find("stanzaId"); if (itr != data.end()) { QString newId = itr.value().toString(); if (stanzaId != newId) { setStanzaId(newId); if (id.size() == 0) idChanged = true; } } itr = data.find("body"); if (itr != data.end()) { QString b = itr.value().toString(); if (body != b) { QMap::const_iterator dItr = data.find("stamp"); QDateTime correctionDate; if (dItr != data.end()) correctionDate = dItr.value().toDateTime(); else correctionDate = QDateTime::currentDateTimeUtc(); //in case there is no information about time of this correction it's applied if (!edited || lastModified < correctionDate) { if (!edited) originalMessage = body; lastModified = correctionDate; setBody(b); setEdited(true); } } } else { QMap::const_iterator dItr = data.find("stamp"); if (dItr != data.end()) { QDateTime ntime = dItr.value().toDateTime(); if (time != ntime) setTime(ntime); } } return idChanged; } void Shared::Message::setCurrentTime() { time = QDateTime::currentDateTimeUtc(); } QString Shared::Message::getOutOfBandUrl() const { return oob; } bool Shared::Message::hasOutOfBandUrl() const { return oob.size() > 0; } void Shared::Message::setOutOfBandUrl(const QString& url) { oob = url; } bool Shared::Message::storable() const { return id.size() > 0 && (body.size() > 0 || oob.size() > 0 || attachPath.size() > 0); } void Shared::Message::setStanzaId(const QString& sid) { stanzaId = sid; } QString Shared::Message::getStanzaId() const { return stanzaId; } QString Shared::Message::getAttachPath() const { return attachPath; } void Shared::Message::setAttachPath(const QString& path) { attachPath = path; } Shared::Message::Change::Change(const QMap& _data): data(_data), idModified(false) {} void Shared::Message::Change::operator()(Shared::Message& msg) { idModified = msg.change(data); } void Shared::Message::Change::operator()(Shared::Message* msg) { idModified = msg->change(data); } bool Shared::Message::Change::hasIdBeenModified() const { return idModified; }