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 ¶ms = QByteArrayLiteral("")); 0273 };