File indexing completed on 2024-04-28 16:37:43
0001 /* 0002 SPDX-FileCopyrightText: 2006-2015 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #undef QT_USE_FAST_CONCATENATION 0008 #undef QT_USE_FAST_OPERATOR_PLUS 0009 0010 #include <QTest> 0011 0012 #include "attachmenttest.h" 0013 0014 #include "kmime_util.h" 0015 #include "kmime_message.h" 0016 0017 using namespace KMime; 0018 0019 QTEST_MAIN(AttachmentTest) 0020 0021 void AttachmentTest::testIsAttachment_data() 0022 { 0023 QTest::addColumn<QByteArray>("mimeType"); 0024 QTest::addColumn<QString>("name"); 0025 QTest::addColumn<QString>("fileName"); 0026 QTest::addColumn<bool>("isAtt"); 0027 0028 QTest::newRow("empty") << QByteArray() << QString() << QString() << false; 0029 QTest::newRow("text part") << QByteArray("text/plain") << QString() << QString() << false; 0030 QTest::newRow("text part w/ CT name") << QByteArray("text/plain") << QStringLiteral("file.txt") << QString() << true; 0031 QTest::newRow("text part w/ CD name") << QByteArray("text/plain") << QString() << QStringLiteral("file.txt") << true; 0032 0033 // multipart is never an attachment, even with a CD name 0034 QTest::newRow("multipart/mixed") << QByteArray("multipart/mixed") << QString() << QStringLiteral("file.txt") << false; 0035 QTest::newRow("multipart/mixed upper") << QByteArray("MULTIPART/MIXED") << QString() << QStringLiteral("file.txt") << false; 0036 0037 // emails are always attachments, even without CT/CD names 0038 QTest::newRow("message/rfc822") << QByteArray("message/rfc822") << QString() << QString() << true; 0039 0040 // crypto nodes, even when looking like attachments, are not attachments 0041 QTest::newRow("crypto part") << QByteArray("application/octet-stream") << QString() << QStringLiteral("msg.asc") << false; 0042 } 0043 0044 void AttachmentTest::testIsAttachment() 0045 { 0046 QFETCH(QByteArray, mimeType); 0047 QFETCH(QString, name); 0048 QFETCH(QString, fileName); 0049 QFETCH(bool, isAtt); 0050 0051 auto root = new KMime::Message; 0052 root->contentType()->from7BitString("multipart/mixed"); 0053 root->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit); 0054 auto c0 = new KMime::Content; 0055 root->appendContent(c0); 0056 auto c = new KMime::Content; 0057 root->appendContent(c); 0058 if (!mimeType.isEmpty()) { 0059 c->contentType()->setMimeType(mimeType); 0060 } 0061 if (!name.isEmpty()) { 0062 c->contentType()->setName(name, "utf-8"); 0063 } 0064 if (!fileName.isEmpty()) { 0065 c->contentDisposition()->setFilename(fileName); 0066 } 0067 QCOMPARE(KMime::isAttachment(c), isAtt); 0068 QCOMPARE(KMime::hasAttachment(root), isAtt); 0069 0070 if (isAtt) { 0071 QCOMPARE(root->attachments().size(), 1); 0072 QCOMPARE(root->attachments().at(0), c); 0073 } else { 0074 QVERIFY(root->attachments().isEmpty()); 0075 } 0076 QVERIFY(c->attachments().isEmpty()); 0077 0078 delete root; 0079 } 0080 0081 // stuff not covered above 0082 void AttachmentTest::testIsAttachmentSpecial() 0083 { 0084 // don't crash on invalid input 0085 QCOMPARE(KMime::isAttachment(nullptr), false); 0086 QCOMPARE(KMime::hasAttachment(nullptr), false); 0087 0088 // disposition type "attachment" is a clear indicator... 0089 KMime::Content c; 0090 c.contentDisposition()->setDisposition(Headers::CDattachment); 0091 QCOMPARE(KMime::isAttachment(&c), true); 0092 } 0093 0094 void AttachmentTest::testHasAttachment() 0095 { 0096 // multipart/related is not an attachment 0097 auto root = new KMime::Message; 0098 root->contentType()->setMimeType("multipart/related"); 0099 0100 auto c1 = new KMime::Content; 0101 c1->contentType()->setMimeType("text/plain"); 0102 root->appendContent(c1); 0103 0104 auto c2 = new KMime::Content; 0105 c2->contentType()->setMimeType("image/jpeg"); 0106 c2->contentDisposition()->setFilename(QStringLiteral("image.jpg")); 0107 root->appendContent(c2); 0108 0109 QCOMPARE(KMime::hasAttachment(root), false); 0110 QCOMPARE(root->attachments().size(), 0); 0111 0112 // just to make sure this actually works for non multipart/related 0113 QCOMPARE(KMime::isAttachment(c2), true); 0114 root->contentType()->setMimeType("multipart/mixed"); 0115 QCOMPARE(KMime::hasAttachment(root), true); 0116 QCOMPARE(root->attachments().size(), 1); 0117 QCOMPARE(root->attachments().at(0), c2); 0118 delete root; 0119 0120 // multipart/alternative is also not an attachment 0121 root = new KMime::Message; 0122 root->contentType()->setMimeType("multipart/alternative"); 0123 0124 c1 = new KMime::Content; 0125 c1->contentType()->setMimeType("text/plain"); 0126 root->appendContent(c1); 0127 0128 c2 = new KMime::Content; 0129 c2->contentType()->setMimeType("text/html"); 0130 root->appendContent(c2); 0131 0132 QCOMPARE(KMime::hasAttachment(root), false); 0133 QCOMPARE(root->attachments().size(), 0); 0134 delete root; 0135 0136 // the main part of multipart/mixed is not an attachment, even if it looks like one 0137 root = new KMime::Message; 0138 root->contentType()->from7BitString("multipart/mixed"); 0139 root->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit); 0140 auto c0 = new KMime::Content; 0141 root->appendContent(c0); 0142 0143 c1 = new KMime::Content; 0144 c1->contentType()->setMimeType("text/plain"); 0145 c1->contentType()->setName(QStringLiteral("file.txt"), "utf-8"); 0146 root->prependContent(c1); 0147 QCOMPARE(KMime::isAttachment(c1), false); 0148 QCOMPARE(KMime::hasAttachment(c1), false); 0149 QCOMPARE(KMime::hasAttachment(root), false); 0150 QCOMPARE(root->attachments().size(), 0); 0151 delete root; 0152 } 0153 0154 void AttachmentTest::testNestedMultipart() 0155 { 0156 auto root = new KMime::Message; 0157 root->contentType()->from7BitString("multipart/mixed"); 0158 root->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit); 0159 auto c0 = new KMime::Content; 0160 root->appendContent(c0); 0161 0162 auto sig = new KMime::Content; 0163 sig->contentType()->setMimeType("application/pgp-signature"); 0164 sig->contentType()->setName(QStringLiteral("signature.asc"), "utf-8"); 0165 root->appendContent(sig); 0166 root->contentType()->setMimeType("multipart/signed"); 0167 0168 auto mixed = root->contents().at(0); 0169 0170 auto att = new KMime::Content; 0171 att->contentType()->setMimeType("image/jpeg"); 0172 att->contentType()->setName(QStringLiteral("attachment.jpg"), "utf-8"); 0173 mixed->appendContent(att); 0174 0175 mixed->contentType()->setMimeType("multipart/mixed"); 0176 0177 QVERIFY(KMime::hasAttachment(root)); 0178 QVERIFY(KMime::hasAttachment(mixed)); 0179 QCOMPARE(root->attachments().size(), 1); 0180 QCOMPARE(root->attachments().at(0), att); 0181 0182 delete root; 0183 } 0184 0185 void AttachmentTest::testEncrypted() 0186 { 0187 auto root = new KMime::Message; 0188 root->setContent( 0189 "From: firstname.lastname@example.com\n" 0190 "To: test@kolab.org\n" 0191 "Subject: OpenPGP encrypted with 2 text attachments\n" 0192 "Date: Sun, 30 Aug 2015 12:05:17 +0200\n" 0193 "Message-ID: <1505824.VT0nqpAGu0@vkpc5>\n" 0194 "MIME-Version: 1.0\n" 0195 "Content-Type: multipart/encrypted; boundary=\"nextPart3335835.KxmPgziKxd\"; protocol=\"application/pgp-encrypted\"\n" 0196 "\n" 0197 "--nextPart3335835.KxmPgziKxd\n" 0198 "Content-Type: application/pgp-encrypted\n" 0199 "Content-Disposition: attachment\n" 0200 "Content-Transfer-Encoding: 7Bit\n" 0201 "\n" 0202 "Version: 1\n" 0203 "--nextPart3335835.KxmPgziKxd\n" 0204 "Content-Type: application/octet-stream\n" 0205 "Content-Disposition: inline; filename=\"msg.asc\"\n" 0206 "Content-Transfer-Encoding: 7Bit\n" 0207 "\n" 0208 "-----BEGIN PGP MESSAGE-----\n" 0209 "-----END PGP MESSAGE-----\n" 0210 "\n" 0211 "--nextPart3335835.KxmPgziKxd--\n" 0212 ); 0213 root->parse(); 0214 QCOMPARE(hasAttachment(root), false); 0215 delete root; 0216 } 0217 0218 void AttachmentTest::testAttachment1() 0219 { 0220 auto root = new KMime::Message; 0221 root->setContent("From: Sender <sender@test.org>\n" 0222 "To: Receiver <receiver@test.org>\n" 0223 "Subject: Test\n" 0224 "Date: Thu, 19 Jul 2018 10:30:06 +0200\n" 0225 "MIME-Version: 1.0\n" 0226 "Content-Type: multipart/mixed; boundary=\"nextPart5103690.GVhdRC0Mqz\"\n" 0227 "Content-Transfer-Encoding: 7Bit\n" 0228 "\n" 0229 "This is a multi-part message in MIME format.\n" 0230 "\n" 0231 "--nextPart5103690.GVhdRC0Mqz\n" 0232 "Content-Transfer-Encoding: 7Bit\n" 0233 "Content-Type: text/plain; charset=\"us-ascii\"\n" 0234 "\n" 0235 "Foo\n" 0236 "\n" 0237 "--nextPart5103690.GVhdRC0Mqz\n" 0238 "Content-Disposition: attachment; filename=\"Screenshot_20180719_102529.png\"\n" 0239 "Content-Transfer-Encoding: base64\n" 0240 "Content-Type: image/png; name=\"Screenshot_20180719_102529.png\"\n" 0241 "\n" 0242 "ddd\n" 0243 "\n" 0244 "--nextPart5103690.GVhdRC0Mqz\n" 0245 "Content-Disposition: attachment; filename=\"Screenshot_20180719_102550.png\"\n" 0246 "Content-Transfer-Encoding: base64\n" 0247 "Content-Type: image/png; name=\"Screenshot_20180719_102550.png\"\n" 0248 "\n" 0249 "zzzz\n" 0250 "\n" 0251 "--nextPart5103690.GVhdRC0Mqz--\n"); 0252 0253 root->parse(); 0254 QCOMPARE(hasAttachment(root), true); 0255 delete root; 0256 } 0257 0258 void AttachmentTest::testAttachment2() 0259 { 0260 auto root = new KMime::Message; 0261 root->setContent("From: Sender <sender@test.org>\n" 0262 "Content-Type: multipart/alternative; boundary=\"Apple-Mail=_627B41D2-E6ED-4B17-8F96-6CD63EC055AE\"\n" 0263 "MIME-Version: 1.0\n" 0264 "Subject: Test\n" 0265 "Date: Tue, 11 Dec 2018 10:44:41 +0000\n" 0266 "To: Receiver <receiver@test.org>\n" 0267 "\n" 0268 "\n" 0269 "\n" 0270 "--Apple-Mail=_627B41D2-E6ED-4B17-8F96-6CD63EC055AE\n" 0271 "Content-Transfer-Encoding: quoted-printable\n" 0272 "Content-Type: text/plain; charset=\"us-ascii\"\n" 0273 "\n" 0274 "Text blabla\n" 0275 "\n" 0276 "--Apple-Mail=_627B41D2-E6ED-4B17-8F96-6CD63EC055AE\n" 0277 "Content-Type: multipart/mixed; boundary=\"Apple-Mail=_5FDAE280-1EA6-4604-9F81-BBB9B9137CE1\"\n" 0278 "\n" 0279 "\n" 0280 "--Apple-Mail=_5FDAE280-1EA6-4604-9F81-BBB9B9137CE1\n" 0281 "Content-Transfer-Encoding: 7bit\n" 0282 "Content-Type: text/html; charset=\"us-ascii\"\n" 0283 "\n" 0284 "<html><head><body>foo</body></html>\n" 0285 "--Apple-Mail=_5FDAE280-1EA6-4604-9F81-BBB9B9137CE1\n" 0286 "Content-Disposition: inline; filename=\"bla.pdf\"\n" 0287 "Content-Type: application/pdf; name=\"bla.pdf\"; x-unix-mode=\"0644\"\n" 0288 "Content-Transfer-Encoding: base64\n" 0289 "\n" 0290 "bla\n" 0291 "\n" 0292 "--Apple-Mail=_5FDAE280-1EA6-4604-9F81-BBB9B9137CE1\n" 0293 "Content-Transfer-Encoding: quoted-printable\n" 0294 "Content-Type: text/html; charset=\"us-ascii\"\n" 0295 "\n" 0296 "<html><body>foo html</body></html>=\n" 0297 "\n" 0298 "--Apple-Mail=_5FDAE280-1EA6-4604-9F81-BBB9B9137CE1--\n" 0299 "\n" 0300 "--Apple-Mail=_627B41D2-E6ED-4B17-8F96-6CD63EC055AE--\n"); 0301 0302 root->parse(); 0303 //Fix show has attachment 0304 QCOMPARE(hasAttachment(root), true); 0305 delete root; 0306 } 0307 0308 #include "moc_attachmenttest.cpp"