1 /***************************************************************************
2 * Copyright (C) 2005-2018 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include "serializers.h"
23 bool checkStreamValid(QDataStream& stream)
25 if (stream.status() != QDataStream::Ok) {
26 qWarning() << "Peer sent corrupt data";
33 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantList& data)
36 if (!deserialize(stream, features, size))
38 if (size > 4 * 1024 * 1024) {
39 qWarning() << "Peer sent too large QVariantList: " << size;
42 for (uint32_t i = 0; i < size; i++) {
44 if (!deserialize(stream, features, element))
48 return checkStreamValid(stream);
51 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantMap& data)
54 if (!deserialize(stream, features, size))
56 if (size > 4 * 1024 * 1024) {
57 qWarning() << "Peer sent too large QVariantMap: " << size;
60 for (uint32_t i = 0; i < size; i++) {
63 if (!deserialize(stream, features, key))
65 if (!deserialize(stream, features, value))
69 return checkStreamValid(stream);
72 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data)
74 Types::VariantType type;
76 if (!deserialize(stream, features, type))
78 if (!deserialize(stream, features, isNull))
80 if (type == Types::VariantType::UserType) {
82 if (!deserialize(stream, features, name))
84 while (name.length() > 0 && name.at(name.length() - 1) == 0)
86 if (!deserialize(stream, features, data, Types::fromName(name)))
90 if (!deserialize(stream, features, data, type))
93 return checkStreamValid(stream);
96 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::VariantType type)
99 case Types::VariantType::Void: {
102 case Types::VariantType::Bool: {
104 if (!deserialize(stream, features, content))
106 data = QVariant(content);
109 case Types::VariantType::Int: {
111 if (!deserialize(stream, features, content))
113 data = QVariant(content);
116 case Types::VariantType::UInt: {
118 if (!deserialize(stream, features, content))
120 data = QVariant(content);
123 case Types::VariantType::QChar: {
125 if (!deserialize(stream, features, content))
127 data = QVariant(content);
130 case Types::VariantType::QVariantMap: {
132 if (!deserialize(stream, features, content))
134 data = QVariant(content);
137 case Types::VariantType::QVariantList: {
138 QVariantList content;
139 if (!deserialize(stream, features, content))
141 data = QVariant(content);
144 case Types::VariantType::QString: {
146 if (!deserialize(stream, features, content))
148 data = QVariant(content);
151 case Types::VariantType::QStringList: {
153 if (!deserialize(stream, features, content))
155 data = QVariant(content);
158 case Types::VariantType::QByteArray: {
160 if (!deserialize(stream, features, content))
162 data = QVariant(content);
165 case Types::VariantType::QDate: {
167 if (!deserialize(stream, features, content))
169 data = QVariant(content);
172 case Types::VariantType::QTime: {
174 if (!deserialize(stream, features, content))
176 data = QVariant(content);
179 case Types::VariantType::QDateTime: {
181 if (!deserialize(stream, features, content))
183 data = QVariant(content);
186 case Types::VariantType::Long: {
188 if (!deserialize(stream, features, content))
190 data = QVariant(content);
193 case Types::VariantType::Short: {
195 if (!deserialize(stream, features, content))
197 data = QVariant(content);
200 case Types::VariantType::Char: {
202 if (!deserialize(stream, features, content))
204 data = QVariant(content);
207 case Types::VariantType::ULong: {
209 if (!deserialize(stream, features, content))
211 data = QVariant(content);
214 case Types::VariantType::UShort: {
216 if (!deserialize(stream, features, content))
218 data = QVariant(content);
221 case Types::VariantType::UChar: {
223 if (!deserialize(stream, features, content))
225 data = QVariant(content);
228 case Types::VariantType::QVariant: {
230 if (!deserialize(stream, features, content))
232 data = QVariant(content);
236 qWarning() << "Usertype should have been caught earlier already";
242 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::QuasselType type)
245 case Types::QuasselType::BufferId: {
247 if (!deserialize(stream, features, content))
249 data = qVariantFromValue(content);
252 case Types::QuasselType::BufferInfo: {
254 if (!deserialize(stream, features, content))
256 data = qVariantFromValue(content);
259 case Types::QuasselType::Identity: {
261 if (!deserialize(stream, features, content))
263 data = qVariantFromValue(content);
266 case Types::QuasselType::IdentityId: {
268 if (!deserialize(stream, features, content))
270 data = qVariantFromValue(content);
273 case Types::QuasselType::Message: {
275 if (!deserialize(stream, features, content))
277 data = qVariantFromValue(content);
280 case Types::QuasselType::MsgId: {
282 if (!deserialize(stream, features, content))
284 data = qVariantFromValue(content);
287 case Types::QuasselType::NetworkId: {
289 if (!deserialize(stream, features, content))
291 data = qVariantFromValue(content);
294 case Types::QuasselType::NetworkInfo: {
296 if (!deserialize(stream, features, content))
298 data = qVariantFromValue(content);
301 case Types::QuasselType::Network_Server: {
302 Network::Server content;
303 if (!deserialize(stream, features, content))
305 data = qVariantFromValue(content);
308 case Types::QuasselType::PeerPtr: {
310 if (!deserialize(stream, features, content))
312 data = qVariantFromValue(content);
316 qWarning() << "Invalid QType";
322 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Types::VariantType& data)
325 if (!deserialize(stream, features, raw))
327 data = static_cast<Types::VariantType>(raw);
328 return checkStreamValid(stream);
331 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QStringList& data)
334 if (!deserialize(stream, features, size))
336 for (uint32_t i = 0; i < size; i++) {
338 if (!deserialize(stream, features, element))
342 return checkStreamValid(stream);
345 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Network::Server& server)
348 QVariantMap serverMap;
349 if (!deserialize(stream, features, serverMap))
351 server.host = serverMap["Host"].toString();
352 server.port = serverMap["Port"].toUInt();
353 server.password = serverMap["Password"].toString();
354 server.useSsl = serverMap["UseSSL"].toBool();
355 server.sslVerify = serverMap["sslVerify"].toBool();
356 server.sslVersion = serverMap["sslVersion"].toInt();
357 server.useProxy = serverMap["UseProxy"].toBool();
358 server.proxyType = serverMap["ProxyType"].toInt();
359 server.proxyHost = serverMap["ProxyHost"].toString();
360 server.proxyPort = serverMap["ProxyPort"].toUInt();
361 server.proxyUser = serverMap["ProxyUser"].toString();
362 server.proxyPass = serverMap["ProxyPass"].toString();
363 return checkStreamValid(stream);
366 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Identity& data)
370 if (!deserialize(stream, features, raw))
372 data.fromVariantMap(raw);
373 return checkStreamValid(stream);
376 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkInfo& info)
380 if (!deserialize(stream, features, i))
382 info.networkId = i["NetworkId"].value<NetworkId>();
383 info.networkName = i["NetworkName"].toString();
384 info.identity = i["Identity"].value<IdentityId>();
385 info.codecForServer = i["CodecForServer"].toByteArray();
386 info.codecForEncoding = i["CodecForEncoding"].toByteArray();
387 info.codecForDecoding = i["CodecForDecoding"].toByteArray();
388 info.serverList = fromVariantList<Network::Server>(i["ServerList"].toList());
389 info.useRandomServer = i["UseRandomServer"].toBool();
390 info.perform = i["Perform"].toStringList();
391 info.useAutoIdentify = i["UseAutoIdentify"].toBool();
392 info.autoIdentifyService = i["AutoIdentifyService"].toString();
393 info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
394 info.useSasl = i["UseSasl"].toBool();
395 info.saslAccount = i["SaslAccount"].toString();
396 info.saslPassword = i["SaslPassword"].toString();
397 info.useAutoReconnect = i["UseAutoReconnect"].toBool();
398 info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
399 info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
400 info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool();
401 info.rejoinChannels = i["RejoinChannels"].toBool();
402 // Custom rate limiting
403 info.useCustomMessageRate = i["UseCustomMessageRate"].toBool();
404 info.messageRateBurstSize = i["MessageRateBurstSize"].toUInt();
405 info.messageRateDelay = i["MessageRateDelay"].toUInt();
406 info.unlimitedMessageRate = i["UnlimitedMessageRate"].toBool();
407 return checkStreamValid(stream);
410 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, PeerPtr& data)
414 return checkStreamValid(stream);
417 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QByteArray& data)
422 if (!deserialize(stream, features, length))
424 // -1 - or 0xffffffff - is used for an empty byte array
425 if (length == 0xffffffff) {
429 // 64 MB should be enough
430 if (length > 64 * 1024 * 1024) {
431 qWarning() << "Peer sent too large QByteArray: " << length;
435 const uint32_t Step = 1024 * 1024;
436 uint32_t allocated = 0;
438 int blockSize = std::min(Step, length - allocated);
439 data.resize(allocated + blockSize);
440 if (stream.readRawData(data.data() + allocated, blockSize) != blockSize) {
442 qWarning() << "BufferUnderFlow while reading QByteArray";
445 allocated += blockSize;
446 } while (allocated < length);
447 return checkStreamValid(stream);
450 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QString& data)
454 // read size of string
455 if (!deserialize(stream, features, bytes))
464 if (bytes == 0xffffffff) {
469 // 64 MB should be enough
470 if (bytes > 64 * 1024 * 1024) {
471 qWarning() << "Peer sent too large QString: " << bytes;
477 qWarning() << "Read corrupted data: UTF-6 String with odd length: " << bytes;
480 const uint32_t step = 1024 * 1024;
481 uint32_t length = bytes / 2;
482 uint32_t allocated = 0;
483 while (allocated < length) {
484 int blockSize = std::min(step, length - allocated);
485 data.resize(allocated + blockSize);
486 if (stream.readRawData(reinterpret_cast<char*>(data.data()) + allocated * 2, blockSize * 2) != blockSize * 2) {
488 qWarning() << "BufferUnderFlow while reading QString";
491 allocated += blockSize;
493 if ((stream.byteOrder() == QDataStream::BigEndian) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
494 auto* rawData = reinterpret_cast<uint16_t*>(data.data());
496 *rawData = qbswap(*rawData);
500 return checkStreamValid(stream);
503 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QChar& data)
507 return checkStreamValid(stream);
510 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDate& data)
514 return checkStreamValid(stream);
517 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QTime& data)
521 return checkStreamValid(stream);
524 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDateTime& data)
528 return checkStreamValid(stream);
531 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int32_t& data)
535 return checkStreamValid(stream);
538 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint32_t& data)
542 return checkStreamValid(stream);
545 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int16_t& data)
549 return checkStreamValid(stream);
552 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint16_t& data)
556 return checkStreamValid(stream);
559 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int8_t& data)
563 return checkStreamValid(stream);
566 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint8_t& data)
570 return checkStreamValid(stream);
573 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qlonglong& data)
577 return checkStreamValid(stream);
580 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qulonglong& data)
584 return checkStreamValid(stream);
587 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, bool& data)
591 return checkStreamValid(stream);
594 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferInfo& data)
598 return checkStreamValid(stream);
601 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Message& data)
605 return checkStreamValid(stream);
608 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkId& data)
612 return checkStreamValid(stream);
615 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, IdentityId& data)
619 return checkStreamValid(stream);
622 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferId& data)
626 return checkStreamValid(stream);
629 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, MsgId& data)
633 return checkStreamValid(stream);
636 Serializers::Types::VariantType Serializers::Types::variantType(Serializers::Types::QuasselType type)
639 case QuasselType::BufferId:
640 return VariantType::UserType;
641 case QuasselType::BufferInfo:
642 return VariantType::UserType;
643 case QuasselType::Identity:
644 return VariantType::UserType;
645 case QuasselType::IdentityId:
646 return VariantType::UserType;
647 case QuasselType::Message:
648 return VariantType::UserType;
649 case QuasselType::MsgId:
650 return VariantType::UserType;
651 case QuasselType::NetworkId:
652 return VariantType::UserType;
653 case QuasselType::NetworkInfo:
654 return VariantType::UserType;
655 case QuasselType::Network_Server:
656 return VariantType::UserType;
657 case QuasselType::PeerPtr:
658 return VariantType::Long;
660 return VariantType::UserType;
664 QString Serializers::Types::toName(Serializers::Types::QuasselType type)
667 case QuasselType::BufferId:
668 return QString("BufferId");
669 case QuasselType::BufferInfo:
670 return QString("BufferInfo");
671 case QuasselType::Identity:
672 return QString("Identity");
673 case QuasselType::IdentityId:
674 return QString("IdentityId");
675 case QuasselType::Message:
676 return QString("Message");
677 case QuasselType::MsgId:
678 return QString("MsgId");
679 case QuasselType::NetworkId:
680 return QString("NetworkId");
681 case QuasselType::NetworkInfo:
682 return QString("NetworkInfo");
683 case QuasselType::Network_Server:
684 return QString("Network::Server");
685 case QuasselType::PeerPtr:
686 return QString("PeerPtr");
688 return QString("Invalid Type");
692 Serializers::Types::QuasselType Serializers::Types::fromName(::QByteArray& name)
694 if (qstrcmp(name, "BufferId") == 0)
695 return QuasselType::BufferId;
696 else if (qstrcmp(name, "BufferInfo") == 0)
697 return QuasselType::BufferInfo;
698 else if (qstrcmp(name, "Identity") == 0)
699 return QuasselType::Identity;
700 else if (qstrcmp(name, "IdentityId") == 0)
701 return QuasselType::IdentityId;
702 else if (qstrcmp(name, "Message") == 0)
703 return QuasselType::Message;
704 else if (qstrcmp(name, "MsgId") == 0)
705 return QuasselType::MsgId;
706 else if (qstrcmp(name, "NetworkId") == 0)
707 return QuasselType::NetworkId;
708 else if (qstrcmp(name, "NetworkInfo") == 0)
709 return QuasselType::NetworkInfo;
710 else if (qstrcmp(name, "Network::Server") == 0)
711 return QuasselType::Network_Server;
712 else if (qstrcmp(name, "PeerPtr") == 0)
713 return QuasselType::PeerPtr;
715 qWarning() << "Type name is not valid: " << name;
716 return QuasselType::Invalid;