src: Yearly copyright bump
[quassel.git] / src / common / serializers / serializers.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2019 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<T>(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     } else {
104         if (!deserialize(stream, features, data, type))
105             return false;
106     }
107     return checkStreamValid(stream);
108 }
109
110 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QVariant &data, Types::VariantType type)
111 {
112     switch (type) {
113     case Types::VariantType::Void:
114         return true;
115     case Types::VariantType::Bool:
116         return toVariant<bool>(stream, features, data);
117     case Types::VariantType::Int:
118         return toVariant<int32_t>(stream, features, data);
119     case Types::VariantType::UInt:
120         return toVariant<uint32_t>(stream, features, data);
121     case Types::VariantType::QChar:
122         return toVariant<QChar>(stream, features, data);
123     case Types::VariantType::QVariantMap:
124         return toVariant<QVariantMap>(stream, features, data);
125     case Types::VariantType::QVariantList:
126         return toVariant<QVariantList>(stream, features, data);
127     case Types::VariantType::QString:
128         return toVariant<QString>(stream, features, data);
129     case Types::VariantType::QStringList:
130         return toVariant<QStringList>(stream, features, data);
131     case Types::VariantType::QByteArray:
132         return toVariant<QByteArray>(stream, features, data);
133     case Types::VariantType::QDate:
134         return toVariant<QDate>(stream, features, data);
135     case Types::VariantType::QTime:
136         return toVariant<QTime>(stream, features, data);
137     case Types::VariantType::QDateTime:
138         return toVariant<QDateTime>(stream, features, data);
139     case Types::VariantType::Long:
140         return toVariant<qlonglong>(stream, features, data);
141     case Types::VariantType::Short:
142         return toVariant<int16_t>(stream, features, data);
143     case Types::VariantType::Char:
144         return toVariant<int8_t>(stream, features, data);
145     case Types::VariantType::ULong:
146         return toVariant<qulonglong>(stream, features, data);
147     case Types::VariantType::UShort:
148         return toVariant<uint16_t>(stream, features, data);
149     case Types::VariantType::UChar:
150         return toVariant<uint8_t>(stream, features, data);
151     case Types::VariantType::QVariant:
152         return toVariant<QVariant>(stream, features, data);
153     default:
154         qWarning() << "Usertype should have been caught earlier already";
155         return false;
156     }
157 }
158
159 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QVariant &data, Types::QuasselType type)
160 {
161     switch (type) {
162     case Types::QuasselType::BufferId:
163         return toVariant<BufferId>(stream, features, data);
164     case Types::QuasselType::BufferInfo:
165         return toVariant<BufferInfo>(stream, features, data);
166     case Types::QuasselType::Identity:
167         return toVariant<Identity>(stream, features, data);
168     case Types::QuasselType::IdentityId:
169         return toVariant<IdentityId>(stream, features, data);
170     case Types::QuasselType::Message:
171         return toVariant<Message>(stream, features, data);
172     case Types::QuasselType::MsgId:
173         return toVariant<MsgId>(stream, features, data);
174     case Types::QuasselType::NetworkId:
175         return toVariant<NetworkId>(stream, features, data);
176     case Types::QuasselType::NetworkInfo:
177         return toVariant<NetworkInfo>(stream, features, data);
178     case Types::QuasselType::Network_Server:
179         return toVariant<Network::Server>(stream, features, data);
180     case Types::QuasselType::PeerPtr:
181         return toVariant<PeerPtr>(stream, features, data);
182     default:
183         qWarning() << "Invalid QType";
184         return false;
185     }
186 }
187
188 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, Types::VariantType &data)
189 {
190     uint32_t raw;
191     if (!deserialize(stream, features, raw))
192         return false;
193     data = static_cast<Types::VariantType>(raw);
194     return checkStreamValid(stream);
195 }
196
197 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QStringList &data)
198 {
199     uint32_t size;
200     if (!deserialize(stream, features, size))
201         return false;
202     for (uint32_t i = 0; i < size; i++) {
203         QString element;
204         if (!deserialize(stream, features, element))
205             return false;
206         data << element;
207     }
208     return checkStreamValid(stream);
209 }
210
211 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, Network::Server &server)
212 {
213     Q_UNUSED(features);
214     QVariantMap serverMap;
215     if (!deserialize(stream, features, serverMap))
216         return false;
217     server.host = serverMap["Host"].toString();
218     server.port = serverMap["Port"].toUInt();
219     server.password = serverMap["Password"].toString();
220     server.useSsl = serverMap["UseSSL"].toBool();
221     server.sslVerify = serverMap["sslVerify"].toBool();
222     server.sslVersion = serverMap["sslVersion"].toInt();
223     server.useProxy = serverMap["UseProxy"].toBool();
224     server.proxyType = serverMap["ProxyType"].toInt();
225     server.proxyHost = serverMap["ProxyHost"].toString();
226     server.proxyPort = serverMap["ProxyPort"].toUInt();
227     server.proxyUser = serverMap["ProxyUser"].toString();
228     server.proxyPass = serverMap["ProxyPass"].toString();
229     return checkStreamValid(stream);
230 }
231
232 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, Identity &data)
233 {
234     Q_UNUSED(features);
235     QVariantMap raw;
236     if (!deserialize(stream, features, raw))
237         return false;
238     data.fromVariantMap(raw);
239     return checkStreamValid(stream);
240 }
241
242 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, NetworkInfo &info)
243 {
244     Q_UNUSED(features);
245     QVariantMap i;
246     if (!deserialize(stream, features, i))
247         return false;
248     info.networkId = i["NetworkId"].value<NetworkId>();
249     info.networkName = i["NetworkName"].toString();
250     info.identity = i["Identity"].value<IdentityId>();
251     info.codecForServer = i["CodecForServer"].toByteArray();
252     info.codecForEncoding = i["CodecForEncoding"].toByteArray();
253     info.codecForDecoding = i["CodecForDecoding"].toByteArray();
254     info.serverList = fromVariantList<Network::Server>(i["ServerList"].toList());
255     info.useRandomServer = i["UseRandomServer"].toBool();
256     info.perform = i["Perform"].toStringList();
257     info.useAutoIdentify = i["UseAutoIdentify"].toBool();
258     info.autoIdentifyService = i["AutoIdentifyService"].toString();
259     info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
260     info.useSasl = i["UseSasl"].toBool();
261     info.saslAccount = i["SaslAccount"].toString();
262     info.saslPassword = i["SaslPassword"].toString();
263     info.useAutoReconnect = i["UseAutoReconnect"].toBool();
264     info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
265     info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
266     info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool();
267     info.rejoinChannels = i["RejoinChannels"].toBool();
268     // Custom rate limiting
269     info.useCustomMessageRate = i["UseCustomMessageRate"].toBool();
270     info.messageRateBurstSize = i["MessageRateBurstSize"].toUInt();
271     info.messageRateDelay = i["MessageRateDelay"].toUInt();
272     info.unlimitedMessageRate = i["UnlimitedMessageRate"].toBool();
273     return checkStreamValid(stream);
274 }
275
276 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, PeerPtr &data)
277 {
278     Q_UNUSED(features);
279     stream >> data;
280     return checkStreamValid(stream);
281 }
282
283 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QByteArray &data)
284 {
285     Q_UNUSED(features);
286     data.clear();
287     uint32_t length;
288     if (!deserialize(stream, features, length))
289         return false;
290     // -1 - or 0xffffffff - is used for an empty byte array
291     if (length == 0xffffffff) {
292         return true;
293     }
294
295     // 64 MB should be enough
296     if (length > 64 * 1024 * 1024) {
297         qWarning() << "Peer sent too large QByteArray: " << length;
298         return false;
299     }
300
301     const uint32_t Step = 1024 * 1024;
302     uint32_t allocated = 0;
303     do {
304         int blockSize = std::min(Step, length - allocated);
305         data.resize(allocated + blockSize);
306         if (stream.readRawData(data.data() + allocated, blockSize) != blockSize) {
307             data.clear();
308             qWarning() << "BufferUnderFlow while reading QByteArray";
309             return false;
310         }
311         allocated += blockSize;
312     } while (allocated < length);
313     return checkStreamValid(stream);
314 }
315
316 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QString &data)
317 {
318     Q_UNUSED(features);
319     uint32_t bytes = 0;
320     // read size of string
321     if (!deserialize(stream, features, bytes))
322         return false;
323
324     // empty string
325     if (bytes == 0) {
326         return true;
327     }
328
329     // null string
330     if (bytes == 0xffffffff) {
331         data.clear();
332         return true;
333     }
334
335     // 64 MB should be enough
336     if (bytes > 64 * 1024 * 1024) {
337         qWarning() << "Peer sent too large QString: " << bytes;
338         return false;
339     }
340
341     if (bytes & 0x1) {
342         data.clear();
343         qWarning() << "Read corrupted data: UTF-6 String with odd length: " << bytes;
344         return false;
345     }
346     const uint32_t step = 1024 * 1024;
347     uint32_t length = bytes / 2;
348     uint32_t allocated = 0;
349     while (allocated < length) {
350         int blockSize = std::min(step, length - allocated);
351         data.resize(allocated + blockSize);
352         if (stream.readRawData(reinterpret_cast<char *>(data.data()) + allocated * 2, blockSize * 2) != blockSize * 2) {
353             data.clear();
354             qWarning() << "BufferUnderFlow while reading QString";
355             return false;
356         }
357         allocated += blockSize;
358     }
359     if ((stream.byteOrder() == QDataStream::BigEndian) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
360         uint16_t *rawData = reinterpret_cast<uint16_t *>(data.data());
361         while (length--) {
362             *rawData = qbswap(*rawData);
363             ++rawData;
364         }
365     }
366     return checkStreamValid(stream);
367 }
368
369 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QChar &data)
370 {
371     Q_UNUSED(features);
372     stream >> data;
373     return checkStreamValid(stream);
374 }
375
376 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QDate &data)
377 {
378     Q_UNUSED(features);
379     stream >> data;
380     return checkStreamValid(stream);
381 }
382
383 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QTime &data)
384 {
385     Q_UNUSED(features);
386     stream >> data;
387     return checkStreamValid(stream);
388 }
389
390 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, QDateTime &data)
391 {
392     Q_UNUSED(features);
393     stream >> data;
394     return checkStreamValid(stream);
395 }
396
397 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, int32_t &data)
398 {
399     Q_UNUSED(features);
400     stream >> data;
401     return checkStreamValid(stream);
402 }
403
404 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, uint32_t &data)
405 {
406     Q_UNUSED(features);
407     stream >> data;
408     return checkStreamValid(stream);
409 }
410
411 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, int16_t &data)
412 {
413     Q_UNUSED(features);
414     stream >> data;
415     return checkStreamValid(stream);
416 }
417
418 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, uint16_t &data)
419 {
420     Q_UNUSED(features);
421     stream >> data;
422     return checkStreamValid(stream);
423 }
424
425 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, int8_t &data)
426 {
427     Q_UNUSED(features);
428     stream >> data;
429     return checkStreamValid(stream);
430 }
431
432 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, uint8_t &data)
433 {
434     Q_UNUSED(features);
435     stream >> data;
436     return checkStreamValid(stream);
437 }
438
439 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, qlonglong &data)
440 {
441     Q_UNUSED(features);
442     stream >> data;
443     return checkStreamValid(stream);
444 }
445
446 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, qulonglong &data)
447 {
448     Q_UNUSED(features);
449     stream >> data;
450     return checkStreamValid(stream);
451 }
452
453 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, bool &data)
454 {
455     Q_UNUSED(features);
456     stream >> data;
457     return checkStreamValid(stream);
458 }
459
460 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, BufferInfo &data)
461 {
462     Q_UNUSED(features);
463     stream >> data;
464     return checkStreamValid(stream);
465 }
466
467 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, Message &data)
468 {
469     Q_UNUSED(features);
470     stream >> data;
471     return checkStreamValid(stream);
472 }
473
474 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, NetworkId &data)
475 {
476     Q_UNUSED(features);
477     stream >> data;
478     return checkStreamValid(stream);
479 }
480
481 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, IdentityId &data)
482 {
483     Q_UNUSED(features);
484     stream >> data;
485     return checkStreamValid(stream);
486 }
487
488 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, BufferId &data)
489 {
490     Q_UNUSED(features);
491     stream >> data;
492     return checkStreamValid(stream);
493 }
494
495 bool Serializers::deserialize(QDataStream &stream, const Quassel::Features &features, MsgId &data)
496 {
497     Q_UNUSED(features);
498     stream >> data;
499     return checkStreamValid(stream);
500 }
501
502 Serializers::Types::VariantType Serializers::Types::variantType(Serializers::Types::QuasselType type)
503 {
504     switch (type) {
505         case QuasselType::BufferId:
506             return VariantType::UserType;
507         case QuasselType::BufferInfo:
508             return VariantType::UserType;
509         case QuasselType::Identity:
510             return VariantType::UserType;
511         case QuasselType::IdentityId:
512             return VariantType::UserType;
513         case QuasselType::Message:
514             return VariantType::UserType;
515         case QuasselType::MsgId:
516             return VariantType::UserType;
517         case QuasselType::NetworkId:
518             return VariantType::UserType;
519         case QuasselType::NetworkInfo:
520             return VariantType::UserType;
521         case QuasselType::Network_Server:
522             return VariantType::UserType;
523         case QuasselType::PeerPtr:
524             return VariantType::Long;
525         default:
526             return VariantType::UserType;
527     }
528 }
529
530 QString Serializers::Types::toName(Serializers::Types::QuasselType type)
531 {
532     switch (type) {
533         case QuasselType::BufferId:
534             return QString("BufferId");
535         case QuasselType::BufferInfo:
536             return QString("BufferInfo");
537         case QuasselType::Identity:
538             return QString("Identity");
539         case QuasselType::IdentityId:
540             return QString("IdentityId");
541         case QuasselType::Message:
542             return QString("Message");
543         case QuasselType::MsgId:
544             return QString("MsgId");
545         case QuasselType::NetworkId:
546             return QString("NetworkId");
547         case QuasselType::NetworkInfo:
548             return QString("NetworkInfo");
549         case QuasselType::Network_Server:
550             return QString("Network::Server");
551         case QuasselType::PeerPtr:
552             return QString("PeerPtr");
553         default:
554             return QString("Invalid Type");
555     }
556 }
557
558 Serializers::Types::QuasselType Serializers::Types::fromName(::QByteArray &name)
559 {
560     if (qstrcmp(name, "BufferId") == 0) return QuasselType::BufferId;
561     else if (qstrcmp(name, "BufferInfo") == 0) return QuasselType::BufferInfo;
562     else if (qstrcmp(name, "Identity") == 0) return QuasselType::Identity;
563     else if (qstrcmp(name, "IdentityId") == 0) return QuasselType::IdentityId;
564     else if (qstrcmp(name, "Message") == 0) return QuasselType::Message;
565     else if (qstrcmp(name, "MsgId") == 0) return QuasselType::MsgId;
566     else if (qstrcmp(name, "NetworkId") == 0) return QuasselType::NetworkId;
567     else if (qstrcmp(name, "NetworkInfo") == 0) return QuasselType::NetworkInfo;
568     else if (qstrcmp(name, "Network::Server") == 0) return QuasselType::Network_Server;
569     else if (qstrcmp(name, "PeerPtr") == 0) return QuasselType::PeerPtr;
570     else {
571         qWarning() << "Type name is not valid: " << name;
572         return QuasselType::Invalid;
573     }
574 }