File indexing completed on 2024-04-28 11:40:32
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2010, 2011 Rolf Eike Beer <kde@opensource.sf-tec.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "httpheaderdispositiontest.h" 0009 0010 #include <QTest> 0011 0012 #include <QByteArray> 0013 0014 #include <parsinghelpers.h> 0015 0016 #include <parsinghelpers.cpp> 0017 0018 // QT5 TODO QTEST_GUILESS_MAIN(HeaderDispositionTest) 0019 QTEST_MAIN(HeaderDispositionTest) 0020 0021 static void runTest(const QString &header, const QByteArray &result) 0022 { 0023 QMap<QString, QString> parameters = contentDispositionParser(header); 0024 0025 QList<QByteArray> results = result.split('\n'); 0026 if (result.isEmpty()) { 0027 results.clear(); 0028 } 0029 0030 for (const QByteArray &ba : std::as_const(results)) { 0031 QList<QByteArray> values = ba.split('\t'); 0032 const QString key(QString::fromLatin1(values.takeFirst())); 0033 0034 QVERIFY(parameters.contains(key)); 0035 0036 const QByteArray val = values.takeFirst(); 0037 QVERIFY(values.isEmpty()); 0038 0039 QCOMPARE(parameters[key], QString::fromUtf8(val.constData(), val.length())); 0040 } 0041 0042 QCOMPARE(parameters.count(), results.count()); 0043 } 0044 0045 void HeaderDispositionTest::runAllTests_data() 0046 { 0047 QTest::addColumn<QString>("header"); 0048 QTest::addColumn<QByteArray>("result"); 0049 0050 // http://greenbytes.de/tech/tc2231/ 0051 QTest::newRow("greenbytes-inlonly") << "inline" << QByteArray("type\tinline"); 0052 QTest::newRow("greenbytes-inlonlyquoted") << "\"inline\"" << QByteArray(); 0053 QTest::newRow("greenbytes-inlwithasciifilename") << "inline; filename=\"foo.html\"" 0054 << QByteArray( 0055 "type\tinline\n" 0056 "filename\tfoo.html"); 0057 QTest::newRow("greenbytes-inlwithfnattach") << "inline; filename=\"Not an attachment!\"" 0058 << QByteArray( 0059 "type\tinline\n" 0060 "filename\tNot an attachment!"); 0061 QTest::newRow("greenbytes-inlwithasciifilenamepdf") << "inline; filename=\"foo.pdf\"" 0062 << QByteArray( 0063 "type\tinline\n" 0064 "filename\tfoo.pdf"); 0065 QTest::newRow("greenbytes-attonly") << "attachment" << QByteArray("type\tattachment"); 0066 QTest::newRow("greenbytes-attonlyquoted") << "\"attachment\"" << QByteArray(); 0067 QTest::newRow("greenbytes-attonlyucase") << "ATTACHMENT" << QByteArray("type\tattachment"); 0068 QTest::newRow("greenbytes-attwithasciifilename") << "attachment; filename=\"foo.html\"" 0069 << QByteArray( 0070 "type\tattachment\n" 0071 "filename\tfoo.html"); 0072 QTest::newRow("greenbytes-attwithasciifnescapedchar") << "attachment; filename=\"f\\oo.html\"" 0073 << QByteArray( 0074 "type\tattachment\n" 0075 "filename\tfoo.html"); 0076 QTest::newRow("greenbytes-attwithasciifnescapedquote") << "attachment; filename=\"\\\"quoting\\\" tested.html\"" 0077 << QByteArray( 0078 "type\tattachment\n" 0079 "filename\t\"quoting\" tested.html"); 0080 QTest::newRow("greenbytes-attwithquotedsemicolon") << "attachment; filename=\"Here's a semicolon;.html\"" 0081 << QByteArray( 0082 "type\tattachment\n" 0083 "filename\tHere's a semicolon;.html"); 0084 QTest::newRow("greenbytes-attwithfilenameandextparam") << "attachment; foo=\"bar\"; filename=\"foo.html\"" 0085 << QByteArray( 0086 "type\tattachment\n" 0087 "foo\tbar\n" 0088 "filename\tfoo.html"); 0089 QTest::newRow("greenbytes-attwithfilenameandextparamescaped") << "attachment; foo=\"\\\"\\\\\";filename=\"foo.html\"" 0090 << QByteArray( 0091 "type\tattachment\n" 0092 "foo\t\"\\\n" 0093 "filename\tfoo.html"); 0094 QTest::newRow("greenbytes-attwithasciifilenameucase") << "attachment; FILENAME=\"foo.html\"" 0095 << QByteArray( 0096 "type\tattachment\n" 0097 "filename\tfoo.html"); 0098 // specification bug in RfC 2616, legal through RfC 2183 and 6266 0099 QTest::newRow("greenbytes-attwithasciifilenamenq") << "attachment; filename=foo.html" 0100 << QByteArray( 0101 "type\tattachment\n" 0102 "filename\tfoo.html"); 0103 QTest::newRow("greenbytes-attwithasciifilenamenqws") << "attachment; filename=foo bar.html" << QByteArray("type\tattachment"); 0104 QTest::newRow("greenbytes-attwithfntokensq") << "attachment; filename='foo.bar'" 0105 << QByteArray( 0106 "type\tattachment\n" 0107 "filename\t'foo.bar'"); 0108 QTest::newRow("greenbytes-attwithisofnplain-x") << QStringLiteral("attachment; filename=\"foo-\xe4.html\"") 0109 << QByteArray( 0110 "type\tattachment\n" 0111 "filename\tfoo-ä.html"); 0112 QTest::newRow("greenbytes-attwithisofnplain") << QString::fromLatin1("attachment; filename=\"foo-ä.html\"") 0113 << QByteArray( 0114 "type\tattachment\n" 0115 "filename\tfoo-ä.html"); 0116 QTest::newRow("greenbytes-attwithfnrawpctenca") << "attachment; filename=\"foo-%41.html\"" 0117 << QByteArray( 0118 "type\tattachment\n" 0119 "filename\tfoo-%41.html"); 0120 QTest::newRow("greenbytes-attwithfnusingpct") << "attachment; filename=\"50%.html\"" 0121 << QByteArray( 0122 "type\tattachment\n" 0123 "filename\t50%.html"); 0124 QTest::newRow("greenbytes-attwithfnrawpctencaq") << "attachment; filename=\"foo-%\\41.html\"" 0125 << QByteArray( 0126 "type\tattachment\n" 0127 "filename\tfoo-%41.html"); 0128 QTest::newRow("greenbytes-attwithnamepct") << "attachment; name=\"foo-%41.html\"" 0129 << QByteArray( 0130 "type\tattachment\n" 0131 "name\tfoo-%41.html"); 0132 QTest::newRow("greenbytes-attwithfilenamepctandiso") << QStringLiteral("attachment; filename=\"\xe4-%41.html\"") 0133 << QByteArray( 0134 "type\tattachment\n" 0135 "filename\tä-%41.html"); 0136 QTest::newRow("greenbytes-attwithfnrawpctenclong") << "attachment; filename=\"foo-%c3%a4-%e2%82%ac.html\"" 0137 << QByteArray( 0138 "type\tattachment\n" 0139 "filename\tfoo-%c3%a4-%e2%82%ac.html"); 0140 QTest::newRow("greenbytes-attwithasciifilenamews1") << "attachment; filename =\"foo.html\"" 0141 << QByteArray( 0142 "type\tattachment\n" 0143 "filename\tfoo.html"); 0144 QTest::newRow("greenbytes-attwith2filenames") << "attachment; filename=\"foo.html\"; filename=\"bar.html\"" << QByteArray("type\tattachment"); 0145 QTest::newRow("greenbytes-attfnbrokentoken") << "attachment; filename=foo[1](2).html" << QByteArray("type\tattachment"); 0146 QTest::newRow("greenbytes-attmissingdisposition") << "filename=foo.html" << QByteArray(); 0147 QTest::newRow("greenbytes-attmissingdisposition2") << "x=y; filename=foo.html" << QByteArray(); 0148 QTest::newRow("greenbytes-attmissingdisposition3") << "\"foo; filename=bar;baz\"; filename=qux" << QByteArray(); 0149 QTest::newRow("greenbytes-attmissingdisposition4") << "filename=foo.html, filename=bar.html" << QByteArray(); 0150 QTest::newRow("greenbytes-emptydisposition") << "; filename=foo.html" << QByteArray(); 0151 QTest::newRow("greenbytes-attbrokenquotedfn") << "attachment; filename=\"foo.html\".txt" << QByteArray("type\tattachment"); 0152 QTest::newRow("greenbytes-attbrokenquotedfn2") << "attachment; filename=\"bar" << QByteArray("type\tattachment"); 0153 QTest::newRow("greenbytes-attbrokenquotedfn3") << "attachment; filename=foo\"bar;baz\"qux" << QByteArray("type\tattachment"); 0154 QTest::newRow("greenbytes-attreversed") << "filename=foo.html; attachment" << QByteArray(); 0155 QTest::newRow("greenbytes-attconfusedparam") << "attachment; xfilename=foo.html" 0156 << QByteArray( 0157 "type\tattachment\n" 0158 "xfilename\tfoo.html"); 0159 QTest::newRow("greenbytes-attabspath") << "attachment; filename=\"/foo.html\"" 0160 << QByteArray( 0161 "type\tattachment\n" 0162 "filename\tfoo.html"); 0163 #ifdef Q_OS_WIN 0164 QTest::newRow("greenbytes-attabspath") << "attachment; filename=\"\\\\foo.html\"" 0165 << QByteArray( 0166 "type\tattachment\n" 0167 "filename\tfoo.html"); 0168 #else // Q_OS_WIN 0169 QTest::newRow("greenbytes-attabspath") << "attachment; filename=\"\\\\foo.html\"" 0170 << QByteArray( 0171 "type\tattachment\n" 0172 "filename\t\\foo.html"); 0173 #endif // Q_OS_WIN 0174 QTest::newRow("greenbytes-") << "attachment; creation-date=\"Wed, 12 Feb 1997 16:29:51 -0500\"" 0175 << QByteArray( 0176 "type\tattachment\n" 0177 "creation-date\tWed, 12 Feb 1997 16:29:51 -0500"); 0178 QTest::newRow("greenbytes-") << "attachment; modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\"" 0179 << QByteArray( 0180 "type\tattachment\n" 0181 "modification-date\tWed, 12 Feb 1997 16:29:51 -0500"); 0182 QTest::newRow("greenbytes-dispext") << "foobar" << QByteArray("type\tfoobar"); 0183 QTest::newRow("greenbytes-dispextbadfn") << "attachment; example=\"filename=example.txt\"" 0184 << QByteArray( 0185 "type\tattachment\n" 0186 "example\tfilename=example.txt"); 0187 QTest::newRow("greenbytes-attwithisofn2231iso") << "attachment; filename*=iso-8859-1''foo-%E4.html" 0188 << QByteArray( 0189 "type\tattachment\n" 0190 "filename\tfoo-ä.html"); 0191 QTest::newRow("greenbytes-attwithfn2231utf8") << "attachment; filename*=UTF-8''foo-%c3%a4-%e2%82%ac.html" 0192 << QByteArray( 0193 "type\tattachment\n" 0194 "filename\tfoo-ä-€.html"); 0195 QTest::newRow("greenbytes-attwithfn2231noc") << "attachment; filename*=''foo-%c3%a4-%e2%82%ac.html" << QByteArray("type\tattachment"); 0196 // it's not filename, but "filename " 0197 QTest::newRow("greenbytes-attwithfn2231ws1") << "attachment; filename *=UTF-8''foo-%c3%a4.html" << QByteArray("type\tattachment"); 0198 QTest::newRow("greenbytes-attwithfn2231ws2") << "attachment; filename*= UTF-8''foo-%c3%a4.html" 0199 << QByteArray( 0200 "type\tattachment\n" 0201 "filename\tfoo-ä.html"); 0202 QTest::newRow("greenbytes-attwithfn2231ws3") << "attachment; filename* =UTF-8''foo-%c3%a4.html" 0203 << QByteArray( 0204 "type\tattachment\n" 0205 "filename\tfoo-ä.html"); 0206 // argument must not be enclosed in double quotes 0207 QTest::newRow("greenbytes-attwithfn2231quot") << "attachment; filename*=\"UTF-8''foo-%c3%a4.html\"" << QByteArray("type\tattachment"); 0208 QTest::newRow("greenbytes-attwithfn2231dpct") << "attachment; filename*=UTF-8''A-%2541.html" 0209 << QByteArray( 0210 "type\tattachment\n" 0211 "filename\tA-%41.html"); 0212 #ifdef Q_OS_WIN 0213 QTest::newRow("greenbytes-attwithfn2231abspathdisguised") << "attachment; filename*=UTF-8''%5cfoo.html" 0214 << QByteArray( 0215 "type\tattachment\n" 0216 "filename\tfoo.html"); 0217 #else // Q_OS_WIN 0218 QTest::newRow("greenbytes-attwithfn2231abspathdisguised") << "attachment; filename*=UTF-8''%5cfoo.html" 0219 << QByteArray( 0220 "type\tattachment\n" 0221 "filename\t\\foo.html"); 0222 #endif // Q_OS_WIN 0223 QTest::newRow("greenbytes-attfncont") << "attachment; filename*0=\"foo.\"; filename*1=\"html\"" 0224 << QByteArray( 0225 "type\tattachment\n" 0226 "filename\tfoo.html"); 0227 QTest::newRow("greenbytes-attfncontenc") << "attachment; filename*0*=UTF-8''foo-%c3%a4; filename*1=\".html\"" 0228 << QByteArray( 0229 "type\tattachment\n" 0230 "filename\tfoo-ä.html"); 0231 // no leading zeros 0232 QTest::newRow("greenbytes-attfncontlz") << "attachment; filename*0=\"foo\"; filename*01=\"bar\"" 0233 << QByteArray( 0234 "type\tattachment\n" 0235 "filename\tfoo"); 0236 QTest::newRow("greenbytes-attfncontnc") << "attachment; filename*0=\"foo\"; filename*2=\"bar\"" 0237 << QByteArray( 0238 "type\tattachment\n" 0239 "filename\tfoo"); 0240 // first element must have number 0 0241 QTest::newRow("greenbytes-attfnconts1") << "attachment; filename*1=\"foo.\"; filename*2=\"html\"" << QByteArray("type\tattachment"); 0242 // we must not rely on element ordering 0243 QTest::newRow("greenbytes-attfncontord") << "attachment; filename*1=\"bar\"; filename*0=\"foo\"" 0244 << QByteArray( 0245 "type\tattachment\n" 0246 "filename\tfoobar"); 0247 // specifying both param and param* is allowed, param* should be taken 0248 QTest::newRow("greenbytes-attfnboth") << "attachment; filename=\"foo-ae.html\"; filename*=UTF-8''foo-%c3%a4.html" 0249 << QByteArray( 0250 "type\tattachment\n" 0251 "filename\tfoo-ä.html"); 0252 // specifying both param and param* is allowed, param* should be taken 0253 QTest::newRow("greenbytes-attfnboth2") << "attachment; filename*=UTF-8''foo-%c3%a4.html; filename=\"foo-ae.html\"" 0254 << QByteArray( 0255 "type\tattachment\n" 0256 "filename\tfoo-ä.html"); 0257 QTest::newRow("greenbytes-attnewandfn") << "attachment; foobar=x; filename=\"foo.html\"" 0258 << QByteArray( 0259 "type\tattachment\n" 0260 "filename\tfoo.html\n" 0261 "foobar\tx"); 0262 // invalid argument, should be ignored 0263 QTest::newRow("greenbytes-attrfc2047token") << "attachment; filename==?ISO-8859-1?Q?foo-=E4.html?=" << QByteArray("type\tattachment"); 0264 QTest::newRow("space_before_value") << "attachment; filename= \"foo.html\"" 0265 << QByteArray( 0266 "type\tattachment\n" 0267 "filename\tfoo.html"); 0268 // no character set given but 8 bit characters 0269 QTest::newRow("8bit_in_ascii") << "attachment; filename*=''foo-%c3%a4.html" << QByteArray("type\tattachment"); 0270 // there may not be gaps in numbering 0271 QTest::newRow("continuation013") << "attachment; filename*0=\"foo.\"; filename*1=\"html\"; filename*3=\"bar\"" 0272 << QByteArray( 0273 "type\tattachment\n" 0274 "filename\tfoo.html"); 0275 // "wrong" element ordering and encoding 0276 QTest::newRow("reversed_continuation+encoding") << "attachment; filename*1=\"html\"; filename*0*=us-ascii''foo." 0277 << QByteArray( 0278 "type\tattachment\n" 0279 "filename\tfoo.html"); 0280 // unknown charset 0281 QTest::newRow("unknown_charset") << "attachment; filename*=unknown''foo" << QByteArray("type\tattachment"); 0282 // no apostrophs 0283 QTest::newRow("encoding-no-apostrophs") << "attachment; filename*=foo" << QByteArray("type\tattachment"); 0284 // only one apostroph 0285 QTest::newRow("encoding-one-apostroph") << "attachment; filename*=us-ascii'foo" << QByteArray("type\tattachment"); 0286 // duplicate filename, both should be ignored and parsing should stop 0287 QTest::newRow("duplicate-filename") << "attachment; filename=foo; filename=bar; foo=bar" << QByteArray("type\tattachment"); 0288 // garbage after closing quote, parsing should stop there 0289 QTest::newRow("garbage_after_closing_quote") << "attachment; filename*=''foo; bar=\"f\"oo; baz=foo" 0290 << QByteArray( 0291 "type\tattachment\n" 0292 "filename\tfoo"); 0293 // trailing whitespace should be ignored 0294 QTest::newRow("whitespace_after_value") << "attachment; filename=\"foo\" ; bar=baz" 0295 << QByteArray( 0296 "type\tattachment\n" 0297 "filename\tfoo\n" 0298 "bar\tbaz"); 0299 // invalid syntax for type 0300 QTest::newRow("invalid_type1") << "filename=foo.html" << QByteArray(); 0301 // invalid syntax for type 0302 QTest::newRow("invalid_type2") << "inline{; filename=\"foo\"" << QByteArray(); 0303 QTest::newRow("invalid_type3") << "foo bar; filename=\"foo\"" << QByteArray(); 0304 QTest::newRow("invalid_type4") << "foo\tbar; filename=\"foo\"" << QByteArray(); 0305 // missing closing quote, so parameter is broken 0306 QTest::newRow("no_closing_quote") << "attachment; filename=\"bar" << QByteArray("type\tattachment"); 0307 // we ignore any path given in the header and use only the filename 0308 QTest::newRow("full_path_given") << "attachment; filename=\"/etc/shadow\"" 0309 << QByteArray( 0310 "type\tattachment\n" 0311 "filename\tshadow"); 0312 // we ignore any path given in the header and use only the filename even if there is an error later 0313 QTest::newRow("full_path_and_parse_error") << "attachment; filename=\"/etc/shadow\"; foo=\"baz\"; foo=\"bar\"" 0314 << QByteArray( 0315 "type\tattachment\n" 0316 "filename\tshadow"); 0317 // control characters are forbidden in the quoted string 0318 QTest::newRow("control_character_in_value") << "attachment; filename=\"foo\003\"" << QByteArray("type\tattachment"); 0319 // duplicate keys must be ignored 0320 QTest::newRow("duplicate_with_continuation") << "attachment; filename=\"bar\"; filename*0=\"foo.\"; filename*1=\"html\"" << QByteArray("type\tattachment"); 0321 0322 // percent encoding, invalid first character 0323 QTest::newRow("percent-first-char-invalid") << "attachment; filename*=UTF-8''foo-%o5.html" << QByteArray("type\tattachment"); 0324 // percent encoding, invalid second character 0325 QTest::newRow("percent-second-char-invalid") << "attachment; filename*=UTF-8''foo-%5o.html" << QByteArray("type\tattachment"); 0326 // percent encoding, both characters invalid 0327 QTest::newRow("greenbytes-attwithfn2231nbadpct2") << "attachment; filename*=UTF-8''foo-%oo.html" << QByteArray("type\tattachment"); 0328 // percent encoding, invalid second character 0329 QTest::newRow("percent-second-char-missing") << "attachment; filename*=UTF-8''foo-%f.html" << QByteArray("type\tattachment"); 0330 // percent encoding, too short value 0331 QTest::newRow("percent-short-encoding-at-end") << "attachment; filename*=UTF-8''foo-%f" << QByteArray("type\tattachment"); 0332 } 0333 0334 #if 0 0335 // currently unclear if our behaviour is only accidentally correct 0336 // invalid syntax 0337 { "inline; attachment; filename=foo.html", 0338 "type\tinline" 0339 }, 0340 // invalid syntax 0341 { 0342 "attachment; inline; filename=foo.html", 0343 "type\tattachment" 0344 }, 0345 0346 // deactivated for now: failing due to missing implementation 0347 { 0348 "attachment; filename=\"foo-ä.html\"", 0349 "type\tattachment\n" 0350 "filename\tfoo-ä.html" 0351 }, 0352 // deactivated for now: not the same utf, no idea if the expected value is actually correct 0353 { 0354 "attachment; filename*=UTF-8''foo-a%cc%88.html", 0355 "type\tattachment\n" 0356 "filename\tfoo-ä.html" 0357 } 0358 0359 // deactivated for now: only working to missing implementation 0360 // string is not valid iso-8859-1 so filename should be ignored 0361 //"attachment; filename*=iso-8859-1''foo-%c3%a4-%e2%82%ac.html", 0362 //"type\tattachment", 0363 0364 // deactivated for now: only working to missing implementation 0365 // should not be decoded 0366 //"attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"", 0367 //"type\tattachment\n" 0368 //"filename\t=?ISO-8859-1?Q?foo-=E4.html?=", 0369 0370 }; 0371 #endif 0372 0373 void HeaderDispositionTest::runAllTests() 0374 { 0375 QFETCH(QString, header); 0376 QFETCH(QByteArray, result); 0377 0378 runTest(header, result); 0379 } 0380 0381 #include "moc_httpheaderdispositiontest.cpp"