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