1 /***************************************************************************
2 * Copyright (C) 2005-2019 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"
26 bool toVariant(QDataStream& stream, Quassel::Features features, QVariant& data)
29 if (!Serializers::deserialize(stream, features, content)) {
32 data = QVariant::fromValue<T>(content);
38 bool checkStreamValid(QDataStream& stream)
40 if (stream.status() != QDataStream::Ok) {
41 qWarning() << "Peer sent corrupt data";
48 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantList& data)
51 if (!deserialize(stream, features, size))
53 if (size > 4 * 1024 * 1024) {
54 qWarning() << "Peer sent too large QVariantList: " << size;
57 for (uint32_t i = 0; i < size; i++) {
59 if (!deserialize(stream, features, element))
63 return checkStreamValid(stream);
66 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantMap& data)
69 if (!deserialize(stream, features, size))
71 if (size > 4 * 1024 * 1024) {
72 qWarning() << "Peer sent too large QVariantMap: " << size;
75 for (uint32_t i = 0; i < size; i++) {
78 if (!deserialize(stream, features, key))
80 if (!deserialize(stream, features, value))
84 return checkStreamValid(stream);
87 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data)
89 Types::VariantType type;
91 if (!deserialize(stream, features, type))
93 if (!deserialize(stream, features, isNull))
95 if (type == Types::VariantType::UserType) {
97 if (!deserialize(stream, features, name))
99 while (name.length() > 0 && name.at(name.length() - 1) == 0)
101 if (!deserialize(stream, features, data, Types::fromName(name)))
105 if (!deserialize(stream, features, data, type))
108 return checkStreamValid(stream);
111 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::VariantType type)
114 case Types::VariantType::Void:
116 case Types::VariantType::Bool:
117 return toVariant<bool>(stream, features, data);
118 case Types::VariantType::Int:
119 return toVariant<int32_t>(stream, features, data);
120 case Types::VariantType::UInt:
121 return toVariant<uint32_t>(stream, features, data);
122 case Types::VariantType::QChar:
123 return toVariant<QChar>(stream, features, data);
124 case Types::VariantType::QVariantMap:
125 return toVariant<QVariantMap>(stream, features, data);
126 case Types::VariantType::QVariantList:
127 return toVariant<QVariantList>(stream, features, data);
128 case Types::VariantType::QString:
129 return toVariant<QString>(stream, features, data);
130 case Types::VariantType::QStringList:
131 return toVariant<QStringList>(stream, features, data);
132 case Types::VariantType::QByteArray:
133 return toVariant<QByteArray>(stream, features, data);
134 case Types::VariantType::QDate:
135 return toVariant<QDate>(stream, features, data);
136 case Types::VariantType::QTime:
137 return toVariant<QTime>(stream, features, data);
138 case Types::VariantType::QDateTime:
139 return toVariant<QDateTime>(stream, features, data);
140 case Types::VariantType::Long:
141 return toVariant<qlonglong>(stream, features, data);
142 case Types::VariantType::Short:
143 return toVariant<int16_t>(stream, features, data);
144 case Types::VariantType::Char:
145 return toVariant<int8_t>(stream, features, data);
146 case Types::VariantType::ULong:
147 return toVariant<qulonglong>(stream, features, data);
148 case Types::VariantType::UShort:
149 return toVariant<uint16_t>(stream, features, data);
150 case Types::VariantType::UChar:
151 return toVariant<uint8_t>(stream, features, data);
152 case Types::VariantType::QVariant:
153 return toVariant<QVariant>(stream, features, data);
155 qWarning() << "Usertype should have been caught earlier already";
160 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::QuasselType type)
163 case Types::QuasselType::BufferId:
164 return toVariant<BufferId>(stream, features, data);
165 case Types::QuasselType::BufferInfo:
166 return toVariant<BufferInfo>(stream, features, data);
167 case Types::QuasselType::Identity:
168 return toVariant<Identity>(stream, features, data);
169 case Types::QuasselType::IdentityId:
170 return toVariant<IdentityId>(stream, features, data);
171 case Types::QuasselType::Message:
172 return toVariant<Message>(stream, features, data);
173 case Types::QuasselType::MsgId:
174 return toVariant<MsgId>(stream, features, data);
175 case Types::QuasselType::NetworkId:
176 return toVariant<NetworkId>(stream, features, data);
177 case Types::QuasselType::NetworkInfo:
178 return toVariant<NetworkInfo>(stream, features, data);
179 case Types::QuasselType::Network_Server:
180 return toVariant<Network::Server>(stream, features, data);
181 case Types::QuasselType::PeerPtr:
182 return toVariant<PeerPtr>(stream, features, data);
184 qWarning() << "Invalid QType";
189 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Types::VariantType& data)
192 if (!deserialize(stream, features, raw))
194 data = static_cast<Types::VariantType>(raw);
195 return checkStreamValid(stream);
198 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QStringList& data)
201 if (!deserialize(stream, features, size))
203 for (uint32_t i = 0; i < size; i++) {
205 if (!deserialize(stream, features, element))
209 return checkStreamValid(stream);
212 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Network::Server& server)
215 QVariantMap serverMap;
216 if (!deserialize(stream, features, serverMap))
218 server.host = serverMap["Host"].toString();
219 server.port = serverMap["Port"].toUInt();
220 server.password = serverMap["Password"].toString();
221 server.useSsl = serverMap["UseSSL"].toBool();
222 server.sslVerify = serverMap["sslVerify"].toBool();
223 server.sslVersion = serverMap["sslVersion"].toInt();
224 server.useProxy = serverMap["UseProxy"].toBool();
225 server.proxyType = serverMap["ProxyType"].toInt();
226 server.proxyHost = serverMap["ProxyHost"].toString();
227 server.proxyPort = serverMap["ProxyPort"].toUInt();
228 server.proxyUser = serverMap["ProxyUser"].toString();
229 server.proxyPass = serverMap["ProxyPass"].toString();
230 return checkStreamValid(stream);
233 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Identity& data)
237 if (!deserialize(stream, features, raw))
239 data.fromVariantMap(raw);
240 return checkStreamValid(stream);
243 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkInfo& info)
247 if (!deserialize(stream, features, i))
249 info.networkId = i["NetworkId"].value<NetworkId>();
250 info.networkName = i["NetworkName"].toString();
251 info.identity = i["Identity"].value<IdentityId>();
252 info.codecForServer = i["CodecForServer"].toByteArray();
253 info.codecForEncoding = i["CodecForEncoding"].toByteArray();
254 info.codecForDecoding = i["CodecForDecoding"].toByteArray();
255 info.serverList = fromVariantList<Network::Server>(i["ServerList"].toList());
256 info.useRandomServer = i["UseRandomServer"].toBool();
257 info.perform = i["Perform"].toStringList();
258 info.useAutoIdentify = i["UseAutoIdentify"].toBool();
259 info.autoIdentifyService = i["AutoIdentifyService"].toString();
260 info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
261 info.useSasl = i["UseSasl"].toBool();
262 info.saslAccount = i["SaslAccount"].toString();
263 info.saslPassword = i["SaslPassword"].toString();
264 info.useAutoReconnect = i["UseAutoReconnect"].toBool();
265 info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
266 info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
267 info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool();
268 info.rejoinChannels = i["RejoinChannels"].toBool();
269 // Custom rate limiting
270 info.useCustomMessageRate = i["UseCustomMessageRate"].toBool();
271 info.messageRateBurstSize = i["MessageRateBurstSize"].toUInt();
272 info.messageRateDelay = i["MessageRateDelay"].toUInt();
273 info.unlimitedMessageRate = i["UnlimitedMessageRate"].toBool();
274 return checkStreamValid(stream);
277 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, PeerPtr& data)
281 return checkStreamValid(stream);
284 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QByteArray& data)
289 if (!deserialize(stream, features, length))
291 // -1 - or 0xffffffff - is used for an empty byte array
292 if (length == 0xffffffff) {
296 // 64 MB should be enough
297 if (length > 64 * 1024 * 1024) {
298 qWarning() << "Peer sent too large QByteArray: " << length;
302 const uint32_t Step = 1024 * 1024;
303 uint32_t allocated = 0;
305 int blockSize = std::min(Step, length - allocated);
306 data.resize(allocated + blockSize);
307 if (stream.readRawData(data.data() + allocated, blockSize) != blockSize) {
309 qWarning() << "BufferUnderFlow while reading QByteArray";
312 allocated += blockSize;
313 } while (allocated < length);
314 return checkStreamValid(stream);
317 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QString& data)
321 // read size of string
322 if (!deserialize(stream, features, bytes))
331 if (bytes == 0xffffffff) {
336 // 64 MB should be enough
337 if (bytes > 64 * 1024 * 1024) {
338 qWarning() << "Peer sent too large QString: " << bytes;
344 qWarning() << "Read corrupted data: UTF-6 String with odd length: " << bytes;
347 const uint32_t step = 1024 * 1024;
348 uint32_t length = bytes / 2;
349 uint32_t allocated = 0;
350 while (allocated < length) {
351 int blockSize = std::min(step, length - allocated);
352 data.resize(allocated + blockSize);
353 if (stream.readRawData(reinterpret_cast<char*>(data.data()) + allocated * 2, blockSize * 2) != blockSize * 2) {
355 qWarning() << "BufferUnderFlow while reading QString";
358 allocated += blockSize;
360 if ((stream.byteOrder() == QDataStream::BigEndian) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
361 auto* rawData = reinterpret_cast<uint16_t*>(data.data());
363 *rawData = qbswap(*rawData);
367 return checkStreamValid(stream);
370 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QChar& data)
374 return checkStreamValid(stream);
377 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDate& data)
381 return checkStreamValid(stream);
384 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QTime& data)
388 return checkStreamValid(stream);
391 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDateTime& data)
395 return checkStreamValid(stream);
398 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int32_t& data)
402 return checkStreamValid(stream);
405 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint32_t& data)
409 return checkStreamValid(stream);
412 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int16_t& data)
416 return checkStreamValid(stream);
419 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint16_t& data)
423 return checkStreamValid(stream);
426 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int8_t& data)
430 return checkStreamValid(stream);
433 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint8_t& data)
437 return checkStreamValid(stream);
440 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qlonglong& data)
444 return checkStreamValid(stream);
447 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qulonglong& data)
451 return checkStreamValid(stream);
454 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, bool& data)
458 return checkStreamValid(stream);
461 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferInfo& data)
465 return checkStreamValid(stream);
468 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Message& data)
472 return checkStreamValid(stream);
475 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkId& data)
479 return checkStreamValid(stream);
482 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, IdentityId& data)
486 return checkStreamValid(stream);
489 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferId& data)
493 return checkStreamValid(stream);
496 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, MsgId& data)
500 return checkStreamValid(stream);
503 Serializers::Types::VariantType Serializers::Types::variantType(Serializers::Types::QuasselType type)
506 case QuasselType::BufferId:
507 return VariantType::UserType;
508 case QuasselType::BufferInfo:
509 return VariantType::UserType;
510 case QuasselType::Identity:
511 return VariantType::UserType;
512 case QuasselType::IdentityId:
513 return VariantType::UserType;
514 case QuasselType::Message:
515 return VariantType::UserType;
516 case QuasselType::MsgId:
517 return VariantType::UserType;
518 case QuasselType::NetworkId:
519 return VariantType::UserType;
520 case QuasselType::NetworkInfo:
521 return VariantType::UserType;
522 case QuasselType::Network_Server:
523 return VariantType::UserType;
524 case QuasselType::PeerPtr:
525 return VariantType::Long;
527 return VariantType::UserType;
531 QString Serializers::Types::toName(Serializers::Types::QuasselType type)
534 case QuasselType::BufferId:
535 return QString("BufferId");
536 case QuasselType::BufferInfo:
537 return QString("BufferInfo");
538 case QuasselType::Identity:
539 return QString("Identity");
540 case QuasselType::IdentityId:
541 return QString("IdentityId");
542 case QuasselType::Message:
543 return QString("Message");
544 case QuasselType::MsgId:
545 return QString("MsgId");
546 case QuasselType::NetworkId:
547 return QString("NetworkId");
548 case QuasselType::NetworkInfo:
549 return QString("NetworkInfo");
550 case QuasselType::Network_Server:
551 return QString("Network::Server");
552 case QuasselType::PeerPtr:
553 return QString("PeerPtr");
555 return QString("Invalid Type");
559 Serializers::Types::QuasselType Serializers::Types::fromName(::QByteArray& name)
561 if (qstrcmp(name, "BufferId") == 0)
562 return QuasselType::BufferId;
563 else if (qstrcmp(name, "BufferInfo") == 0)
564 return QuasselType::BufferInfo;
565 else if (qstrcmp(name, "Identity") == 0)
566 return QuasselType::Identity;
567 else if (qstrcmp(name, "IdentityId") == 0)
568 return QuasselType::IdentityId;
569 else if (qstrcmp(name, "Message") == 0)
570 return QuasselType::Message;
571 else if (qstrcmp(name, "MsgId") == 0)
572 return QuasselType::MsgId;
573 else if (qstrcmp(name, "NetworkId") == 0)
574 return QuasselType::NetworkId;
575 else if (qstrcmp(name, "NetworkInfo") == 0)
576 return QuasselType::NetworkInfo;
577 else if (qstrcmp(name, "Network::Server") == 0)
578 return QuasselType::Network_Server;
579 else if (qstrcmp(name, "PeerPtr") == 0)
580 return QuasselType::PeerPtr;
582 qWarning() << "Type name is not valid: " << name;
583 return QuasselType::Invalid;