cmake: avoid de-duplication of user's CXXFLAGS
[quassel.git] / src / common / serializers / serializers.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2022 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
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.                                           *
9  *                                                                         *
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.                          *
14  *                                                                         *
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  ***************************************************************************/
20
21 #include "serializers.h"
22
23 namespace {
24
25 template<typename T>
26 bool toVariant(QDataStream& stream, Quassel::Features features, QVariant& data)
27 {
28     T content;
29     if (!Serializers::deserialize(stream, features, content)) {
30         return false;
31     }
32     data = QVariant::fromValue(content);
33     return true;
34 }
35
36 }  // anon
37
38 bool checkStreamValid(QDataStream& stream)
39 {
40     if (stream.status() != QDataStream::Ok) {
41         qWarning() << "Peer sent corrupt data";
42         return false;
43     }
44
45     return true;
46 }
47
48 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantList& data)
49 {
50     uint32_t size;
51     if (!deserialize(stream, features, size))
52         return false;
53     if (size > 4 * 1024 * 1024) {
54         qWarning() << "Peer sent too large QVariantList: " << size;
55         return false;
56     }
57     for (uint32_t i = 0; i < size; i++) {
58         QVariant element;
59         if (!deserialize(stream, features, element))
60             return false;
61         data << element;
62     }
63     return checkStreamValid(stream);
64 }
65
66 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantMap& data)
67 {
68     uint32_t size;
69     if (!deserialize(stream, features, size))
70         return false;
71     if (size > 4 * 1024 * 1024) {
72         qWarning() << "Peer sent too large QVariantMap: " << size;
73         return false;
74     }
75     for (uint32_t i = 0; i < size; i++) {
76         QString key;
77         QVariant value;
78         if (!deserialize(stream, features, key))
79             return false;
80         if (!deserialize(stream, features, value))
81             return false;
82         data[key] = value;
83     }
84     return checkStreamValid(stream);
85 }
86
87 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data)
88 {
89     Types::VariantType type;
90     int8_t isNull;
91     if (!deserialize(stream, features, type))
92         return false;
93     if (!deserialize(stream, features, isNull))
94         return false;
95     if (type == Types::VariantType::UserType) {
96         QByteArray name;
97         if (!deserialize(stream, features, name))
98             return false;
99         while (name.length() > 0 && name.at(name.length() - 1) == 0)
100             name.chop(1);
101         if (!deserialize(stream, features, data, Types::fromName(name)))
102             return false;
103     }
104     else {
105         if (!deserialize(stream, features, data, type))
106             return false;
107     }
108     return checkStreamValid(stream);
109 }
110
111 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::VariantType type)
112 {
113     switch (type) {
114     case Types::VariantType::Void:
115         return true;
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);
154     default:
155         qWarning() << "Usertype should have been caught earlier already";
156         return false;
157     }
158 }
159
160 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::QuasselType type)
161 {
162     switch (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);
183     default:
184         qWarning() << "Invalid QType";
185         return false;
186     }
187 }
188
189 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Types::VariantType& data)
190 {
191     uint32_t raw;
192     if (!deserialize(stream, features, raw))
193         return false;
194     data = static_cast<Types::VariantType>(raw);
195     return checkStreamValid(stream);
196 }
197
198 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QStringList& data)
199 {
200     uint32_t size;
201     if (!deserialize(stream, features, size))
202         return false;
203     for (uint32_t i = 0; i < size; i++) {
204         QString element;
205         if (!deserialize(stream, features, element))
206             return false;
207         data << element;
208     }
209     return checkStreamValid(stream);
210 }
211
212 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Network::Server& server)
213 {
214     Q_UNUSED(features);
215     QVariantMap serverMap;
216     if (!deserialize(stream, features, serverMap))
217         return false;
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);
231 }
232
233 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Identity& data)
234 {
235     Q_UNUSED(features);
236     QVariantMap raw;
237     if (!deserialize(stream, features, raw))
238         return false;
239     data.fromVariantMap(raw);
240     return checkStreamValid(stream);
241 }
242
243 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkInfo& info)
244 {
245     Q_UNUSED(features);
246     QVariantMap i;
247     if (!deserialize(stream, features, i))
248         return false;
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.skipCaps = i["SkipCaps"].toStringList();
259     info.useAutoIdentify = i["UseAutoIdentify"].toBool();
260     info.autoIdentifyService = i["AutoIdentifyService"].toString();
261     info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
262     info.useSasl = i["UseSasl"].toBool();
263     info.saslAccount = i["SaslAccount"].toString();
264     info.saslPassword = i["SaslPassword"].toString();
265     info.useAutoReconnect = i["UseAutoReconnect"].toBool();
266     info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
267     info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
268     info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool();
269     info.rejoinChannels = i["RejoinChannels"].toBool();
270     // Custom rate limiting
271     info.useCustomMessageRate = i["UseCustomMessageRate"].toBool();
272     info.messageRateBurstSize = i["MessageRateBurstSize"].toUInt();
273     info.messageRateDelay = i["MessageRateDelay"].toUInt();
274     info.unlimitedMessageRate = i["UnlimitedMessageRate"].toBool();
275     return checkStreamValid(stream);
276 }
277
278 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, PeerPtr& data)
279 {
280     Q_UNUSED(features);
281     stream >> data;
282     return checkStreamValid(stream);
283 }
284
285 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QByteArray& data)
286 {
287     Q_UNUSED(features);
288     data.clear();
289     uint32_t length;
290     if (!deserialize(stream, features, length))
291         return false;
292     // -1 - or 0xffffffff - is used for an empty byte array
293     if (length == 0xffffffff) {
294         return true;
295     }
296
297     // 64 MB should be enough
298     if (length > 64 * 1024 * 1024) {
299         qWarning() << "Peer sent too large QByteArray: " << length;
300         return false;
301     }
302
303     const uint32_t Step = 1024 * 1024;
304     uint32_t allocated = 0;
305     do {
306         int blockSize = std::min(Step, length - allocated);
307         data.resize(allocated + blockSize);
308         if (stream.readRawData(data.data() + allocated, blockSize) != blockSize) {
309             data.clear();
310             qWarning() << "BufferUnderFlow while reading QByteArray";
311             return false;
312         }
313         allocated += blockSize;
314     } while (allocated < length);
315     return checkStreamValid(stream);
316 }
317
318 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QString& data)
319 {
320     Q_UNUSED(features);
321     uint32_t bytes = 0;
322     // read size of string
323     if (!deserialize(stream, features, bytes))
324         return false;
325
326     // empty string
327     if (bytes == 0) {
328         return true;
329     }
330
331     // null string
332     if (bytes == 0xffffffff) {
333         data.clear();
334         return true;
335     }
336
337     // 64 MB should be enough
338     if (bytes > 64 * 1024 * 1024) {
339         qWarning() << "Peer sent too large QString: " << bytes;
340         return false;
341     }
342
343     if (bytes & 0x1) {
344         data.clear();
345         qWarning() << "Read corrupted data: UTF-6 String with odd length: " << bytes;
346         return false;
347     }
348     const uint32_t step = 1024 * 1024;
349     uint32_t length = bytes / 2;
350     uint32_t allocated = 0;
351     while (allocated < length) {
352         int blockSize = std::min(step, length - allocated);
353         data.resize(allocated + blockSize);
354         if (stream.readRawData(reinterpret_cast<char*>(data.data()) + allocated * 2, blockSize * 2) != blockSize * 2) {
355             data.clear();
356             qWarning() << "BufferUnderFlow while reading QString";
357             return false;
358         }
359         allocated += blockSize;
360     }
361     if ((stream.byteOrder() == QDataStream::BigEndian) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
362         auto* rawData = reinterpret_cast<uint16_t*>(data.data());
363         while (length--) {
364             *rawData = qbswap(*rawData);
365             ++rawData;
366         }
367     }
368     return checkStreamValid(stream);
369 }
370
371 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QChar& data)
372 {
373     Q_UNUSED(features);
374     stream >> data;
375     return checkStreamValid(stream);
376 }
377
378 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDate& data)
379 {
380     Q_UNUSED(features);
381     stream >> data;
382     return checkStreamValid(stream);
383 }
384
385 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QTime& data)
386 {
387     Q_UNUSED(features);
388     stream >> data;
389     return checkStreamValid(stream);
390 }
391
392 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDateTime& data)
393 {
394     Q_UNUSED(features);
395     stream >> data;
396     return checkStreamValid(stream);
397 }
398
399 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int32_t& data)
400 {
401     Q_UNUSED(features);
402     stream >> data;
403     return checkStreamValid(stream);
404 }
405
406 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint32_t& data)
407 {
408     Q_UNUSED(features);
409     stream >> data;
410     return checkStreamValid(stream);
411 }
412
413 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int16_t& data)
414 {
415     Q_UNUSED(features);
416     stream >> data;
417     return checkStreamValid(stream);
418 }
419
420 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint16_t& data)
421 {
422     Q_UNUSED(features);
423     stream >> data;
424     return checkStreamValid(stream);
425 }
426
427 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int8_t& data)
428 {
429     Q_UNUSED(features);
430     stream >> data;
431     return checkStreamValid(stream);
432 }
433
434 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint8_t& data)
435 {
436     Q_UNUSED(features);
437     stream >> data;
438     return checkStreamValid(stream);
439 }
440
441 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qlonglong& data)
442 {
443     Q_UNUSED(features);
444     stream >> data;
445     return checkStreamValid(stream);
446 }
447
448 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qulonglong& data)
449 {
450     Q_UNUSED(features);
451     stream >> data;
452     return checkStreamValid(stream);
453 }
454
455 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, bool& data)
456 {
457     Q_UNUSED(features);
458     stream >> data;
459     return checkStreamValid(stream);
460 }
461
462 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferInfo& data)
463 {
464     Q_UNUSED(features);
465     stream >> data;
466     return checkStreamValid(stream);
467 }
468
469 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Message& data)
470 {
471     Q_UNUSED(features);
472     stream >> data;
473     return checkStreamValid(stream);
474 }
475
476 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkId& data)
477 {
478     Q_UNUSED(features);
479     stream >> data;
480     return checkStreamValid(stream);
481 }
482
483 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, IdentityId& data)
484 {
485     Q_UNUSED(features);
486     stream >> data;
487     return checkStreamValid(stream);
488 }
489
490 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferId& data)
491 {
492     Q_UNUSED(features);
493     stream >> data;
494     return checkStreamValid(stream);
495 }
496
497 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, MsgId& data)
498 {
499     Q_UNUSED(features);
500     stream >> data;
501     return checkStreamValid(stream);
502 }
503
504 Serializers::Types::VariantType Serializers::Types::variantType(Serializers::Types::QuasselType type)
505 {
506     switch (type) {
507     case QuasselType::BufferId:
508         return VariantType::UserType;
509     case QuasselType::BufferInfo:
510         return VariantType::UserType;
511     case QuasselType::Identity:
512         return VariantType::UserType;
513     case QuasselType::IdentityId:
514         return VariantType::UserType;
515     case QuasselType::Message:
516         return VariantType::UserType;
517     case QuasselType::MsgId:
518         return VariantType::UserType;
519     case QuasselType::NetworkId:
520         return VariantType::UserType;
521     case QuasselType::NetworkInfo:
522         return VariantType::UserType;
523     case QuasselType::Network_Server:
524         return VariantType::UserType;
525     case QuasselType::PeerPtr:
526         return VariantType::Long;
527     default:
528         return VariantType::UserType;
529     }
530 }
531
532 QString Serializers::Types::toName(Serializers::Types::QuasselType type)
533 {
534     switch (type) {
535     case QuasselType::BufferId:
536         return QString("BufferId");
537     case QuasselType::BufferInfo:
538         return QString("BufferInfo");
539     case QuasselType::Identity:
540         return QString("Identity");
541     case QuasselType::IdentityId:
542         return QString("IdentityId");
543     case QuasselType::Message:
544         return QString("Message");
545     case QuasselType::MsgId:
546         return QString("MsgId");
547     case QuasselType::NetworkId:
548         return QString("NetworkId");
549     case QuasselType::NetworkInfo:
550         return QString("NetworkInfo");
551     case QuasselType::Network_Server:
552         return QString("Network::Server");
553     case QuasselType::PeerPtr:
554         return QString("PeerPtr");
555     default:
556         return QString("Invalid Type");
557     }
558 }
559
560 Serializers::Types::QuasselType Serializers::Types::fromName(::QByteArray& name)
561 {
562     if (qstrcmp(name, "BufferId") == 0)
563         return QuasselType::BufferId;
564     else if (qstrcmp(name, "BufferInfo") == 0)
565         return QuasselType::BufferInfo;
566     else if (qstrcmp(name, "Identity") == 0)
567         return QuasselType::Identity;
568     else if (qstrcmp(name, "IdentityId") == 0)
569         return QuasselType::IdentityId;
570     else if (qstrcmp(name, "Message") == 0)
571         return QuasselType::Message;
572     else if (qstrcmp(name, "MsgId") == 0)
573         return QuasselType::MsgId;
574     else if (qstrcmp(name, "NetworkId") == 0)
575         return QuasselType::NetworkId;
576     else if (qstrcmp(name, "NetworkInfo") == 0)
577         return QuasselType::NetworkInfo;
578     else if (qstrcmp(name, "Network::Server") == 0)
579         return QuasselType::Network_Server;
580     else if (qstrcmp(name, "PeerPtr") == 0)
581         return QuasselType::PeerPtr;
582     else {
583         qWarning() << "Type name is not valid: " << name;
584         return QuasselType::Invalid;
585     }
586 }