21ca92fd27452842b3909cfe41a23cee4c3faac5
[quassel.git] / src / common / serializers / serializers.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 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 bool checkStreamValid(QDataStream& stream)
24 {
25     if (stream.status() != QDataStream::Ok) {
26         qWarning() << "Peer sent corrupt data";
27         return false;
28     }
29
30     return true;
31 }
32
33 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantList& data)
34 {
35     uint32_t size;
36     if (!deserialize(stream, features, size))
37         return false;
38     if (size > 4 * 1024 * 1024) {
39         qWarning() << "Peer sent too large QVariantList: " << size;
40         return false;
41     }
42     for (uint32_t i = 0; i < size; i++) {
43         QVariant element;
44         if (!deserialize(stream, features, element))
45             return false;
46         data << element;
47     }
48     return checkStreamValid(stream);
49 }
50
51 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantMap& data)
52 {
53     uint32_t size;
54     if (!deserialize(stream, features, size))
55         return false;
56     if (size > 4 * 1024 * 1024) {
57         qWarning() << "Peer sent too large QVariantMap: " << size;
58         return false;
59     }
60     for (uint32_t i = 0; i < size; i++) {
61         QString key;
62         QVariant value;
63         if (!deserialize(stream, features, key))
64             return false;
65         if (!deserialize(stream, features, value))
66             return false;
67         data[key] = value;
68     }
69     return checkStreamValid(stream);
70 }
71
72 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data)
73 {
74     Types::VariantType type;
75     int8_t isNull;
76     if (!deserialize(stream, features, type))
77         return false;
78     if (!deserialize(stream, features, isNull))
79         return false;
80     if (type == Types::VariantType::UserType) {
81         QByteArray name;
82         if (!deserialize(stream, features, name))
83             return false;
84         while (name.length() > 0 && name.at(name.length() - 1) == 0)
85             name.chop(1);
86         if (!deserialize(stream, features, data, Types::fromName(name)))
87             return false;
88     }
89     else {
90         if (!deserialize(stream, features, data, type))
91             return false;
92     }
93     return checkStreamValid(stream);
94 }
95
96 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::VariantType type)
97 {
98     switch (type) {
99     case Types::VariantType::Void: {
100         return true;
101     }
102     case Types::VariantType::Bool: {
103         bool content;
104         if (!deserialize(stream, features, content))
105             return false;
106         data = QVariant(content);
107         return true;
108     }
109     case Types::VariantType::Int: {
110         int32_t content;
111         if (!deserialize(stream, features, content))
112             return false;
113         data = QVariant(content);
114         return true;
115     }
116     case Types::VariantType::UInt: {
117         uint32_t content;
118         if (!deserialize(stream, features, content))
119             return false;
120         data = QVariant(content);
121         return true;
122     }
123     case Types::VariantType::QChar: {
124         QChar content;
125         if (!deserialize(stream, features, content))
126             return false;
127         data = QVariant(content);
128         return true;
129     }
130     case Types::VariantType::QVariantMap: {
131         QVariantMap content;
132         if (!deserialize(stream, features, content))
133             return false;
134         data = QVariant(content);
135         return true;
136     }
137     case Types::VariantType::QVariantList: {
138         QVariantList content;
139         if (!deserialize(stream, features, content))
140             return false;
141         data = QVariant(content);
142         return true;
143     }
144     case Types::VariantType::QString: {
145         QString content;
146         if (!deserialize(stream, features, content))
147             return false;
148         data = QVariant(content);
149         return true;
150     }
151     case Types::VariantType::QStringList: {
152         QStringList content;
153         if (!deserialize(stream, features, content))
154             return false;
155         data = QVariant(content);
156         return true;
157     }
158     case Types::VariantType::QByteArray: {
159         QByteArray content;
160         if (!deserialize(stream, features, content))
161             return false;
162         data = QVariant(content);
163         return true;
164     }
165     case Types::VariantType::QDate: {
166         QDate content;
167         if (!deserialize(stream, features, content))
168             return false;
169         data = QVariant(content);
170         return true;
171     }
172     case Types::VariantType::QTime: {
173         QTime content;
174         if (!deserialize(stream, features, content))
175             return false;
176         data = QVariant(content);
177         return true;
178     }
179     case Types::VariantType::QDateTime: {
180         QDateTime content;
181         if (!deserialize(stream, features, content))
182             return false;
183         data = QVariant(content);
184         return true;
185     }
186     case Types::VariantType::Long: {
187         qlonglong content;
188         if (!deserialize(stream, features, content))
189             return false;
190         data = QVariant(content);
191         return true;
192     }
193     case Types::VariantType::Short: {
194         int16_t content;
195         if (!deserialize(stream, features, content))
196             return false;
197         data = QVariant(content);
198         return true;
199     }
200     case Types::VariantType::Char: {
201         int8_t content;
202         if (!deserialize(stream, features, content))
203             return false;
204         data = QVariant(content);
205         return true;
206     }
207     case Types::VariantType::ULong: {
208         qulonglong content;
209         if (!deserialize(stream, features, content))
210             return false;
211         data = QVariant(content);
212         return true;
213     }
214     case Types::VariantType::UShort: {
215         uint16_t content;
216         if (!deserialize(stream, features, content))
217             return false;
218         data = QVariant(content);
219         return true;
220     }
221     case Types::VariantType::UChar: {
222         uint8_t content;
223         if (!deserialize(stream, features, content))
224             return false;
225         data = QVariant(content);
226         return true;
227     }
228     case Types::VariantType::QVariant: {
229         QVariant content;
230         if (!deserialize(stream, features, content))
231             return false;
232         data = QVariant(content);
233         return true;
234     }
235     default: {
236         qWarning() << "Usertype should have been caught earlier already";
237         return false;
238     }
239     }
240 }
241
242 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::QuasselType type)
243 {
244     switch (type) {
245     case Types::QuasselType::BufferId: {
246         BufferId content;
247         if (!deserialize(stream, features, content))
248             return false;
249         data = qVariantFromValue(content);
250         return true;
251     }
252     case Types::QuasselType::BufferInfo: {
253         BufferInfo content;
254         if (!deserialize(stream, features, content))
255             return false;
256         data = qVariantFromValue(content);
257         return true;
258     }
259     case Types::QuasselType::Identity: {
260         Identity content;
261         if (!deserialize(stream, features, content))
262             return false;
263         data = qVariantFromValue(content);
264         return true;
265     }
266     case Types::QuasselType::IdentityId: {
267         IdentityId content;
268         if (!deserialize(stream, features, content))
269             return false;
270         data = qVariantFromValue(content);
271         return true;
272     }
273     case Types::QuasselType::Message: {
274         Message content;
275         if (!deserialize(stream, features, content))
276             return false;
277         data = qVariantFromValue(content);
278         return true;
279     }
280     case Types::QuasselType::MsgId: {
281         MsgId content;
282         if (!deserialize(stream, features, content))
283             return false;
284         data = qVariantFromValue(content);
285         return true;
286     }
287     case Types::QuasselType::NetworkId: {
288         NetworkId content;
289         if (!deserialize(stream, features, content))
290             return false;
291         data = qVariantFromValue(content);
292         return true;
293     }
294     case Types::QuasselType::NetworkInfo: {
295         NetworkInfo content;
296         if (!deserialize(stream, features, content))
297             return false;
298         data = qVariantFromValue(content);
299         return true;
300     }
301     case Types::QuasselType::Network_Server: {
302         Network::Server content;
303         if (!deserialize(stream, features, content))
304             return false;
305         data = qVariantFromValue(content);
306         return true;
307     }
308     case Types::QuasselType::PeerPtr: {
309         PeerPtr content;
310         if (!deserialize(stream, features, content))
311             return false;
312         data = qVariantFromValue(content);
313         return true;
314     }
315     default: {
316         qWarning() << "Invalid QType";
317         return false;
318     }
319     }
320 }
321
322 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Types::VariantType& data)
323 {
324     uint32_t raw;
325     if (!deserialize(stream, features, raw))
326         return false;
327     data = static_cast<Types::VariantType>(raw);
328     return checkStreamValid(stream);
329 }
330
331 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QStringList& data)
332 {
333     uint32_t size;
334     if (!deserialize(stream, features, size))
335         return false;
336     for (uint32_t i = 0; i < size; i++) {
337         QString element;
338         if (!deserialize(stream, features, element))
339             return false;
340         data << element;
341     }
342     return checkStreamValid(stream);
343 }
344
345 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Network::Server& server)
346 {
347     Q_UNUSED(features);
348     QVariantMap serverMap;
349     if (!deserialize(stream, features, serverMap))
350         return false;
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);
364 }
365
366 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Identity& data)
367 {
368     Q_UNUSED(features);
369     QVariantMap raw;
370     if (!deserialize(stream, features, raw))
371         return false;
372     data.fromVariantMap(raw);
373     return checkStreamValid(stream);
374 }
375
376 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkInfo& info)
377 {
378     Q_UNUSED(features);
379     QVariantMap i;
380     if (!deserialize(stream, features, i))
381         return false;
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);
408 }
409
410 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, PeerPtr& data)
411 {
412     Q_UNUSED(features);
413     stream >> data;
414     return checkStreamValid(stream);
415 }
416
417 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QByteArray& data)
418 {
419     Q_UNUSED(features);
420     data.clear();
421     uint32_t length;
422     if (!deserialize(stream, features, length))
423         return false;
424     // -1 - or 0xffffffff - is used for an empty byte array
425     if (length == 0xffffffff) {
426         return true;
427     }
428
429     // 64 MB should be enough
430     if (length > 64 * 1024 * 1024) {
431         qWarning() << "Peer sent too large QByteArray: " << length;
432         return false;
433     }
434
435     const uint32_t Step = 1024 * 1024;
436     uint32_t allocated = 0;
437     do {
438         int blockSize = std::min(Step, length - allocated);
439         data.resize(allocated + blockSize);
440         if (stream.readRawData(data.data() + allocated, blockSize) != blockSize) {
441             data.clear();
442             qWarning() << "BufferUnderFlow while reading QByteArray";
443             return false;
444         }
445         allocated += blockSize;
446     } while (allocated < length);
447     return checkStreamValid(stream);
448 }
449
450 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QString& data)
451 {
452     Q_UNUSED(features);
453     uint32_t bytes = 0;
454     // read size of string
455     if (!deserialize(stream, features, bytes))
456         return false;
457
458     // empty string
459     if (bytes == 0) {
460         return true;
461     }
462
463     // null string
464     if (bytes == 0xffffffff) {
465         data.clear();
466         return true;
467     }
468
469     // 64 MB should be enough
470     if (bytes > 64 * 1024 * 1024) {
471         qWarning() << "Peer sent too large QString: " << bytes;
472         return false;
473     }
474
475     if (bytes & 0x1) {
476         data.clear();
477         qWarning() << "Read corrupted data: UTF-6 String with odd length: " << bytes;
478         return false;
479     }
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) {
487             data.clear();
488             qWarning() << "BufferUnderFlow while reading QString";
489             return false;
490         }
491         allocated += blockSize;
492     }
493     if ((stream.byteOrder() == QDataStream::BigEndian) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
494         auto* rawData = reinterpret_cast<uint16_t*>(data.data());
495         while (length--) {
496             *rawData = qbswap(*rawData);
497             ++rawData;
498         }
499     }
500     return checkStreamValid(stream);
501 }
502
503 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QChar& data)
504 {
505     Q_UNUSED(features);
506     stream >> data;
507     return checkStreamValid(stream);
508 }
509
510 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDate& data)
511 {
512     Q_UNUSED(features);
513     stream >> data;
514     return checkStreamValid(stream);
515 }
516
517 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QTime& data)
518 {
519     Q_UNUSED(features);
520     stream >> data;
521     return checkStreamValid(stream);
522 }
523
524 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDateTime& data)
525 {
526     Q_UNUSED(features);
527     stream >> data;
528     return checkStreamValid(stream);
529 }
530
531 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int32_t& data)
532 {
533     Q_UNUSED(features);
534     stream >> data;
535     return checkStreamValid(stream);
536 }
537
538 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint32_t& data)
539 {
540     Q_UNUSED(features);
541     stream >> data;
542     return checkStreamValid(stream);
543 }
544
545 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int16_t& data)
546 {
547     Q_UNUSED(features);
548     stream >> data;
549     return checkStreamValid(stream);
550 }
551
552 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint16_t& data)
553 {
554     Q_UNUSED(features);
555     stream >> data;
556     return checkStreamValid(stream);
557 }
558
559 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int8_t& data)
560 {
561     Q_UNUSED(features);
562     stream >> data;
563     return checkStreamValid(stream);
564 }
565
566 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint8_t& data)
567 {
568     Q_UNUSED(features);
569     stream >> data;
570     return checkStreamValid(stream);
571 }
572
573 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qlonglong& data)
574 {
575     Q_UNUSED(features);
576     stream >> data;
577     return checkStreamValid(stream);
578 }
579
580 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qulonglong& data)
581 {
582     Q_UNUSED(features);
583     stream >> data;
584     return checkStreamValid(stream);
585 }
586
587 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, bool& data)
588 {
589     Q_UNUSED(features);
590     stream >> data;
591     return checkStreamValid(stream);
592 }
593
594 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferInfo& data)
595 {
596     Q_UNUSED(features);
597     stream >> data;
598     return checkStreamValid(stream);
599 }
600
601 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Message& data)
602 {
603     Q_UNUSED(features);
604     stream >> data;
605     return checkStreamValid(stream);
606 }
607
608 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkId& data)
609 {
610     Q_UNUSED(features);
611     stream >> data;
612     return checkStreamValid(stream);
613 }
614
615 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, IdentityId& data)
616 {
617     Q_UNUSED(features);
618     stream >> data;
619     return checkStreamValid(stream);
620 }
621
622 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferId& data)
623 {
624     Q_UNUSED(features);
625     stream >> data;
626     return checkStreamValid(stream);
627 }
628
629 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, MsgId& data)
630 {
631     Q_UNUSED(features);
632     stream >> data;
633     return checkStreamValid(stream);
634 }
635
636 Serializers::Types::VariantType Serializers::Types::variantType(Serializers::Types::QuasselType type)
637 {
638     switch (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;
659     default:
660         return VariantType::UserType;
661     }
662 }
663
664 QString Serializers::Types::toName(Serializers::Types::QuasselType type)
665 {
666     switch (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");
687     default:
688         return QString("Invalid Type");
689     }
690 }
691
692 Serializers::Types::QuasselType Serializers::Types::fromName(::QByteArray& name)
693 {
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;
714     else {
715         qWarning() << "Type name is not valid: " << name;
716         return QuasselType::Invalid;
717     }
718 }