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)))
89 if (!deserialize(stream, features, data, type))
92 return checkStreamValid(stream);
95 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QVariant &data, Types::VariantType type)
98 case Types::VariantType::Void: {
101 case Types::VariantType::Bool: {
103 if (!deserialize(stream, features, content))
105 data = QVariant(content);
108 case Types::VariantType::Int: {
110 if (!deserialize(stream, features, content))
112 data = QVariant(content);
115 case Types::VariantType::UInt: {
117 if (!deserialize(stream, features, content))
119 data = QVariant(content);
122 case Types::VariantType::QChar: {
124 if (!deserialize(stream, features, content))
126 data = QVariant(content);
129 case Types::VariantType::QVariantMap: {
131 if (!deserialize(stream, features, content))
133 data = QVariant(content);
136 case Types::VariantType::QVariantList: {
137 QVariantList content;
138 if (!deserialize(stream, features, content))
140 data = QVariant(content);
143 case Types::VariantType::QString: {
145 if (!deserialize(stream, features, content))
147 data = QVariant(content);
150 case Types::VariantType::QStringList: {
152 if (!deserialize(stream, features, content))
154 data = QVariant(content);
157 case Types::VariantType::QByteArray: {
159 if (!deserialize(stream, features, content))
161 data = QVariant(content);
164 case Types::VariantType::QDate: {
166 if (!deserialize(stream, features, content))
168 data = QVariant(content);
171 case Types::VariantType::QTime: {
173 if (!deserialize(stream, features, content))
175 data = QVariant(content);
178 case Types::VariantType::QDateTime: {
180 if (!deserialize(stream, features, content))
182 data = QVariant(content);
185 case Types::VariantType::Long: {
187 if (!deserialize(stream, features, content))
189 data = QVariant(content);
192 case Types::VariantType::Short: {
194 if (!deserialize(stream, features, content))
196 data = QVariant(content);
199 case Types::VariantType::Char: {
201 if (!deserialize(stream, features, content))
203 data = QVariant(content);
206 case Types::VariantType::ULong: {
208 if (!deserialize(stream, features, content))
210 data = QVariant(content);
213 case Types::VariantType::UShort: {
215 if (!deserialize(stream, features, content))
217 data = QVariant(content);
220 case Types::VariantType::UChar: {
222 if (!deserialize(stream, features, content))
224 data = QVariant(content);
227 case Types::VariantType::QVariant: {
229 if (!deserialize(stream, features, content))
231 data = QVariant(content);
235 qWarning() << "Usertype should have been caught earlier already";
241 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QVariant &data, Types::QuasselType type)
244 case Types::QuasselType::BufferId: {
246 if (!deserialize(stream, features, content))
248 data = qVariantFromValue(content);
251 case Types::QuasselType::BufferInfo: {
253 if (!deserialize(stream, features, content))
255 data = qVariantFromValue(content);
258 case Types::QuasselType::Identity: {
260 if (!deserialize(stream, features, content))
262 data = qVariantFromValue(content);
265 case Types::QuasselType::IdentityId: {
267 if (!deserialize(stream, features, content))
269 data = qVariantFromValue(content);
272 case Types::QuasselType::Message: {
274 if (!deserialize(stream, features, content))
276 data = qVariantFromValue(content);
279 case Types::QuasselType::MsgId: {
281 if (!deserialize(stream, features, content))
283 data = qVariantFromValue(content);
286 case Types::QuasselType::NetworkId: {
288 if (!deserialize(stream, features, content))
290 data = qVariantFromValue(content);
293 case Types::QuasselType::NetworkInfo: {
295 if (!deserialize(stream, features, content))
297 data = qVariantFromValue(content);
300 case Types::QuasselType::Network_Server: {
301 Network::Server content;
302 if (!deserialize(stream, features, content))
304 data = qVariantFromValue(content);
307 case Types::QuasselType::PeerPtr: {
309 if (!deserialize(stream, features, content))
311 data = qVariantFromValue(content);
315 qWarning() << "Invalid QType";
321 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, Types::VariantType &data)
324 if (!deserialize(stream, features, raw))
326 data = static_cast<Types::VariantType>(raw);
327 return checkStreamValid(stream);
330 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QStringList &data)
333 if (!deserialize(stream, features, size))
335 for (uint32_t i = 0; i < size; i++) {
337 if (!deserialize(stream, features, element))
341 return checkStreamValid(stream);
344 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, Network::Server &server)
347 QVariantMap serverMap;
348 if (!deserialize(stream, features, serverMap))
350 server.host = serverMap["Host"].toString();
351 server.port = serverMap["Port"].toUInt();
352 server.password = serverMap["Password"].toString();
353 server.useSsl = serverMap["UseSSL"].toBool();
354 server.sslVerify = serverMap["sslVerify"].toBool();
355 server.sslVersion = serverMap["sslVersion"].toInt();
356 server.useProxy = serverMap["UseProxy"].toBool();
357 server.proxyType = serverMap["ProxyType"].toInt();
358 server.proxyHost = serverMap["ProxyHost"].toString();
359 server.proxyPort = serverMap["ProxyPort"].toUInt();
360 server.proxyUser = serverMap["ProxyUser"].toString();
361 server.proxyPass = serverMap["ProxyPass"].toString();
362 return checkStreamValid(stream);
365 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, Identity &data)
369 if (!deserialize(stream, features, raw))
371 data.fromVariantMap(raw);
372 return checkStreamValid(stream);
375 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, NetworkInfo &info)
379 if (!deserialize(stream, features, i))
381 info.networkId = i["NetworkId"].value<NetworkId>();
382 info.networkName = i["NetworkName"].toString();
383 info.identity = i["Identity"].value<IdentityId>();
384 info.codecForServer = i["CodecForServer"].toByteArray();
385 info.codecForEncoding = i["CodecForEncoding"].toByteArray();
386 info.codecForDecoding = i["CodecForDecoding"].toByteArray();
387 info.serverList = fromVariantList<Network::Server>(i["ServerList"].toList());
388 info.useRandomServer = i["UseRandomServer"].toBool();
389 info.perform = i["Perform"].toStringList();
390 info.useAutoIdentify = i["UseAutoIdentify"].toBool();
391 info.autoIdentifyService = i["AutoIdentifyService"].toString();
392 info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
393 info.useSasl = i["UseSasl"].toBool();
394 info.saslAccount = i["SaslAccount"].toString();
395 info.saslPassword = i["SaslPassword"].toString();
396 info.useAutoReconnect = i["UseAutoReconnect"].toBool();
397 info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
398 info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
399 info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool();
400 info.rejoinChannels = i["RejoinChannels"].toBool();
401 // Custom rate limiting
402 info.useCustomMessageRate = i["UseCustomMessageRate"].toBool();
403 info.messageRateBurstSize = i["MessageRateBurstSize"].toUInt();
404 info.messageRateDelay = i["MessageRateDelay"].toUInt();
405 info.unlimitedMessageRate = i["UnlimitedMessageRate"].toBool();
406 return checkStreamValid(stream);
409 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, PeerPtr &data)
413 return checkStreamValid(stream);
416 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QByteArray &data)
421 if (!deserialize(stream, features, length))
423 // -1 - or 0xffffffff - is used for an empty byte array
424 if (length == 0xffffffff) {
428 // 64 MB should be enough
429 if (length > 64 * 1024 * 1024) {
430 qWarning() << "Peer sent too large QByteArray: " << length;
434 const uint32_t Step = 1024 * 1024;
435 uint32_t allocated = 0;
437 int blockSize = std::min(Step, length - allocated);
438 data.resize(allocated + blockSize);
439 if (stream.readRawData(data.data() + allocated, blockSize) != blockSize) {
441 qWarning() << "BufferUnderFlow while reading QByteArray";
444 allocated += blockSize;
445 } while (allocated < length);
446 return checkStreamValid(stream);
449 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QString &data)
453 // read size of string
454 if (!deserialize(stream, features, bytes))
463 if (bytes == 0xffffffff) {
468 // 64 MB should be enough
469 if (bytes > 64 * 1024 * 1024) {
470 qWarning() << "Peer sent too large QString: " << bytes;
476 qWarning() << "Read corrupted data: UTF-6 String with odd length: " << bytes;
479 const uint32_t step = 1024 * 1024;
480 uint32_t length = bytes / 2;
481 uint32_t allocated = 0;
482 while (allocated < length) {
483 int blockSize = std::min(step, length - allocated);
484 data.resize(allocated + blockSize);
485 if (stream.readRawData(reinterpret_cast<char *>(data.data()) + allocated * 2, blockSize * 2) != blockSize * 2) {
487 qWarning() << "BufferUnderFlow while reading QString";
490 allocated += blockSize;
492 if ((stream.byteOrder() == QDataStream::BigEndian) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
493 uint16_t *rawData = reinterpret_cast<uint16_t *>(data.data());
495 *rawData = qbswap(*rawData);
499 return checkStreamValid(stream);
502 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QChar &data)
506 return checkStreamValid(stream);
509 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QDate &data)
513 return checkStreamValid(stream);
516 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QTime &data)
520 return checkStreamValid(stream);
523 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QDateTime &data)
527 return checkStreamValid(stream);
530 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, int32_t &data)
534 return checkStreamValid(stream);
537 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, uint32_t &data)
541 return checkStreamValid(stream);
544 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, int16_t &data)
548 return checkStreamValid(stream);
551 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, uint16_t &data)
555 return checkStreamValid(stream);
558 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, int8_t &data)
562 return checkStreamValid(stream);
565 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, uint8_t &data)
569 return checkStreamValid(stream);
572 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, qlonglong &data)
576 return checkStreamValid(stream);
579 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, qulonglong &data)
583 return checkStreamValid(stream);
586 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, bool &data)
590 return checkStreamValid(stream);
593 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, BufferInfo &data)
597 return checkStreamValid(stream);
600 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, Message &data)
604 return checkStreamValid(stream);
607 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, NetworkId &data)
611 return checkStreamValid(stream);
614 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, IdentityId &data)
618 return checkStreamValid(stream);
621 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, BufferId &data)
625 return checkStreamValid(stream);
628 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, MsgId &data)
632 return checkStreamValid(stream);
635 Serializers::Types::VariantType Serializers::Types::variantType(Serializers::Types::QuasselType type)
638 case QuasselType::BufferId:
639 return VariantType::UserType;
640 case QuasselType::BufferInfo:
641 return VariantType::UserType;
642 case QuasselType::Identity:
643 return VariantType::UserType;
644 case QuasselType::IdentityId:
645 return VariantType::UserType;
646 case QuasselType::Message:
647 return VariantType::UserType;
648 case QuasselType::MsgId:
649 return VariantType::UserType;
650 case QuasselType::NetworkId:
651 return VariantType::UserType;
652 case QuasselType::NetworkInfo:
653 return VariantType::UserType;
654 case QuasselType::Network_Server:
655 return VariantType::UserType;
656 case QuasselType::PeerPtr:
657 return VariantType::Long;
659 return VariantType::UserType;
663 QString Serializers::Types::toName(Serializers::Types::QuasselType type)
666 case QuasselType::BufferId:
667 return QString("BufferId");
668 case QuasselType::BufferInfo:
669 return QString("BufferInfo");
670 case QuasselType::Identity:
671 return QString("Identity");
672 case QuasselType::IdentityId:
673 return QString("IdentityId");
674 case QuasselType::Message:
675 return QString("Message");
676 case QuasselType::MsgId:
677 return QString("MsgId");
678 case QuasselType::NetworkId:
679 return QString("NetworkId");
680 case QuasselType::NetworkInfo:
681 return QString("NetworkInfo");
682 case QuasselType::Network_Server:
683 return QString("Network::Server");
684 case QuasselType::PeerPtr:
685 return QString("PeerPtr");
687 return QString("Invalid Type");
691 Serializers::Types::QuasselType Serializers::Types::fromName(::QByteArray &name)
693 if (qstrcmp(name, "BufferId") == 0) return QuasselType::BufferId;
694 else if (qstrcmp(name, "BufferInfo") == 0) return QuasselType::BufferInfo;
695 else if (qstrcmp(name, "Identity") == 0) return QuasselType::Identity;
696 else if (qstrcmp(name, "IdentityId") == 0) return QuasselType::IdentityId;
697 else if (qstrcmp(name, "Message") == 0) return QuasselType::Message;
698 else if (qstrcmp(name, "MsgId") == 0) return QuasselType::MsgId;
699 else if (qstrcmp(name, "NetworkId") == 0) return QuasselType::NetworkId;
700 else if (qstrcmp(name, "NetworkInfo") == 0) return QuasselType::NetworkInfo;
701 else if (qstrcmp(name, "Network::Server") == 0) return QuasselType::Network_Server;
702 else if (qstrcmp(name, "PeerPtr") == 0) return QuasselType::PeerPtr;
704 qWarning() << "Type name is not valid: " << name;
705 return QuasselType::Invalid;