File indexing completed on 2024-05-05 17:32:29

0001 // SPDX-FileCopyrightText: 2021 Michael Lang <criticaltemp@protonmail.com>
0002 //
0003 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 
0005 #pragma once
0006 
0007 #include <QDateTime>
0008 #include <QObject>
0009 
0010 #include <span>
0011 
0012 #include <global.h>
0013 #include <phonenumberlist.h>
0014 
0015 /*
0016  * Spec documentation:
0017  * http://www.openmobilealliance.org/release/MMS/V1_3-20110913-A/OMA-TS-MMS_ENC-V1_3-20110913-A.pdf
0018  *
0019  * Content types:
0020  * https://technical.openmobilealliance.org/OMNA/wsp/wsp_content_type_codes.html
0021  */
0022 
0023 struct FieldMap {
0024     unsigned char id;
0025     QStringView name;
0026     QStringView type;
0027 };
0028 
0029 constexpr std::array<QStringView, 24> MESSAGE_TYPES = {
0030     u"m-send-req",         u"m-send-conf",     u"m-notification-ind", u"m-notifyresp-ind",  u"m-retrieve-conf",    u"m-acknowledge-ind",
0031     u"m-delivery-ind",     u"m-read-rec-ind",  u"m-read-orig-ind",    u"m-forward-req",     u"m-forward-conf",     u"m-mbox-store-req",
0032     u"m-mbox-store-conf",  u"m-mbox-view-req", u"m-mbox-view-conf",   u"m-mbox-upload-req", u"m-mbox-upload-conf", u"m-mbox-delete-req",
0033     u"m-mbox-delete-conf", u"m-mbox-descr",    u"m-delete-req",       u"m-delete-conf",     u"m-cancel-req",       u"m-cancel-conf"};
0034 
0035 constexpr std::array<QStringView, 81> CONTENT_TYPES = {u"*/*",
0036                                                        u"text/*",
0037                                                        u"text/html",
0038                                                        u"text/plain",
0039                                                        u"text/x-hdml",
0040                                                        u"text/x-ttml",
0041                                                        u"text/x-vCalendar",
0042                                                        u"text/x-vCard",
0043                                                        u"text/vnd.wap.wml",
0044                                                        u"text/vnd.wap.wmlscript",
0045                                                        u"text/vnd.wap.wta-event",
0046                                                        u"multipart/*",
0047                                                        u"multipart/mixed",
0048                                                        u"multipart/form-data",
0049                                                        u"multipart/byteranges",
0050                                                        u"multipart/alternative",
0051                                                        u"application/*",
0052                                                        u"application/java-vm",
0053                                                        u"application/x-www-form-urlencoded",
0054                                                        u"application/x-hdmlc",
0055                                                        u"application/vnd.wap.wmlc",
0056                                                        u"application/vnd.wap.wmlscriptc",
0057                                                        u"application/vnd.wap.wta-eventc",
0058                                                        u"application/vnd.wap.uaprof",
0059                                                        u"application/vnd.wap.wtls-ca-certificate",
0060                                                        u"application/vnd.wap.wtls-user-certificate",
0061                                                        u"application/x-x509-ca-cert",
0062                                                        u"application/x-x509-user-cert",
0063                                                        u"image/*",
0064                                                        u"image/gif",
0065                                                        u"image/jpeg",
0066                                                        u"image/tiff",
0067                                                        u"image/png",
0068                                                        u"image/vnd.wap.wbmp",
0069                                                        u"application/vnd.wap.multipart.*",
0070                                                        u"application/vnd.wap.multipart.mixed",
0071                                                        u"application/vnd.wap.multipart.form-data",
0072                                                        u"application/vnd.wap.multipart.byteranges",
0073                                                        u"application/vnd.wap.multipart.alternative",
0074                                                        u"application/xml",
0075                                                        u"text/xml",
0076                                                        u"application/vnd.wap.wbxml",
0077                                                        u"application/x-x968-cross-cert",
0078                                                        u"application/x-x968-ca-cert",
0079                                                        u"application/x-x968-user-cert",
0080                                                        u"text/vnd.wap.si",
0081                                                        u"application/vnd.wap.sic",
0082                                                        u"text/vnd.wap.sl",
0083                                                        u"application/vnd.wap.slc",
0084                                                        u"text/vnd.wap.co",
0085                                                        u"application/vnd.wap.coc",
0086                                                        u"application/vnd.wap.multipart.related",
0087                                                        u"application/vnd.wap.sia",
0088                                                        u"text/vnd.wap.connectivity-xml",
0089                                                        u"application/vnd.wap.connectivity-wbxml",
0090                                                        u"application/pkcs7-mime",
0091                                                        u"application/vnd.wap.hashed-certificate",
0092                                                        u"application/vnd.wap.signed-certificate",
0093                                                        u"application/vnd.wap.cert-response",
0094                                                        u"application/xhtml+xml",
0095                                                        u"application/wml+xml",
0096                                                        u"text/css",
0097                                                        u"application/vnd.wap.mms-message",
0098                                                        u"application/vnd.wap.rollover-certificate",
0099                                                        u"application/vnd.wap.locc+wbxml",
0100                                                        u"application/vnd.wap.loc+xml",
0101                                                        u"application/vnd.syncml.dm+wbxml",
0102                                                        u"application/vnd.syncml.dm+xml",
0103                                                        u"application/vnd.syncml.notification",
0104                                                        u"application/vnd.wap.xhtml+xml",
0105                                                        u"application/vnd.wv.csp.cir",
0106                                                        u"application/vnd.oma.dd+xml",
0107                                                        u"application/vnd.oma.drm.message",
0108                                                        u"application/vnd.oma.drm.content",
0109                                                        u"application/vnd.oma.drm.rights+xml",
0110                                                        u"application/vnd.oma.drm.rights+wbxml",
0111                                                        u"application/vnd.wv.csp+xml ",
0112                                                        u"application/vnd.wv.csp+wbxml",
0113                                                        u"application/vnd.syncml.ds.notification",
0114                                                        u"audio/*",
0115                                                        u"video/* "};
0116 
0117 constexpr std::array<QStringView, 8> STATUS_VALUES =
0118     {u"expired", u"retrieved", u"rejected", u"deferred", u"unrecognized", u"indeterminate", u"forwarded", u"unreachable"};
0119 
0120 constexpr std::array<FieldMap, 63> HEADER_FIELDS = {FieldMap{0x81, u"bcc", u"encodedStringValue"},
0121                                                     {0x82, u"cc", u"encodedStringValue"},
0122                                                     {0x83, u"contentLocation", u"textString"},
0123                                                     {0x84, u"contentType", u"contentTypeValue"},
0124                                                     {0x85, u"date", u"dateValue"},
0125                                                     {0x86, u"deliveryReport", u"shortInteger"},
0126                                                     {0x87, u"deliveryTime", u"dateValue"},
0127                                                     {0x88, u"expiry", u"dateValue"},
0128                                                     {0x89, u"from", u"fromValue"},
0129                                                     {0x8A, u"messageClass", u"messageClassValue"},
0130                                                     {0x8B, u"messageId", u"textString"},
0131                                                     {0x8C, u"messageType", u"messageTypeValue"},
0132                                                     {0x8D, u"mmsVersion", u"mmsVersion"},
0133                                                     {0x8E, u"messageSize", u"longInteger"},
0134                                                     {0x8F, u"priority", u"shortInteger"},
0135                                                     {0x90, u"readReport", u"shortInteger"},
0136                                                     {0x91, u"reportAllowed", u"shortInteger"},
0137                                                     {0x92, u"responseStatus", u"shortInteger"},
0138                                                     {0x93, u"responseText", u"encodedStringValue"},
0139                                                     {0x94, u"senderVisibility", u"shortInteger"},
0140                                                     {0x95, u"status", u"shortInteger"},
0141                                                     {0x96, u"subject", u"encodedStringValue"},
0142                                                     {0x97, u"to", u"encodedStringValue"},
0143                                                     {0x98, u"transactionId", u"textString"},
0144                                                     {0x99, u"retrieveStatus", u"shortInteger"},
0145                                                     {0x9A, u"retrieveText", u"encodedStringValue"},
0146                                                     {0x9B, u"readStatus", u"shortInteger"},
0147                                                     {0x9C, u"replyCharging", u"shortInteger"},
0148                                                     {0x9D, u"replyChargingDeadline", u"fromValue"},
0149                                                     {0x9E, u"replyChargingId", u"textString"},
0150                                                     {0x9F, u"replyChargingSize", u"longInteger"},
0151                                                     {0xA0, u"previoulySentBy", u"encodedStringValue"},
0152                                                     {0xA1, u"previoulySentDate", u"longInteger"},
0153                                                     {0xA2, u"store", u"shortInteger"},
0154                                                     {0xA3, u"mmState", u"shortInteger"},
0155                                                     {0xA4, u"mmFlags", u"encodedStringValue"},
0156                                                     {0xA5, u"storeStatus", u"shortInteger"},
0157                                                     {0xA6, u"storeStatusText", u"encodedStringValue"},
0158                                                     {0xA7, u"stored", u"shortInteger"},
0159                                                     {0xA8, u"attributes", u"shortInteger"},
0160                                                     {0xA9, u"totals", u"shortInteger"},
0161                                                     {0xAA, u"mboxTotals", u"shortInteger"},
0162                                                     {0xAB, u"quotas", u"shortInteger"},
0163                                                     {0xAC, u"mboxQuotas", u"shortInteger"},
0164                                                     {0xAD, u"messageCount", u"shortInteger"},
0165                                                     {0xAE, u"content", u"encodedStringValue"},
0166                                                     {0xAF, u"start", u"shortInteger"},
0167                                                     {0xB0, u"additionalHeaders", u"shortInteger"},
0168                                                     {0xB1, u"distributionIndicator", u"shortInteger"},
0169                                                     {0xB2, u"elementDescription", u"textString"},
0170                                                     {0xB3, u"limit", u"shortInteger"},
0171                                                     {0xB4, u"recRetrievalMode", u"shortInteger"},
0172                                                     {0xB5, u"recdRetrievalModeText", u"encodedStringValue"},
0173                                                     {0xB6, u"statusText", u"encodedStringValue"},
0174                                                     {0xB7, u"applicId", u"textString"},
0175                                                     {0xB8, u"replyApplicId", u"textString"},
0176                                                     {0xB9, u"auxAppliInfo", u"textString"},
0177                                                     {0xBA, u"contentClass", u"shortInteger"},
0178                                                     {0xBB, u"drmContent", u"shortInteger"},
0179                                                     {0xBC, u"adaptationAllowed", u"shortInteger"},
0180                                                     {0xBD, u"replaceId", u"textString"},
0181                                                     {0xBE, u"cancelId", u"textString"},
0182                                                     {0xBF, u"cancelStatus", u"shortInteger"}};
0183 
0184 constexpr std::array<FieldMap, 29> PARAM_FIELDS = {FieldMap{0x01, u"q", u"qValue"},         {0x02, u"charset", u"textString"},
0185                                                    {0x03, u"level", u"versionValue"},       {0x04, u"type", u"integerValue"},
0186                                                    {0x05, u"name", u"textString"},          {0x06, u"filename", u"encodedStringValue"},
0187                                                    {0x07, u"differences", u"fieldName"},    {0x08, u"padding", u"shortInteger"},
0188                                                    {0x09, u"typeSpec", u"textString"},      {0x0A, u"start", u"textString"},
0189                                                    {0x0B, u"startInfo", u"textString"},     {0x0C, u"comment", u"textString"},
0190                                                    {0x0D, u"domain", u"textString"},        {0x0E, u"maxAge", u"longInteger"},
0191                                                    {0x0F, u"path", u"textString"},          {0x10, u"secure", u""},
0192                                                    {0x11, u"sec", u"shortInteger"},         {0x12, u"mac", u"textValue"},
0193                                                    {0x13, u"creationDate", u"longInteger"}, {0x14, u"modificationDate", u"longInteger"},
0194                                                    {0x15, u"readDate", u"longInteger"},     {0x16, u"size", u"integerValue"},
0195                                                    {0x17, u"nameVal", u"textValue"},        {0x18, u"filenameVal", u"textValue"},
0196                                                    {0x19, u"startMulti", u"textValue"},     {0x1A, u"startInfoMulti", u"textValue"},
0197                                                    {0x1B, u"commentVal", u"textValue"},     {0x1C, u"domainVal", u"textValue"},
0198                                                    {0x1D, u"pathVal", u"textValue"}};
0199 
0200 struct MmsMessage {
0201     QString messageType;
0202     QString transactionId;
0203     QString messageId;
0204     qint64 messageSize = 0;
0205     QDateTime expiry;
0206     QDateTime date = QDateTime::currentDateTime();
0207     QStringList to;
0208     QString from;
0209     QString subject;
0210     QString contentType;
0211     QString contentLocation;
0212     QString text;
0213     QString attachments;
0214     QString smil;
0215     QStringList partNames;
0216     int responseStatus = 0;
0217     QString responseText;
0218 
0219     // The following are not part of a mms. Stored here rather than passing extra params
0220     QString databaseId;
0221     PhoneNumberList phoneNumberList;
0222     PhoneNumber ownNumber;
0223 };
0224 Q_DECLARE_METATYPE(MmsMessage)
0225 
0226 class Mms : public QObject
0227 {
0228     Q_OBJECT
0229 
0230 public:
0231     explicit Mms(QObject *parent = nullptr);
0232 
0233     QByteArray encodeNotifyResponse(const QString &transactionId, const QString &status);
0234     QByteArray encodeDeliveryAcknowledgement(const QString &transactionId);
0235     QByteArray encodeReadReport(const QString &messageId);
0236     QByteArray encodeCancelResponse(const QString &transactionId);
0237     void decodeNotification(MmsMessage &message, const QByteArray &data);
0238     void decodeConfirmation(MmsMessage &message, const QByteArray &data);
0239     void decodeMessage(MmsMessage &message, const QByteArray &data);
0240     void encodeMessage(MmsMessage &message, QByteArray &data, const QStringList &files, qint64 totalSize);
0241     static QString generateTransactionId();
0242 
0243 private:
0244     bool decodeHeader(MmsMessage &message, const QByteArray &data, int &pos);
0245     QByteArray encodeHeaderPrefix(const QString &type, const QString &id, bool msgId = false);
0246     bool decodeMessageBody(MmsMessage &message, const QByteArray &data, int &pos);
0247     QString saveLocation(const QString &folderName, const QString &subFolderName = QString());
0248     bool saveData(const QByteArray &data, const QString &path);
0249     static QString generateRandomId();
0250 
0251     QString contentTypeValue(const QByteArray &data, int &pos, MmsMessage &message);
0252     QString messageTypeValue(const QByteArray &data, int &pos);
0253     unsigned int unsignedInt(const QByteArray &data, int &pos);
0254     quint64 longInteger(const QByteArray &data, int &pos);
0255     int shortInteger(const QByteArray &data, int &pos);
0256     int integerValue(const QByteArray &data, int &pos);
0257     int valueLength(const QByteArray &data, int &pos);
0258     QString textString(const QByteArray &data, int &pos, int len = -1);
0259     QString encodedStringValue(const QByteArray &data, int &pos);
0260     QString fromValue(const QByteArray &data, int &pos);
0261     QDateTime dateValue(const QByteArray &data, int &pos);
0262     QString messageClassValue(const QByteArray &data, int &pos);
0263     QString mmsVersion(const QByteArray &data, int &pos);
0264     QString lookupValString(const QByteArray &data, int &pos, std::span<const QStringView> list);
0265 
0266     QByteArray encodeUnsignedInt(unsigned int value);
0267     QByteArray encodeLongInteger(quint64 value);
0268     QByteArray encodeTextValue(const QString &value);
0269     QByteArray encodeEncodedStringValue(const QString &value);
0270     QByteArray encodeFromValue(const QString &value);
0271     QByteArray encodeValueFromList(const QString &value, std::span<const QStringView> list);
0272     QByteArray encodePart(const QByteArray &type, const QString &name, const QByteArray &body, const QByteArray &params = QByteArrayLiteral(""));
0273 };