309 QVERIFY(document.type() == QVersitDocument::VCard21Type); |
325 QVERIFY(document.type() == QVersitDocument::VCard21Type); |
310 |
326 |
311 // VERSION property with BASE64 encoded not supported value |
327 // VERSION property with BASE64 encoded not supported value |
312 property.setValue(QString::fromAscii(QByteArray("4.0").toBase64())); |
328 property.setValue(QString::fromAscii(QByteArray("4.0").toBase64())); |
313 QVERIFY(!mReaderPrivate->setVersionFromProperty(document,property)); |
329 QVERIFY(!mReaderPrivate->setVersionFromProperty(document,property)); |
314 } |
330 #endif |
315 |
331 } |
316 void tst_QVersitReader::testParseNextVersitPropertyVCard21() |
332 |
317 { |
333 void tst_QVersitReader::testParseNextVersitProperty() |
318 QVersitDocument::VersitType type = QVersitDocument::VCard21Type; |
334 { |
319 |
335 #ifndef QT_BUILD_INTERNAL |
320 // Test a valid vCard 2.1 with properties having separate handling: |
336 QSKIP("Testing private API", SkipSingle); |
321 // AGENT property, ENCODING parameters (BASE64 and QUOTED-PRINTABLE) and CHARSET parameter |
337 #else |
322 QTextCodec* codec = QTextCodec::codecForName("UTF-16BE"); |
338 QFETCH(QVersitDocument::VersitType, documentType); |
323 QByteArray vCard("Begin:vcard\r\n"); |
339 QFETCH(QByteArray, input); |
324 vCard.append("VERSION:2.1\r\n"); |
340 QFETCH(QVersitProperty, expectedProperty); |
325 vCard.append("FN:John\r\n"); |
341 |
326 // "NOTE:\;\,\:\\" |
342 QBuffer buffer(&input); |
327 vCard.append("NOTE:\\;\\,\\:\\\\\r\n"); |
|
328 // "N:foo\;bar;foo\,bar;foo\:bar;foo\\bar;foo\\\;bar" |
|
329 vCard.append("N:foo\\;bar;foo\\,bar;foo\\:bar;foo\\\\bar;foo\\\\\\;bar\r\n"); |
|
330 // missing structured value |
|
331 vCard.append("ADR:\r\n"); |
|
332 // "NICKNAME:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar" |
|
333 vCard.append("NICKNAME:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n"); |
|
334 // "CATEGORIES:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar" |
|
335 vCard.append("CATEGORIES:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n"); |
|
336 vCard.append("ORG;CHARSET=UTF-8:"); |
|
337 vCard.append(KATAKANA_NOKIA); |
|
338 vCard.append("\r\n"); |
|
339 // "NOKIA" in Katakana, UTF-8 encoded, then base-64 encoded: |
|
340 vCard.append("NOTE;ENCODING=BASE64;CHARSET=UTF-8:"); |
|
341 vCard.append(KATAKANA_NOKIA.toBase64()); |
|
342 vCard.append("\r\n"); |
|
343 // The value here is "UXQgaXMgZ3JlYXQh", which is the base64 encoding of "Qt is great!". |
|
344 vCard.append("PHOTO;ENCODING=BASE64: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n"); |
|
345 // Again, but without the explicit "ENCODING" parameter |
|
346 vCard.append("PHOTO;BASE64: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n"); |
|
347 vCard.append("HOME.Springfield.EMAIL;Encoding=Quoted-Printable:john.citizen=40exam=\r\nple.com\r\n"); |
|
348 vCard.append("EMAIL;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-16BE:"); |
|
349 vCard.append(codec->fromUnicode(QLatin1String("john.citizen=40exam=\r\nple.com"))); |
|
350 vCard.append("\r\n"); |
|
351 vCard.append("AGENT:\r\nBEGIN:VCARD\r\nFN:Jenny\r\nEND:VCARD\r\n\r\n"); |
|
352 vCard.append("End:VCARD\r\n"); |
|
353 QBuffer buffer(&vCard); |
|
354 buffer.open(QIODevice::ReadOnly); |
343 buffer.open(QIODevice::ReadOnly); |
355 LineReader lineReader(&buffer, mAsciiCodec); |
344 LineReader lineReader(&buffer, mAsciiCodec); |
356 |
345 QVersitProperty property = mReaderPrivate->parseNextVersitProperty(documentType, lineReader); |
357 QVersitProperty property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
346 if (property != expectedProperty) { |
358 QCOMPARE(property.name(),QString::fromAscii("BEGIN")); |
347 // compare each part of the property separately for easier debugging |
359 QCOMPARE(property.value(),QString::fromAscii("vcard")); |
348 QCOMPARE(property.groups(), expectedProperty.groups()); |
360 |
349 QCOMPARE(property.name(), expectedProperty.name()); |
361 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
350 QCOMPARE(property.valueType(), expectedProperty.valueType()); |
362 QCOMPARE(property.name(),QString::fromAscii("VERSION")); |
351 |
363 QCOMPARE(property.value(),QString::fromAscii("2.1")); |
352 // QVariant doesn't support == on QVersitDocuments - do it manually |
364 |
353 if (property.variantValue().userType() == qMetaTypeId<QVersitDocument>()) { |
365 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
354 QVERIFY(expectedProperty.variantValue().userType() == qMetaTypeId<QVersitDocument>()); |
366 QCOMPARE(property.name(),QString::fromAscii("FN")); |
355 QCOMPARE(property.value<QVersitDocument>(), expectedProperty.value<QVersitDocument>()); |
367 QCOMPARE(property.value(),QString::fromAscii("John")); |
356 } |
368 |
357 else |
369 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
358 QCOMPARE(property.variantValue(), expectedProperty.variantValue()); |
370 QCOMPARE(property.name(),QString::fromAscii("NOTE")); |
359 |
371 // Do not Unescape semicolons, commas, colons and backlashes |
360 // Don't check parameters because the reader can add random parameters of its own (like CHARSET) |
372 // "\;\,\:\\" |
361 // QCOMPARE(property.parameters(), expectedProperty.parameters()); |
373 QCOMPARE(property.value(),QString::fromAscii("\\;\\,\\:\\\\")); |
362 } |
374 |
363 #endif |
375 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
364 } |
376 QCOMPARE(property.name(),QString::fromAscii("N")); |
365 |
377 QCOMPARE(property.valueType(), QVersitProperty::CompoundType); |
366 void tst_QVersitReader::testParseNextVersitProperty_data() |
378 QCOMPARE(property.variantValue().type(), QVariant::StringList); |
367 { |
379 QStringList components = property.value<QStringList>(); |
368 #ifdef QT_BUILD_INTERNAL |
380 QCOMPARE(components.size(), 5); |
369 QTest::addColumn<QVersitDocument::VersitType>("documentType"); |
381 QCOMPARE(components.at(0), QLatin1String("foo;bar")); |
370 QTest::addColumn<QByteArray>("input"); |
382 QCOMPARE(components.at(1), QLatin1String("foo\\,bar")); |
371 QTest::addColumn<QVersitProperty>("expectedProperty"); |
383 QCOMPARE(components.at(2), QLatin1String("foo\\:bar")); |
372 |
384 QCOMPARE(components.at(3), QLatin1String("foo\\\\bar")); |
373 { |
385 QCOMPARE(components.at(4), QLatin1String("foo\\\\;bar")); |
374 QVersitProperty expectedProperty; |
386 |
375 expectedProperty.setName(QLatin1String("BEGIN")); |
387 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
376 expectedProperty.setValue(QLatin1String("vcard")); |
388 QCOMPARE(property.name(),QString::fromAscii("ADR")); |
377 QTest::newRow("begin") |
389 QCOMPARE(property.valueType(), QVersitProperty::CompoundType); |
378 << QVersitDocument::VCard21Type |
390 QCOMPARE(property.variantValue().type(), QVariant::StringList); |
379 << QByteArray("Begin:vcard\r\n") |
391 components = property.value<QStringList>(); |
380 << expectedProperty; |
392 QCOMPARE(components.size(), 1); |
381 } |
393 QVERIFY(components.at(0).isEmpty()); |
382 |
394 |
383 { |
395 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
384 QVersitProperty expectedProperty; |
396 QCOMPARE(property.name(),QString::fromAscii("NICKNAME")); |
385 expectedProperty.setName(QLatin1String("VERSION")); |
397 QCOMPARE(property.valueType(), QVersitProperty::ListType); |
386 expectedProperty.setValue(QLatin1String("2.1")); |
398 QCOMPARE(property.variantValue().type(), QVariant::StringList); |
387 expectedProperty.setValueType(QVersitProperty::PlainType); |
399 components = property.value<QStringList>(); |
388 QTest::newRow("version") |
400 QCOMPARE(components.size(), 5); |
389 << QVersitDocument::VCard21Type |
401 QCOMPARE(components.at(0), QLatin1String("foo\\;bar")); |
390 << QByteArray("VERSION:2.1\r\n") |
402 QCOMPARE(components.at(1), QLatin1String("foo,bar")); |
391 << expectedProperty; |
403 QCOMPARE(components.at(2), QLatin1String("foo\\:bar")); |
392 } |
404 QCOMPARE(components.at(3), QLatin1String("foo\\\\bar")); |
393 |
405 QCOMPARE(components.at(4), QLatin1String("foo\\\\,bar")); |
394 { |
406 |
395 QVersitProperty expectedProperty; |
407 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
396 expectedProperty.setName(QLatin1String("FN")); |
408 QCOMPARE(property.name(),QString::fromAscii("CATEGORIES")); |
397 expectedProperty.setValue(QLatin1String("John")); |
409 QCOMPARE(property.valueType(), QVersitProperty::ListType); |
398 expectedProperty.setValueType(QVersitProperty::PlainType); |
410 QCOMPARE(property.variantValue().type(), QVariant::StringList); |
399 QTest::newRow("fn") |
411 components = property.value<QStringList>(); |
400 << QVersitDocument::VCard21Type |
412 QCOMPARE(components.size(), 5); |
401 << QByteArray("FN:John\r\n") |
413 QCOMPARE(components.at(0), QLatin1String("foo\\;bar")); |
402 << expectedProperty; |
414 QCOMPARE(components.at(1), QLatin1String("foo,bar")); |
403 } |
415 QCOMPARE(components.at(2), QLatin1String("foo\\:bar")); |
404 |
416 QCOMPARE(components.at(3), QLatin1String("foo\\\\bar")); |
405 { |
417 QCOMPARE(components.at(4), QLatin1String("foo\\\\,bar")); |
406 // "NOTE:\;\,\:\\" |
418 |
407 QVersitProperty expectedProperty; |
419 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
408 expectedProperty.setName(QLatin1String("NOTE")); |
420 QCOMPARE(property.name(),QString::fromAscii("ORG")); |
409 expectedProperty.setValue(QLatin1String("\\;\\,\\:\\\\")); |
421 QCOMPARE(property.value(),QString::fromUtf8(KATAKANA_NOKIA)); |
410 expectedProperty.setValueType(QVersitProperty::PlainType); |
422 |
411 QTest::newRow("vcard21 note") |
423 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
412 << QVersitDocument::VCard21Type |
424 QCOMPARE(property.name(),QString::fromAscii("NOTE")); |
413 << QByteArray("NOTE:\\;\\,\\:\\\\\r\n") |
425 QCOMPARE(property.value(),QString::fromUtf8(KATAKANA_NOKIA)); |
414 << expectedProperty; |
426 |
415 |
427 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
416 expectedProperty.setValue(QLatin1String(";,:\\")); |
428 QCOMPARE(property.name(),QString::fromAscii("PHOTO")); |
417 QTest::newRow("vcard30 note") |
429 // Linear whitespaces (SPACEs and TABs) removed from the value and base64 decoded: |
418 << QVersitDocument::VCard30Type |
430 QCOMPARE(property.variantValue().type(), QVariant::ByteArray); |
419 << QByteArray("NOTE:\\;\\,\\:\\\\\r\n") |
431 QCOMPARE(property.value<QByteArray>(), QByteArray("Qt is great!")); |
420 << expectedProperty; |
432 // Ensure that base-64 encoded strings can be retrieved as strings. |
421 } |
433 QCOMPARE(property.value(), QLatin1String("Qt is great!")); |
422 |
434 |
423 { |
435 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
424 // "N:foo\;bar;foo\,bar;foo\:bar;foo\\bar;foo\\\;bar" |
436 QCOMPARE(property.name(),QString::fromAscii("PHOTO")); |
425 QVersitProperty expectedProperty; |
437 QCOMPARE(property.variantValue().type(), QVariant::ByteArray); |
426 expectedProperty.setName(QLatin1String("N")); |
438 QCOMPARE(property.value<QByteArray>(), QByteArray("Qt is great!")); |
427 QStringList components; |
439 QCOMPARE(property.value(), QLatin1String("Qt is great!")); |
428 components << QLatin1String("foo;bar") |
440 |
429 << QLatin1String("foo\\,bar") |
441 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
430 << QLatin1String("foo\\:bar") |
442 QStringList propertyGroup(QString::fromAscii("HOME")); |
431 << QLatin1String("foo\\\\bar") |
443 propertyGroup.append(QString::fromAscii("Springfield")); |
432 << QLatin1String("foo\\\\;bar"); |
444 QCOMPARE(property.groups(),propertyGroup); |
433 expectedProperty.setValue(components); |
445 QCOMPARE(property.name(),QString::fromAscii("EMAIL")); |
434 expectedProperty.setValueType(QVersitProperty::CompoundType); |
446 QCOMPARE(0,property.parameters().count()); |
435 QTest::newRow("vcard21 n") |
447 QCOMPARE(property.value(),QString::fromAscii("john.citizen@example.com")); |
436 << QVersitDocument::VCard21Type |
448 |
437 << QByteArray("N:foo\\;bar;foo\\,bar;foo\\:bar;foo\\\\bar;foo\\\\\\;bar\r\n") |
449 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
438 << expectedProperty; |
450 QCOMPARE(property.name(),QString::fromAscii("EMAIL")); |
439 |
451 // The encoding and charset parameters should be stripped by the reader. |
440 components.clear(); |
452 QCOMPARE(property.parameters().count(), 0); |
441 components << QLatin1String("foo;bar") |
453 QCOMPARE(property.value(),QString::fromAscii("john.citizen@example.com")); |
442 << QLatin1String("foo,bar") |
454 |
443 << QLatin1String("foo:bar") |
455 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
444 << QLatin1String("foo\\bar") |
456 QCOMPARE(property.name(),QString::fromAscii("AGENT")); |
445 << QLatin1String("foo\\;bar"); |
457 QCOMPARE(property.value(),QString()); |
446 expectedProperty.setValue(components); |
458 QVERIFY(property.variantValue().userType() == qMetaTypeId<QVersitDocument>()); |
447 QTest::newRow("vcard30 n") |
459 QCOMPARE(property.value<QVersitDocument>().properties().count(), 1); |
448 << QVersitDocument::VCard30Type |
460 |
449 << QByteArray("N:foo\\;bar;foo\\,bar;foo\\:bar;foo\\\\bar;foo\\\\\\;bar\r\n") |
461 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
450 << expectedProperty; |
462 QCOMPARE(property.name(),QString::fromAscii("END")); |
451 } |
463 QCOMPARE(property.value(),QString::fromAscii("VCARD")); |
452 |
464 |
453 { |
465 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
454 QVersitProperty expectedProperty; |
466 QCOMPARE(property.name(),QString()); |
455 expectedProperty.setName(QLatin1String("ADR")); |
467 QCOMPARE(property.value(),QString()); |
456 expectedProperty.setValue(QStringList(QString())); |
468 |
457 expectedProperty.setValueType(QVersitProperty::CompoundType); |
469 // Simulate a situation where the document nesting level is exceeded |
458 QTest::newRow("empty structured") |
470 // In practice this would mean a big number of nested AGENT properties |
459 << QVersitDocument::VCard21Type |
471 mReaderPrivate->mDocumentNestingLevel = 20; |
460 << QByteArray("ADR:\r\n") |
472 QByteArray agentProperty("AGENT:BEGIN:VCARD\r\nN:Jenny\r\nEND:VCARD\r\n\r\n"); |
461 << expectedProperty; |
473 buffer.close(); |
462 } |
474 buffer.setData(agentProperty); |
463 |
475 buffer.open(QIODevice::ReadOnly); |
464 { |
476 LineReader agentLineReader(&buffer, mAsciiCodec); |
465 QVersitProperty expectedProperty; |
477 |
466 expectedProperty.setName(QLatin1String("X-CHILDREN")); |
478 property = mReaderPrivate->parseNextVersitProperty(type, agentLineReader); |
467 expectedProperty.setValue(QStringList() << QLatin1String("Child1") << QLatin1String("Child2")); |
479 QVERIFY(property.isEmpty()); |
468 expectedProperty.setValueType(QVersitProperty::ListType); |
480 } |
469 QTest::newRow("children") |
481 |
470 << QVersitDocument::VCard21Type |
482 void tst_QVersitReader::testParseNextVersitPropertyVCard30() |
471 << QByteArray("X-CHILDREN:Child1,Child2\r\n") |
483 { |
472 << expectedProperty; |
484 QVersitDocument::VersitType type = QVersitDocument::VCard30Type; |
473 } |
485 |
474 |
486 // Test a valid vCard 3.0 with properties having separate handling: |
475 { |
487 // AGENT property and some other property |
476 // "NICKNAME:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar" |
488 QByteArray vCard("Begin:vcard\r\n"); |
477 QVersitProperty expectedProperty; |
489 vCard.append("VERSION:3.0\r\n"); |
478 expectedProperty.setName(QLatin1String("NICKNAME")); |
490 vCard.append("FN:John\r\n"); |
479 QStringList components; |
491 // "NOTE:\;\,\:\\" |
480 components << QLatin1String("foo\\;bar") |
492 vCard.append("NOTE:\\;\\,\\:\\\\\r\n"); |
481 << QLatin1String("foo,bar") |
493 // "N:foo\;bar;foo\,bar;foo\:bar;foo\\bar;foo\\\;bar" |
482 << QLatin1String("foo\\:bar") |
494 vCard.append("N:foo\\;bar;foo\\,bar;foo\\:bar;foo\\\\bar;foo\\\\\\;bar\r\n"); |
483 << QLatin1String("foo\\\\bar") |
495 // "NICKNAME:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar" |
484 << QLatin1String("foo\\\\,bar"); |
496 vCard.append("NICKNAME:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n"); |
485 expectedProperty.setValue(components); |
497 // "CATEGORIES:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar" |
486 expectedProperty.setValueType(QVersitProperty::ListType); |
498 vCard.append("CATEGORIES:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n"); |
487 QTest::newRow("vcard21 nickname") |
499 // "CATEGORIES:foobar\\,foobar\\\\,foo\\\\\,bar" |
488 << QVersitDocument::VCard21Type |
500 vCard.append("CATEGORIES:foobar\\\\,foobar\\\\\\\\,foo\\\\\\\\\\,bar\r\n"); |
489 << QByteArray("NICKNAME:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n") |
501 vCard.append("ORG;CHARSET=UTF-8:"); |
490 << expectedProperty; |
502 vCard.append(KATAKANA_NOKIA); |
491 |
503 vCard.append("\r\n"); |
492 components.clear(); |
504 // "NOKIA" in Katakana, UTF-8 encoded, then base-64 encoded: |
493 components << QLatin1String("foo;bar") |
505 vCard.append("NOTE;ENCODING=B;CHARSET=UTF-8:"); |
494 << QLatin1String("foo,bar") |
506 vCard.append(KATAKANA_NOKIA.toBase64()); |
495 << QLatin1String("foo:bar") |
507 vCard.append("\r\n"); |
496 << QLatin1String("foo\\bar") |
508 vCard.append("TEL;TYPE=PREF;HOME:123\r\n"); |
497 << QLatin1String("foo\\,bar"); |
509 // The value here is "UXQgaXMgZ3JlYXQh", which is the base64 encoding of "Qt is great!". |
498 expectedProperty.setValue(components); |
510 vCard.append("PHOTO;ENCODING=B:UXQgaXMgZ3JlYXQh\r\n"); |
499 QTest::newRow("vcard30 nickname") |
511 // Again, but without the explicity "ENCODING" parameter |
500 << QVersitDocument::VCard30Type |
512 vCard.append("PHOTO;B:UXQgaXMgZ3JlYXQh\r\n"); |
501 << QByteArray("NICKNAME:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n") |
513 vCard.append("EMAIL:john.citizen@example.com\r\n"); |
502 << expectedProperty; |
514 vCard.append("AGENT:BEGIN:VCARD\\nFN:Jenny\\nEND:VCARD\\n\r\n"); |
503 } |
515 vCard.append("End:VCARD\r\n"); |
504 |
516 QBuffer buffer(&vCard); |
505 { |
517 buffer.open(QIODevice::ReadOnly); |
506 // "CATEGORIES:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar" |
518 LineReader lineReader(&buffer, mAsciiCodec); |
507 QVersitProperty expectedProperty; |
519 |
508 expectedProperty.setName(QLatin1String("CATEGORIES")); |
520 QVersitProperty property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
509 QStringList components; |
521 QCOMPARE(property.name(),QString::fromAscii("BEGIN")); |
510 components << QLatin1String("foo\\;bar") |
522 QCOMPARE(property.value(),QString::fromAscii("vcard")); |
511 << QLatin1String("foo,bar") |
523 |
512 << QLatin1String("foo\\:bar") |
524 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
513 << QLatin1String("foo\\\\bar") |
525 QCOMPARE(property.name(),QString::fromAscii("VERSION")); |
514 << QLatin1String("foo\\\\,bar"); |
526 QCOMPARE(property.value(),QString::fromAscii("3.0")); |
515 expectedProperty.setValue(components); |
527 |
516 expectedProperty.setValueType(QVersitProperty::ListType); |
528 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
517 QTest::newRow("vcard21 categories") |
529 QCOMPARE(property.name(),QString::fromAscii("FN")); |
518 << QVersitDocument::VCard21Type |
530 QCOMPARE(property.value(),QString::fromAscii("John")); |
519 << QByteArray("CATEGORIES:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n") |
531 |
520 << expectedProperty; |
532 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
521 |
533 QCOMPARE(property.name(),QString::fromAscii("NOTE")); |
522 components.clear(); |
534 QCOMPARE(property.valueType(), QVersitProperty::PlainType); |
523 components << QLatin1String("foo;bar") |
535 QCOMPARE(property.variantValue().type(), QVariant::String); |
524 << QLatin1String("foo,bar") |
536 // Unescape semicolons, commas, colons and backlashes |
525 << QLatin1String("foo:bar") |
537 QCOMPARE(property.value(), QString::fromAscii(";,:\\")); |
526 << QLatin1String("foo\\bar") |
538 |
527 << QLatin1String("foo\\,bar"); |
539 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
528 expectedProperty.setValue(components); |
540 QCOMPARE(property.name(),QString::fromAscii("N")); |
529 QTest::newRow("vcard30 categories") |
541 QCOMPARE(property.valueType(), QVersitProperty::CompoundType); |
530 << QVersitDocument::VCard30Type |
542 QCOMPARE(property.variantValue().type(), QVariant::StringList); |
531 << QByteArray("CATEGORIES:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n") |
543 QStringList components = property.value<QStringList>(); |
532 << expectedProperty; |
544 QCOMPARE(components.size(), 5); |
533 |
545 QCOMPARE(components.at(0), QLatin1String("foo;bar")); |
534 // "CATEGORIES:foobar\\,foobar\\\\,foo\\\\\,bar" |
546 QCOMPARE(components.at(1), QLatin1String("foo,bar")); |
535 components.clear(); |
547 QCOMPARE(components.at(2), QLatin1String("foo:bar")); |
536 components << QLatin1String("foobar\\") |
548 QCOMPARE(components.at(3), QLatin1String("foo\\bar")); |
537 << QLatin1String("foobar\\\\") |
549 QCOMPARE(components.at(4), QLatin1String("foo\\;bar")); |
538 << QLatin1String("foo\\\\,bar"); |
550 |
539 expectedProperty.setValue(components); |
551 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
540 QTest::newRow("vcard30 unescaping") |
552 QCOMPARE(property.name(),QString::fromAscii("NICKNAME")); |
541 << QVersitDocument::VCard30Type |
553 QCOMPARE(property.valueType(), QVersitProperty::ListType); |
542 << QByteArray("CATEGORIES:foobar\\\\,foobar\\\\\\\\,foo\\\\\\\\\\,bar") |
554 QCOMPARE(property.variantValue().type(), QVariant::StringList); |
543 << expectedProperty; |
555 components = property.value<QStringList>(); |
544 } |
556 QCOMPARE(components.size(), 5); |
545 |
557 QCOMPARE(components.at(0), QLatin1String("foo;bar")); |
546 { |
558 QCOMPARE(components.at(1), QLatin1String("foo,bar")); |
547 QVersitProperty expectedProperty; |
559 QCOMPARE(components.at(2), QLatin1String("foo:bar")); |
548 expectedProperty.setName(QLatin1String("ORG")); |
560 QCOMPARE(components.at(3), QLatin1String("foo\\bar")); |
549 expectedProperty.setValue(QString::fromUtf8(KATAKANA_NOKIA)); |
561 QCOMPARE(components.at(4), QLatin1String("foo\\,bar")); |
550 expectedProperty.setValueType(QVersitProperty::CompoundType); |
562 |
551 QTest::newRow("org utf8") |
563 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
552 << QVersitDocument::VCard21Type |
564 QCOMPARE(property.name(),QString::fromAscii("CATEGORIES")); |
553 << QByteArray("ORG;CHARSET=UTF-8:" + KATAKANA_NOKIA + "\r\n") |
565 QCOMPARE(property.valueType(), QVersitProperty::ListType); |
554 << expectedProperty; |
566 QCOMPARE(property.variantValue().type(), QVariant::StringList); |
555 } |
567 components = property.value<QStringList>(); |
556 |
568 QCOMPARE(components.size(), 5); |
557 { |
569 QCOMPARE(components.at(0), QLatin1String("foo;bar")); |
558 QVersitProperty expectedProperty; |
570 QCOMPARE(components.at(1), QLatin1String("foo,bar")); |
559 expectedProperty.setName(QLatin1String("PHOTO")); |
571 QCOMPARE(components.at(2), QLatin1String("foo:bar")); |
560 expectedProperty.setValue(QLatin1String("Qt is great!")); |
572 QCOMPARE(components.at(3), QLatin1String("foo\\bar")); |
561 expectedProperty.setValueType(QVersitProperty::BinaryType); |
573 QCOMPARE(components.at(4), QLatin1String("foo\\,bar")); |
562 QTest::newRow("vcard21 photo1") |
574 |
563 << QVersitDocument::VCard21Type |
575 // "CATEGORIES:foobar\\,foobar\\\\,foo\\\\\,bar" |
564 << QByteArray("PHOTO;ENCODING=BASE64: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n") |
576 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
565 << expectedProperty; |
577 QCOMPARE(property.name(),QString::fromAscii("CATEGORIES")); |
566 |
578 QCOMPARE(property.valueType(), QVersitProperty::ListType); |
567 QTest::newRow("vcard30 photo1") |
579 QCOMPARE(property.variantValue().type(), QVariant::StringList); |
568 << QVersitDocument::VCard30Type |
580 components = property.value<QStringList>(); |
569 << QByteArray("PHOTO;ENCODING=B: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n") |
581 QCOMPARE(components.size(), 3); |
570 << expectedProperty; |
582 QCOMPARE(components.at(0), QLatin1String("foobar\\")); |
571 } |
583 QCOMPARE(components.at(1), QLatin1String("foobar\\\\")); |
572 |
584 QCOMPARE(components.at(2), QLatin1String("foo\\\\,bar")); |
573 // Again, but without the explicit "ENCODING" parameter |
585 |
574 { |
586 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
575 QVersitProperty expectedProperty; |
587 QCOMPARE(property.name(),QString::fromAscii("ORG")); |
576 expectedProperty.setName(QLatin1String("PHOTO")); |
588 QCOMPARE(property.value(),QString::fromUtf8(KATAKANA_NOKIA)); |
577 expectedProperty.setValue(QLatin1String("Qt is great!")); |
589 |
578 expectedProperty.setValueType(QVersitProperty::BinaryType); |
590 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
579 QTest::newRow("photo2") |
591 QCOMPARE(property.name(),QString::fromAscii("NOTE")); |
580 << QVersitDocument::VCard21Type |
592 QCOMPARE(property.value(),QString::fromUtf8(KATAKANA_NOKIA)); |
581 << QByteArray("PHOTO;BASE64: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n") |
593 |
582 << expectedProperty; |
594 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
583 |
595 QCOMPARE(property.name(),QString::fromAscii("TEL")); |
584 QTest::newRow("photo2") |
596 QCOMPARE(property.value(),QString::fromAscii("123")); |
585 << QVersitDocument::VCard30Type |
597 QCOMPARE(property.parameters().count(), 2); |
586 << QByteArray("PHOTO;B: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n") |
598 |
587 << expectedProperty; |
599 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
588 } |
600 QCOMPARE(property.name(),QString::fromAscii("PHOTO")); |
589 |
601 QCOMPARE(property.variantValue().type(), QVariant::ByteArray); |
590 { |
602 QCOMPARE(property.value<QByteArray>(), QByteArray("Qt is great!")); |
591 QVersitProperty expectedProperty; |
603 // Ensure that base-64 encoded strings can be retrieved as strings. |
592 expectedProperty.setGroups(QStringList() << QLatin1String("HOME") << QLatin1String("Springfield")); |
604 QCOMPARE(property.value(), QLatin1String("Qt is great!")); |
593 expectedProperty.setName(QLatin1String("EMAIL")); |
605 |
594 expectedProperty.setValue(QLatin1String("john.citizen@example.com")); |
606 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
595 expectedProperty.setValueType(QVersitProperty::PlainType); |
607 QCOMPARE(property.name(),QString::fromAscii("PHOTO")); |
596 QTest::newRow("email qp") |
608 QCOMPARE(property.variantValue().type(), QVariant::ByteArray); |
597 << QVersitDocument::VCard21Type |
609 QCOMPARE(property.value<QByteArray>(), QByteArray("Qt is great!")); |
598 << QByteArray("HOME.Springfield.EMAIL;Encoding=Quoted-Printable:john.citizen=40exam=\r\nple.com\r\n") |
610 QCOMPARE(property.value(), QLatin1String("Qt is great!")); |
599 << expectedProperty; |
611 |
600 } |
612 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
601 |
613 QCOMPARE(property.name(),QString::fromAscii("EMAIL")); |
602 { |
614 QCOMPARE(0,property.parameters().count()); |
603 QVersitProperty expectedProperty; |
615 QCOMPARE(property.value(),QString::fromAscii("john.citizen@example.com")); |
604 expectedProperty.setName(QLatin1String("EMAIL")); |
616 |
605 expectedProperty.setValue(QLatin1String("john.citizen@example.com")); |
617 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
606 expectedProperty.setValueType(QVersitProperty::PlainType); |
618 QCOMPARE(property.name(),QString::fromAscii("AGENT")); |
607 QTest::newRow("email qp utf16") |
619 QVERIFY(property.variantValue().userType() == qMetaTypeId<QVersitDocument>()); |
608 << QVersitDocument::VCard21Type |
620 QCOMPARE(property.value<QVersitDocument>().properties().count(), 1); |
609 << QByteArray("EMAIL;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-16BE:" + QTextCodec::codecForName("UTF-16BE")->fromUnicode(QLatin1String("john.citizen=40exam=\r\nple.com")) + "\r\n") |
621 |
610 << expectedProperty; |
622 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
611 } |
623 QCOMPARE(property.name(),QString::fromAscii("END")); |
612 |
624 QCOMPARE(property.value(),QString::fromAscii("VCARD")); |
613 { |
625 |
614 QVersitDocument subDocument; |
626 property = mReaderPrivate->parseNextVersitProperty(type, lineReader); |
615 subDocument.setType(QVersitDocument::VCard30Type); |
627 QCOMPARE(property.name(),QString()); |
616 QVersitProperty subProperty; |
628 QCOMPARE(property.value(),QString()); |
617 subProperty.setName(QLatin1String("FN")); |
629 |
618 subProperty.setValue(QLatin1String("Jenny")); |
630 // Simulate a situation where the document nesting level is exceeded |
619 subDocument.addProperty(subProperty); |
631 // In practice this would mean a big number of nested AGENT properties |
620 |
632 mReaderPrivate->mDocumentNestingLevel = 20; |
621 QVersitProperty expectedProperty; |
633 QByteArray agentProperty("AGENT:BEGIN\\:VCARD\\nFN\\:Jenny\\nEND\\:VCARD\\n\r\n"); |
622 expectedProperty.setName(QLatin1String("AGENT")); |
634 buffer.close(); |
623 expectedProperty.setValue(QVariant::fromValue(subDocument)); |
635 buffer.setData(agentProperty); |
624 expectedProperty.setValueType(QVersitProperty::VersitDocumentType); |
636 buffer.open(QIODevice::ReadOnly); |
625 QTest::newRow("agent") |
637 LineReader agentLineReader(&buffer, mAsciiCodec); |
626 << QVersitDocument::VCard21Type |
638 |
627 << QByteArray("AGENT:\r\nBEGIN:VCARD\r\nFN:Jenny\r\nEND:VCARD\r\n\r\n") |
639 property = mReaderPrivate->parseNextVersitProperty(type, agentLineReader); |
628 << expectedProperty; |
640 QVERIFY(property.isEmpty()); |
629 } |
|
630 #endif |
641 } |
631 } |
642 |
632 |
643 void tst_QVersitReader::testParseVersitDocument() |
633 void tst_QVersitReader::testParseVersitDocument() |
644 { |
634 { |
|
635 #ifndef QT_BUILD_INTERNAL |
|
636 QSKIP("Testing private API", SkipSingle); |
|
637 #else |
645 QFETCH(QByteArray, vCard); |
638 QFETCH(QByteArray, vCard); |
646 QFETCH(bool, expectedSuccess); |
639 QFETCH(bool, expectedSuccess); |
647 QFETCH(int, expectedProperties); |
640 QFETCH(int, expectedProperties); |
648 |
641 |
649 QBuffer buffer(&vCard); |
642 QBuffer buffer(&vCard); |