From 7a40f4354b32809af3d0cfd6e3af0eda02ab0e0a Mon Sep 17 00:00:00 2001
From: friendica
Date: Sat, 12 May 2012 17:57:41 -0700
Subject: some important stuff we'll need
---
.../tests/HTMLPurifier/AttrCollectionsTest.php | 134 ++++
.../HTMLPurifier/AttrDef/CSS/AlphaValueTest.php | 28 +
.../AttrDef/CSS/BackgroundPositionTest.php | 68 ++
.../HTMLPurifier/AttrDef/CSS/BackgroundTest.php | 23 +
.../tests/HTMLPurifier/AttrDef/CSS/BorderTest.php | 21 +
.../tests/HTMLPurifier/AttrDef/CSS/ColorTest.php | 41 ++
.../HTMLPurifier/AttrDef/CSS/CompositeTest.php | 81 +++
.../tests/HTMLPurifier/AttrDef/CSS/FilterTest.php | 29 +
.../HTMLPurifier/AttrDef/CSS/FontFamilyTest.php | 52 ++
.../tests/HTMLPurifier/AttrDef/CSS/FontTest.php | 34 +
.../AttrDef/CSS/ImportantDecoratorTest.php | 49 ++
.../tests/HTMLPurifier/AttrDef/CSS/LengthTest.php | 48 ++
.../HTMLPurifier/AttrDef/CSS/ListStyleTest.php | 35 +
.../HTMLPurifier/AttrDef/CSS/MultipleTest.php | 28 +
.../tests/HTMLPurifier/AttrDef/CSS/NumberTest.php | 51 ++
.../HTMLPurifier/AttrDef/CSS/PercentageTest.php | 24 +
.../AttrDef/CSS/TextDecorationTest.php | 27 +
.../tests/HTMLPurifier/AttrDef/CSS/URITest.php | 29 +
.../tests/HTMLPurifier/AttrDef/CSSTest.php | 164 +++++
.../tests/HTMLPurifier/AttrDef/EnumTest.php | 37 +
.../tests/HTMLPurifier/AttrDef/HTML/BoolTest.php | 22 +
.../tests/HTMLPurifier/AttrDef/HTML/ClassTest.php | 48 ++
.../tests/HTMLPurifier/AttrDef/HTML/ColorTest.php | 20 +
.../HTMLPurifier/AttrDef/HTML/FrameTargetTest.php | 28 +
.../tests/HTMLPurifier/AttrDef/HTML/IDTest.php | 108 +++
.../tests/HTMLPurifier/AttrDef/HTML/LengthTest.php | 32 +
.../HTMLPurifier/AttrDef/HTML/LinkTypesTest.php | 21 +
.../HTMLPurifier/AttrDef/HTML/MultiLengthTest.php | 28 +
.../HTMLPurifier/AttrDef/HTML/NmtokensTest.php | 35 +
.../tests/HTMLPurifier/AttrDef/HTML/PixelsTest.php | 45 ++
.../tests/HTMLPurifier/AttrDef/IntegerTest.php | 61 ++
.../tests/HTMLPurifier/AttrDef/LangTest.php | 85 +++
.../tests/HTMLPurifier/AttrDef/SwitchTest.php | 34 +
.../tests/HTMLPurifier/AttrDef/TextTest.php | 17 +
.../AttrDef/URI/Email/SimpleCheckTest.php | 13 +
.../HTMLPurifier/AttrDef/URI/EmailHarness.php | 31 +
.../tests/HTMLPurifier/AttrDef/URI/HostTest.php | 53 ++
.../tests/HTMLPurifier/AttrDef/URI/IPv4Test.php | 25 +
.../tests/HTMLPurifier/AttrDef/URI/IPv6Test.php | 43 ++
.../tests/HTMLPurifier/AttrDef/URITest.php | 146 ++++
.../tests/HTMLPurifier/AttrDefHarness.php | 27 +
.../tests/HTMLPurifier/AttrDefTest.php | 32 +
.../HTMLPurifier/AttrTransform/BackgroundTest.php | 40 ++
.../HTMLPurifier/AttrTransform/BdoDirTest.php | 30 +
.../HTMLPurifier/AttrTransform/BgColorTest.php | 44 ++
.../HTMLPurifier/AttrTransform/BoolToCSSTest.php | 38 ++
.../HTMLPurifier/AttrTransform/BorderTest.php | 38 ++
.../HTMLPurifier/AttrTransform/EnumToCSSTest.php | 73 ++
.../HTMLPurifier/AttrTransform/ImgRequiredTest.php | 55 ++
.../HTMLPurifier/AttrTransform/ImgSpaceTest.php | 55 ++
.../tests/HTMLPurifier/AttrTransform/InputTest.php | 94 +++
.../tests/HTMLPurifier/AttrTransform/LangTest.php | 46 ++
.../HTMLPurifier/AttrTransform/LengthTest.php | 45 ++
.../HTMLPurifier/AttrTransform/NameSyncTest.php | 40 ++
.../tests/HTMLPurifier/AttrTransform/NameTest.php | 31 +
.../tests/HTMLPurifier/AttrTransformHarness.php | 13 +
.../tests/HTMLPurifier/AttrTransformTest.php | 45 ++
.../tests/HTMLPurifier/AttrTypesTest.php | 26 +
.../HTMLPurifier/AttrValidator_ErrorsTest.php | 66 ++
.../tests/HTMLPurifier/ChildDef/ChameleonTest.php | 40 ++
.../tests/HTMLPurifier/ChildDef/CustomTest.php | 89 +++
.../tests/HTMLPurifier/ChildDef/ListTest.php | 50 ++
.../tests/HTMLPurifier/ChildDef/OptionalTest.php | 33 +
.../tests/HTMLPurifier/ChildDef/RequiredTest.php | 73 ++
.../HTMLPurifier/ChildDef/StrictBlockquoteTest.php | 83 +++
.../tests/HTMLPurifier/ChildDef/TableTest.php | 75 ++
.../tests/HTMLPurifier/ChildDefHarness.php | 16 +
.../tests/HTMLPurifier/ComplexHarness.php | 106 +++
.../HTMLPurifier/ConfigSchema/InterchangeTest.php | 21 +
.../directive/aliasesAliasCollision.vtest | 13 +
.../directive/aliasesDirectiveCollision.vtest | 12 +
.../Validator/directive/allowedIsString.vtest | 7 +
.../Validator/directive/allowedNotEmpty.vtest | 7 +
.../Validator/directive/defaultIsAllowed.vtest | 7 +
.../directive/defaultNullWithAllowed.vtest | 5 +
.../Validator/directive/defaultType.vtest | 6 +
.../Validator/directive/descriptionNotEmpty.vtest | 5 +
.../Validator/directive/ignoreNamespace.vtest | 3 +
.../Validator/directive/typeDefined.vtest | 5 +
.../Validator/directive/typeExists.vtest | 6 +
.../directive/typeWithAllowedIsStringType.vtest | 7 +
.../typeWithValueAliasesIsStringType.vtest | 7 +
.../ConfigSchema/Validator/directive/unique.vtest | 11 +
.../directive/valueAliasesAliasIsString.vtest | 7 +
.../directive/valueAliasesAliasNotAllowed.vtest | 8 +
.../directive/valueAliasesNotAliasSelf.vtest | 7 +
.../directive/valueAliasesRealAllowed.vtest | 8 +
.../directive/valueAliasesRealIsString.vtest | 7 +
.../ConfigSchema/ValidatorAtomTest.php | 92 +++
.../HTMLPurifier/ConfigSchema/ValidatorTest.php | 101 +++
.../ConfigSchema/ValidatorTestCase.php | 44 ++
.../tests/HTMLPurifier/ConfigSchemaTest.php | 99 +++
.../tests/HTMLPurifier/ConfigTest-create.ini | 4 +
.../tests/HTMLPurifier/ConfigTest-finalize.ini | 4 +
.../tests/HTMLPurifier/ConfigTest-loadIni.ini | 6 +
lib/htmlpurifier/tests/HTMLPurifier/ConfigTest.php | 557 +++++++++++++++
.../tests/HTMLPurifier/ContextTest.php | 84 +++
.../DefinitionCache/Decorator/CleanupTest.php | 56 ++
.../DefinitionCache/Decorator/MemoryTest.php | 70 ++
.../DefinitionCache/DecoratorHarness.php | 23 +
.../HTMLPurifier/DefinitionCache/DecoratorTest.php | 42 ++
.../DefinitionCache/SerializerTest.php | 225 ++++++
.../DefinitionCache/SerializerTest/README | 3 +
.../HTMLPurifier/DefinitionCacheFactoryTest.php | 70 ++
.../tests/HTMLPurifier/DefinitionCacheHarness.php | 34 +
.../tests/HTMLPurifier/DefinitionCacheTest.php | 32 +
.../tests/HTMLPurifier/DefinitionTest.php | 20 +
.../tests/HTMLPurifier/DefinitionTestable.php | 8 +
.../tests/HTMLPurifier/DoctypeRegistryTest.php | 77 +++
.../tests/HTMLPurifier/ElementDefTest.php | 91 +++
.../tests/HTMLPurifier/EncoderTest.php | 215 ++++++
.../tests/HTMLPurifier/EntityLookupTest.php | 27 +
.../tests/HTMLPurifier/EntityParserTest.php | 85 +++
.../tests/HTMLPurifier/ErrorCollectorEMock.php | 48 ++
.../tests/HTMLPurifier/ErrorCollectorTest.php | 157 +++++
.../tests/HTMLPurifier/ErrorsHarness.php | 38 ++
.../HTMLPurifier/Filter/ExtractStyleBlocksTest.php | 231 +++++++
.../tests/HTMLPurifier/GeneratorTest.php | 288 ++++++++
.../tests/HTMLPurifier/HTMLDefinitionTest.php | 355 ++++++++++
.../tests/HTMLPurifier/HTMLModule/FormsTest.php | 155 +++++
.../tests/HTMLPurifier/HTMLModule/ImageTest.php | 55 ++
.../tests/HTMLPurifier/HTMLModule/NameTest.php | 32 +
.../tests/HTMLPurifier/HTMLModule/NofollowTest.php | 26 +
.../tests/HTMLPurifier/HTMLModule/ObjectTest.php | 38 ++
.../HTMLPurifier/HTMLModule/ProprietaryTest.php | 30 +
.../tests/HTMLPurifier/HTMLModule/RubyTest.php | 55 ++
.../HTMLPurifier/HTMLModule/SafeEmbedTest.php | 41 ++
.../HTMLPurifier/HTMLModule/SafeObjectTest.php | 49 ++
.../HTMLPurifier/HTMLModule/ScriptingTest.php | 55 ++
.../HTMLPurifier/HTMLModule/TargetBlankTest.php | 20 +
.../tests/HTMLPurifier/HTMLModule/TidyTest.php | 224 ++++++
.../tests/HTMLPurifier/HTMLModuleHarness.php | 11 +
.../tests/HTMLPurifier/HTMLModuleManagerTest.php | 120 ++++
.../tests/HTMLPurifier/HTMLModuleTest.php | 146 ++++
lib/htmlpurifier/tests/HTMLPurifier/HTMLT.php | 33 +
.../HTMLPurifier/HTMLT/allowed-preserve.htmlt | 8 +
.../tests/HTMLPurifier/HTMLT/allowed-remove.htmlt | 8 +
.../tests/HTMLPurifier/HTMLT/basic.htmlt | 5 +
.../HTMLPurifier/HTMLT/blacklist-preserve.htmlt | 6 +
.../HTMLPurifier/HTMLT/blacklist-remove.htmlt | 8 +
.../HTMLPurifier/HTMLT/css-allowed-preserve.htmlt | 5 +
.../HTMLPurifier/HTMLT/css-allowed-remove.htmlt | 7 +
.../tests/HTMLPurifier/HTMLT/disable-uri.htmlt | 6 +
.../tests/HTMLPurifier/HTMLT/double-youtube.htmlt | 6 +
.../tests/HTMLPurifier/HTMLT/empty.htmlt | 6 +
.../tests/HTMLPurifier/HTMLT/file-uri.htmlt | 5 +
.../tests/HTMLPurifier/HTMLT/id-default.htmlt | 5 +
.../tests/HTMLPurifier/HTMLT/id-enabled.htmlt | 6 +
.../tests/HTMLPurifier/HTMLT/id-img.htmlt | 8 +
.../tests/HTMLPurifier/HTMLT/id-name-mix.htmlt | 11 +
.../HTMLPurifier/HTMLT/inline-list-loop.htmlt | 5 +
.../HTMLPurifier/HTMLT/inline-wraps-block.htmlt | 5 +
.../tests/HTMLPurifier/HTMLT/list-nesting.htmlt | 5 +
.../tests/HTMLPurifier/HTMLT/munge-extra.htmlt | 11 +
.../tests/HTMLPurifier/HTMLT/munge.htmlt | 52 ++
.../tests/HTMLPurifier/HTMLT/name.htmlt | 6 +
.../HTMLT/safe-iframe-googlemaps.htmlt | 8 +
.../HTMLPurifier/HTMLT/safe-iframe-invalid.htmlt | 7 +
.../HTMLPurifier/HTMLT/safe-iframe-youtube.htmlt | 8 +
.../tests/HTMLPurifier/HTMLT/safe-iframe.htmlt | 14 +
.../HTMLT/safe-object-embed-munge.htmlt | 10 +
.../HTMLPurifier/HTMLT/safe-object-embed.htmlt | 8 +
.../tests/HTMLPurifier/HTMLT/script-bare.htmlt | 9 +
.../tests/HTMLPurifier/HTMLT/script-cdata.htmlt | 11 +
.../tests/HTMLPurifier/HTMLT/script-comment.htmlt | 11 +
.../HTMLPurifier/HTMLT/script-dbl-comment.htmlt | 11 +
.../tests/HTMLPurifier/HTMLT/script-ideal.htmlt | 11 +
.../tests/HTMLPurifier/HTMLT/secure-munge.htmlt | 10 +
.../HTMLT/shift-jis-preserve-yen.htmlt | 8 +
.../HTMLPurifier/HTMLT/shift-jis-remove-yen.htmlt | 9 +
.../HTMLT/strict-blockquote-with-inline.htmlt | 7 +
.../HTMLPurifier/HTMLT/strict-blockquote.htmlt | 7 +
.../HTMLPurifier/HTMLT/strict-underline.htmlt | 7 +
.../tests/HTMLPurifier/HTMLT/tidy-background.htmlt | 5 +
.../HTMLT/trusted-comments-required.htmlt | 6 +
.../HTMLT/trusted-comments-table.htmlt | 5 +
.../HTMLPurifier/HTMLT/trusted-comments.htmlt | 5 +
.../HTMLPurifier/HTMLT/whitespace-preserve.htmlt | 3 +
lib/htmlpurifier/tests/HTMLPurifier/Harness.php | 90 +++
.../tests/HTMLPurifier/IDAccumulatorTest.php | 39 ++
.../HTMLPurifier/Injector/AutoParagraphTest.php | 515 ++++++++++++++
.../HTMLPurifier/Injector/DisplayLinkURITest.php | 33 +
.../tests/HTMLPurifier/Injector/LinkifyTest.php | 50 ++
.../HTMLPurifier/Injector/PurifierLinkifyTest.php | 59 ++
.../HTMLPurifier/Injector/RemoveEmptyTest.php | 80 +++
.../Injector/RemoveSpansWithoutAttributesTest.php | 99 +++
.../tests/HTMLPurifier/Injector/SafeObjectTest.php | 88 +++
.../tests/HTMLPurifier/InjectorHarness.php | 13 +
.../tests/HTMLPurifier/LanguageFactoryTest.php | 70 ++
.../tests/HTMLPurifier/LanguageTest.php | 79 +++
lib/htmlpurifier/tests/HTMLPurifier/LengthTest.php | 73 ++
.../tests/HTMLPurifier/Lexer/DirectLexTest.php | 130 ++++
.../HTMLPurifier/Lexer/DirectLex_ErrorsTest.php | 58 ++
lib/htmlpurifier/tests/HTMLPurifier/LexerTest.php | 752 +++++++++++++++++++++
.../tests/HTMLPurifier/PHPT/domxml.phpt | 15 +
lib/htmlpurifier/tests/HTMLPurifier/PHPT/func.phpt | 9 +
.../tests/HTMLPurifier/PHPT/kses/basic.phpt | 15 +
.../tests/HTMLPurifier/PHPT/loading/_autoload.inc | 12 +
.../HTMLPurifier/PHPT/loading/_no-autoload.inc | 17 +
.../HTMLPurifier/PHPT/loading/auto-includes.phpt | 12 +
.../PHPT/loading/auto-with-autoload.phpt | 28 +
.../loading/auto-with-spl-autoload-default.phpt | 25 +
.../PHPT/loading/auto-with-spl-autoload.phpt | 43 ++
.../PHPT/loading/auto-without-spl-autoload.phpt | 19 +
.../loading/auto-without-spl-with-autoload.phpt | 21 +
.../tests/HTMLPurifier/PHPT/loading/auto.phpt | 11 +
.../error-auto-with-spl-nonstatic-autoload.phpt | 32 +
.../PHPT/loading/path-includes-autoload.phpt | 14 +
.../HTMLPurifier/PHPT/loading/path-includes.phpt | 12 +
.../HTMLPurifier/PHPT/loading/safe-includes.phpt | 12 +
.../PHPT/loading/standalone-autoload.phpt | 12 +
.../PHPT/loading/standalone-with-prefix.phpt | 15 +
.../HTMLPurifier/PHPT/loading/standalone.phpt | 13 +
lib/htmlpurifier/tests/HTMLPurifier/PHPT/stub.phpt | 6 +
lib/htmlpurifier/tests/HTMLPurifier/PHPT/utf8.phpt | 9 +
.../HTMLPurifier/PHPT/ze1_compatibility_mode.phpt | 14 +
.../tests/HTMLPurifier/PercentEncoderTest.php | 63 ++
.../tests/HTMLPurifier/PropertyListTest.php | 93 +++
.../tests/HTMLPurifier/SimpleTest/Reporter.php | 60 ++
.../tests/HTMLPurifier/SimpleTest/TextReporter.php | 21 +
.../tests/HTMLPurifier/Strategy/CompositeTest.php | 66 ++
.../tests/HTMLPurifier/Strategy/CoreTest.php | 45 ++
.../tests/HTMLPurifier/Strategy/ErrorsHarness.php | 18 +
.../tests/HTMLPurifier/Strategy/FixNestingTest.php | 144 ++++
.../Strategy/FixNesting_ErrorsTest.php | 41 ++
.../Strategy/MakeWellFormed/EndInsertInjector.php | 18 +
.../MakeWellFormed/EndInsertInjectorTest.php | 38 ++
.../Strategy/MakeWellFormed/EndRewindInjector.php | 29 +
.../MakeWellFormed/EndRewindInjectorTest.php | 33 +
.../Strategy/MakeWellFormed/SkipInjector.php | 12 +
.../Strategy/MakeWellFormed/SkipInjectorTest.php | 27 +
.../HTMLPurifier/Strategy/MakeWellFormedTest.php | 149 ++++
.../Strategy/MakeWellFormed_ErrorsTest.php | 62 ++
.../Strategy/MakeWellFormed_InjectorTest.php | 149 ++++
.../Strategy/RemoveForeignElementsTest.php | 115 ++++
.../Strategy/RemoveForeignElements_ErrorsTest.php | 71 ++
.../Strategy/RemoveForeignElements_TidyTest.php | 45 ++
.../Strategy/ValidateAttributesTest.php | 232 +++++++
.../Strategy/ValidateAttributes_IDTest.php | 63 ++
.../Strategy/ValidateAttributes_TidyTest.php | 351 ++++++++++
.../tests/HTMLPurifier/StrategyHarness.php | 15 +
.../StringHashParser/AppendMultiline.txt | 5 +
.../HTMLPurifier/StringHashParser/Default.txt | 2 +
.../tests/HTMLPurifier/StringHashParser/Multi.txt | 19 +
.../StringHashParser/OverrideSingle.txt | 3 +
.../tests/HTMLPurifier/StringHashParser/Simple.txt | 10 +
.../tests/HTMLPurifier/StringHashParserTest.php | 89 +++
.../tests/HTMLPurifier/StringHashTest.php | 20 +
.../tests/HTMLPurifier/TagTransformTest.php | 179 +++++
.../tests/HTMLPurifier/TokenFactoryTest.php | 17 +
lib/htmlpurifier/tests/HTMLPurifier/TokenTest.php | 34 +
.../tests/HTMLPurifier/URIDefinitionTest.php | 62 ++
.../URIFilter/DisableExternalResourcesTest.php | 23 +
.../HTMLPurifier/URIFilter/DisableExternalTest.php | 53 ++
.../URIFilter/DisableResourcesTest.php | 24 +
.../HTMLPurifier/URIFilter/HostBlacklistTest.php | 29 +
.../HTMLPurifier/URIFilter/MakeAbsoluteTest.php | 146 ++++
.../tests/HTMLPurifier/URIFilter/MungeTest.php | 145 ++++
.../tests/HTMLPurifier/URIFilterHarness.php | 15 +
lib/htmlpurifier/tests/HTMLPurifier/URIHarness.php | 31 +
.../tests/HTMLPurifier/URIParserTest.php | 145 ++++
.../tests/HTMLPurifier/URISchemeRegistryTest.php | 49 ++
.../tests/HTMLPurifier/URISchemeTest.php | 188 ++++++
lib/htmlpurifier/tests/HTMLPurifier/URITest.php | 201 ++++++
.../tests/HTMLPurifier/UnitConverterTest.php | 131 ++++
.../tests/HTMLPurifier/VarParser/FlexibleTest.php | 66 ++
.../tests/HTMLPurifier/VarParser/NativeTest.php | 12 +
.../tests/HTMLPurifier/VarParserHarness.php | 33 +
268 files changed, 14385 insertions(+)
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrCollectionsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/AlphaValueTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BackgroundPositionTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BackgroundTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BorderTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ColorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/CompositeTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FilterTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FontFamilyTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FontTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ImportantDecoratorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/LengthTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ListStyleTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/MultipleTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/NumberTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/PercentageTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/TextDecorationTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/URITest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSSTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/EnumTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/BoolTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/ClassTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/ColorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/FrameTargetTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/IDTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/LengthTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/LinkTypesTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/MultiLengthTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/NmtokensTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/PixelsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/IntegerTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/LangTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/SwitchTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/TextTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/Email/SimpleCheckTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/EmailHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/HostTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/IPv4Test.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/IPv6Test.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URITest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDefHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrDefTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BackgroundTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BdoDirTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BgColorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BoolToCSSTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BorderTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/EnumToCSSTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/ImgRequiredTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/ImgSpaceTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/InputTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/LangTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/LengthTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/NameSyncTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/NameTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransformHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTransformTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrTypesTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/AttrValidator_ErrorsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ChildDef/ChameleonTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ChildDef/CustomTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ChildDef/ListTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ChildDef/OptionalTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ChildDef/RequiredTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ChildDef/StrictBlockquoteTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ChildDef/TableTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ChildDefHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ComplexHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/InterchangeTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/aliasesAliasCollision.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/aliasesDirectiveCollision.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/allowedIsString.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/allowedNotEmpty.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultIsAllowed.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultNullWithAllowed.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultType.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/descriptionNotEmpty.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/ignoreNamespace.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeDefined.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeExists.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeWithAllowedIsStringType.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeWithValueAliasesIsStringType.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/unique.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesAliasIsString.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesAliasNotAllowed.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesNotAliasSelf.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesRealAllowed.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesRealIsString.vtest
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorAtomTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorTestCase.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigSchemaTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-create.ini
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-finalize.ini
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-loadIni.ini
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ConfigTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ContextTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/Decorator/CleanupTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/Decorator/MemoryTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/DecoratorHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/DecoratorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/SerializerTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/SerializerTest/README
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheFactoryTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DefinitionTestable.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/DoctypeRegistryTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ElementDefTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/EncoderTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/EntityLookupTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/EntityParserTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ErrorCollectorEMock.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ErrorCollectorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/ErrorsHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Filter/ExtractStyleBlocksTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/GeneratorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLDefinitionTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/FormsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/ImageTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/NameTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/NofollowTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/ObjectTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/ProprietaryTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/RubyTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/SafeEmbedTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/SafeObjectTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/ScriptingTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/TargetBlankTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/TidyTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleManagerTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/allowed-preserve.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/allowed-remove.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/basic.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/blacklist-preserve.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/blacklist-remove.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/css-allowed-preserve.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/css-allowed-remove.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/disable-uri.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/double-youtube.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/empty.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/file-uri.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-default.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-enabled.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-img.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-name-mix.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/inline-list-loop.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/inline-wraps-block.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/list-nesting.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/munge-extra.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/munge.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/name.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-googlemaps.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-invalid.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-youtube.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-object-embed-munge.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-object-embed.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-bare.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-cdata.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-comment.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-dbl-comment.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-ideal.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/secure-munge.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/shift-jis-preserve-yen.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/shift-jis-remove-yen.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-blockquote-with-inline.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-blockquote.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-underline.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/tidy-background.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments-required.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments-table.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/HTMLT/whitespace-preserve.htmlt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Harness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/IDAccumulatorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Injector/AutoParagraphTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Injector/DisplayLinkURITest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Injector/LinkifyTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Injector/PurifierLinkifyTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Injector/RemoveEmptyTest.php
create mode 100755 lib/htmlpurifier/tests/HTMLPurifier/Injector/RemoveSpansWithoutAttributesTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Injector/SafeObjectTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/InjectorHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/LanguageFactoryTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/LanguageTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/LengthTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Lexer/DirectLexTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Lexer/DirectLex_ErrorsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/LexerTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/domxml.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/func.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/kses/basic.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/_autoload.inc
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/_no-autoload.inc
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/auto-includes.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/auto-with-autoload.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/auto-with-spl-autoload-default.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/auto-with-spl-autoload.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/auto-without-spl-autoload.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/auto-without-spl-with-autoload.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/auto.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/error-auto-with-spl-nonstatic-autoload.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/path-includes-autoload.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/path-includes.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/safe-includes.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/standalone-autoload.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/standalone-with-prefix.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/loading/standalone.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/stub.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/utf8.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PHPT/ze1_compatibility_mode.phpt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PercentEncoderTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/PropertyListTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/SimpleTest/Reporter.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/SimpleTest/TextReporter.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/CompositeTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/CoreTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/ErrorsHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/FixNestingTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/FixNesting_ErrorsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormed/EndInsertInjector.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormed/EndInsertInjectorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormed/EndRewindInjector.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormed/EndRewindInjectorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormed/SkipInjector.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormed/SkipInjectorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormedTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormed_ErrorsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/MakeWellFormed_InjectorTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/RemoveForeignElementsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/RemoveForeignElements_ErrorsTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/RemoveForeignElements_TidyTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/ValidateAttributes_IDTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/Strategy/ValidateAttributes_TidyTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/StrategyHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/StringHashParser/AppendMultiline.txt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/StringHashParser/Default.txt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/StringHashParser/Multi.txt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/StringHashParser/OverrideSingle.txt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/StringHashParser/Simple.txt
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/StringHashParserTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/StringHashTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/TagTransformTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/TokenFactoryTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/TokenTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIDefinitionTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIFilter/DisableExternalResourcesTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIFilter/DisableExternalTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIFilter/DisableResourcesTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIFilter/HostBlacklistTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIFilter/MakeAbsoluteTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIFilter/MungeTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIFilterHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIHarness.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URIParserTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URISchemeRegistryTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URISchemeTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/URITest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/UnitConverterTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/VarParser/FlexibleTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/VarParser/NativeTest.php
create mode 100644 lib/htmlpurifier/tests/HTMLPurifier/VarParserHarness.php
(limited to 'lib/htmlpurifier/tests/HTMLPurifier')
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrCollectionsTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrCollectionsTest.php
new file mode 100644
index 000000000..227bc9535
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrCollectionsTest.php
@@ -0,0 +1,134 @@
+attr_collections = array(
+ 'Core' => array(
+ 0 => array('Soup', 'Undefined'),
+ 'attribute' => 'Type',
+ 'attribute-2' => 'Type2',
+ ),
+ 'Soup' => array(
+ 'attribute-3' => 'Type3-old' // overwritten
+ )
+ );
+
+ $modules['Module2'] = new HTMLPurifier_HTMLModule();
+ $modules['Module2']->attr_collections = array(
+ 'Core' => array(
+ 0 => array('Brocolli')
+ ),
+ 'Soup' => array(
+ 'attribute-3' => 'Type3'
+ ),
+ 'Brocolli' => array()
+ );
+
+ $collections->__construct($types, $modules);
+ // this is without identifier expansion or inclusions
+ $this->assertIdentical(
+ $collections->info,
+ array(
+ 'Core' => array(
+ 0 => array('Soup', 'Undefined', 'Brocolli'),
+ 'attribute' => 'Type',
+ 'attribute-2' => 'Type2'
+ ),
+ 'Soup' => array(
+ 'attribute-3' => 'Type3'
+ ),
+ 'Brocolli' => array()
+ )
+ );
+
+ }
+
+ function test_performInclusions() {
+
+ generate_mock_once('HTMLPurifier_AttrTypes');
+
+ $types = new HTMLPurifier_AttrTypesMock();
+ $collections = new HTMLPurifier_AttrCollections($types, array());
+ $collections->info = array(
+ 'Core' => array(0 => array('Inclusion', 'Undefined'), 'attr-original' => 'Type'),
+ 'Inclusion' => array(0 => array('SubInclusion'), 'attr' => 'Type'),
+ 'SubInclusion' => array('attr2' => 'Type')
+ );
+
+ $collections->performInclusions($collections->info['Core']);
+ $this->assertIdentical(
+ $collections->info['Core'],
+ array(
+ 'attr-original' => 'Type',
+ 'attr' => 'Type',
+ 'attr2' => 'Type'
+ )
+ );
+
+ // test recursive
+ $collections->info = array(
+ 'One' => array(0 => array('Two'), 'one' => 'Type'),
+ 'Two' => array(0 => array('One'), 'two' => 'Type')
+ );
+ $collections->performInclusions($collections->info['One']);
+ $this->assertIdentical(
+ $collections->info['One'],
+ array(
+ 'one' => 'Type',
+ 'two' => 'Type'
+ )
+ );
+
+ }
+
+ function test_expandIdentifiers() {
+
+ generate_mock_once('HTMLPurifier_AttrTypes');
+
+ $types = new HTMLPurifier_AttrTypesMock();
+ $collections = new HTMLPurifier_AttrCollections($types, array());
+
+ $attr = array(
+ 'attr1' => 'Color',
+ 'attr2*' => 'URI'
+ );
+ $c_object = new HTMLPurifier_AttrDef_HTML_Color();
+ $u_object = new HTMLPurifier_AttrDef_URI();
+
+ $types->setReturnValue('get', $c_object, array('Color'));
+ $types->setReturnValue('get', $u_object, array('URI'));
+
+ $collections->expandIdentifiers($attr, $types);
+
+ $u_object->required = true;
+ $this->assertIdentical(
+ $attr,
+ array(
+ 'attr1' => $c_object,
+ 'attr2' => $u_object
+ )
+ );
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/AlphaValueTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/AlphaValueTest.php
new file mode 100644
index 000000000..56efa306f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/AlphaValueTest.php
@@ -0,0 +1,28 @@
+def = new HTMLPurifier_AttrDef_CSS_AlphaValue();
+
+ $this->assertDef('0');
+ $this->assertDef('1');
+ $this->assertDef('.2');
+
+ // clamping to [0.0, 1,0]
+ $this->assertDef('1.2', '1');
+ $this->assertDef('-3', '0');
+
+ $this->assertDef('0.0', '0');
+ $this->assertDef('1.0', '1');
+ $this->assertDef('000', '0');
+
+ $this->assertDef('asdf', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BackgroundPositionTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BackgroundPositionTest.php
new file mode 100644
index 000000000..a216b2677
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BackgroundPositionTest.php
@@ -0,0 +1,68 @@
+def = new HTMLPurifier_AttrDef_CSS_BackgroundPosition();
+
+ // explicitly cited in spec
+ $this->assertDef('0% 0%');
+ $this->assertDef('100% 100%');
+ $this->assertDef('14% 84%');
+ $this->assertDef('2cm 1cm');
+ $this->assertDef('top');
+ $this->assertDef('left');
+ $this->assertDef('center');
+ $this->assertDef('right');
+ $this->assertDef('bottom');
+ $this->assertDef('left top');
+ $this->assertDef('center top');
+ $this->assertDef('right top');
+ $this->assertDef('left center');
+ $this->assertDef('right center');
+ $this->assertDef('left bottom');
+ $this->assertDef('center bottom');
+ $this->assertDef('right bottom');
+
+ // reordered due to internal impl details
+ $this->assertDef('top left', 'left top');
+ $this->assertDef('top center', 'top');
+ $this->assertDef('top right', 'right top');
+ $this->assertDef('center left', 'left');
+ $this->assertDef('center center', 'center');
+ $this->assertDef('center right', 'right');
+ $this->assertDef('bottom left', 'left bottom');
+ $this->assertDef('bottom center', 'bottom');
+ $this->assertDef('bottom right', 'right bottom');
+
+ // more cases from the defined syntax
+ $this->assertDef('1.32in 4ex');
+ $this->assertDef('-14% -84.65%');
+ $this->assertDef('-1in -4ex');
+ $this->assertDef('-1pc 2.3%');
+
+ // keyword mixing
+ $this->assertDef('3em top');
+ $this->assertDef('left 50%');
+
+ // fixable keyword mixing
+ $this->assertDef('top 3em', '3em top');
+ $this->assertDef('50% left', 'left 50%');
+
+ // whitespace collapsing
+ $this->assertDef('3em top', '3em top');
+ $this->assertDef("left\n \t foo ", 'left');
+
+ // invalid uses (we're going to be strict on these)
+ $this->assertDef('foo bar', false);
+ $this->assertDef('left left', 'left');
+ $this->assertDef('left right top bottom center left', 'left bottom');
+ $this->assertDef('0fr 9%', '9%');
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BackgroundTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BackgroundTest.php
new file mode 100644
index 000000000..83461c365
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BackgroundTest.php
@@ -0,0 +1,23 @@
+def = new HTMLPurifier_AttrDef_CSS_Background($config);
+
+ $valid = '#333 url("chess.png") repeat fixed 50% top';
+ $this->assertDef($valid);
+ $this->assertDef('url(\'chess.png\') #333 50% top repeat fixed', $valid);
+ $this->assertDef(
+ 'rgb(34, 56, 33) url(chess.png) repeat fixed top',
+ 'rgb(34,56,33) url("chess.png") repeat fixed top'
+ );
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BorderTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BorderTest.php
new file mode 100644
index 000000000..6cd77fd7a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/BorderTest.php
@@ -0,0 +1,21 @@
+def = new HTMLPurifier_AttrDef_CSS_Border($config);
+
+ $this->assertDef('thick solid red', 'thick solid #FF0000');
+ $this->assertDef('thick solid');
+ $this->assertDef('solid red', 'solid #FF0000');
+ $this->assertDef('1px solid #000');
+ $this->assertDef('1px solid rgb(0, 0, 0)', '1px solid rgb(0,0,0)');
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ColorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ColorTest.php
new file mode 100644
index 000000000..f3a74e897
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ColorTest.php
@@ -0,0 +1,41 @@
+def = new HTMLPurifier_AttrDef_CSS_Color();
+
+ $this->assertDef('#F00');
+ $this->assertDef('#fff');
+ $this->assertDef('#eeeeee');
+ $this->assertDef('#808080');
+ $this->assertDef('rgb(255, 0, 0)', 'rgb(255,0,0)'); // rm spaces
+ $this->assertDef('rgb(100%,0%,0%)');
+ $this->assertDef('rgb(50.5%,23.2%,43.9%)'); // decimals okay
+
+ $this->assertDef('#G00', false);
+ $this->assertDef('cmyk(40, 23, 43, 23)', false);
+ $this->assertDef('rgb(0%, 23, 68%)', false);
+
+ // clip numbers outside sRGB gamut
+ $this->assertDef('rgb(200%, -10%, 0%)', 'rgb(100%,0%,0%)');
+ $this->assertDef('rgb(256,-23,34)', 'rgb(255,0,34)');
+
+ // color keywords, of course
+ $this->assertDef('red', '#FF0000');
+
+ // malformed hex declaration
+ $this->assertDef('808080', '#808080');
+ $this->assertDef('000000', '#000000');
+ $this->assertDef('fed', '#fed');
+
+ // maybe hex transformations would be another nice feature
+ // at the very least transform rgb percent to rgb integer
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/CompositeTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/CompositeTest.php
new file mode 100644
index 000000000..44bef5551
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/CompositeTest.php
@@ -0,0 +1,81 @@
+defs =& $defs;
+ }
+
+}
+
+class HTMLPurifier_AttrDef_CSS_CompositeTest extends HTMLPurifier_AttrDefHarness
+{
+
+ protected $def1, $def2;
+
+ function test() {
+
+ generate_mock_once('HTMLPurifier_AttrDef');
+
+ $config = HTMLPurifier_Config::createDefault();
+ $context = new HTMLPurifier_Context();
+
+ // first test: value properly validates on first definition
+ // so second def is never called
+
+ $def1 = new HTMLPurifier_AttrDefMock();
+ $def2 = new HTMLPurifier_AttrDefMock();
+ $defs = array(&$def1, &$def2);
+ $def = new HTMLPurifier_AttrDef_CSS_Composite_Testable($defs);
+ $input = 'FOOBAR';
+ $output = 'foobar';
+ $def1_params = array($input, $config, $context);
+ $def1->expectOnce('validate', $def1_params);
+ $def1->setReturnValue('validate', $output, $def1_params);
+ $def2->expectNever('validate');
+
+ $result = $def->validate($input, $config, $context);
+ $this->assertIdentical($output, $result);
+
+ // second test, first def fails, second def works
+
+ $def1 = new HTMLPurifier_AttrDefMock();
+ $def2 = new HTMLPurifier_AttrDefMock();
+ $defs = array(&$def1, &$def2);
+ $def = new HTMLPurifier_AttrDef_CSS_Composite_Testable($defs);
+ $input = 'BOOMA';
+ $output = 'booma';
+ $def_params = array($input, $config, $context);
+ $def1->expectOnce('validate', $def_params);
+ $def1->setReturnValue('validate', false, $def_params);
+ $def2->expectOnce('validate', $def_params);
+ $def2->setReturnValue('validate', $output, $def_params);
+
+ $result = $def->validate($input, $config, $context);
+ $this->assertIdentical($output, $result);
+
+ // third test, all fail, so composite faiils
+
+ $def1 = new HTMLPurifier_AttrDefMock();
+ $def2 = new HTMLPurifier_AttrDefMock();
+ $defs = array(&$def1, &$def2);
+ $def = new HTMLPurifier_AttrDef_CSS_Composite_Testable($defs);
+ $input = 'BOOMA';
+ $output = false;
+ $def_params = array($input, $config, $context);
+ $def1->expectOnce('validate', $def_params);
+ $def1->setReturnValue('validate', false, $def_params);
+ $def2->expectOnce('validate', $def_params);
+ $def2->setReturnValue('validate', false, $def_params);
+
+ $result = $def->validate($input, $config, $context);
+ $this->assertIdentical($output, $result);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FilterTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FilterTest.php
new file mode 100644
index 000000000..7795643f1
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FilterTest.php
@@ -0,0 +1,29 @@
+def = new HTMLPurifier_AttrDef_CSS_Filter();
+
+ $this->assertDef('none');
+
+ $this->assertDef('alpha(opacity=0)');
+ $this->assertDef('alpha(opacity=100)');
+ $this->assertDef('alpha(opacity=50)');
+ $this->assertDef('alpha(opacity=342)', 'alpha(opacity=100)');
+ $this->assertDef('alpha(opacity=-23)', 'alpha(opacity=0)');
+
+ $this->assertDef('alpha ( opacity = 0 )', 'alpha(opacity=0)');
+ $this->assertDef('alpha(opacity=0,opacity=100)', 'alpha(opacity=0)');
+
+ $this->assertDef('progid:DXImageTransform.Microsoft.Alpha(opacity=20)');
+
+ $this->assertDef('progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FontFamilyTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FontFamilyTest.php
new file mode 100644
index 000000000..fda8e01ff
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FontFamilyTest.php
@@ -0,0 +1,52 @@
+def = new HTMLPurifier_AttrDef_CSS_FontFamily();
+
+ $this->assertDef('Gill, Helvetica, sans-serif');
+ $this->assertDef("'Times New Roman', serif");
+ $this->assertDef("\"Times New Roman\"", "'Times New Roman'");
+ $this->assertDef('01234');
+ $this->assertDef(',', false);
+ $this->assertDef('Times New Roman, serif', "'Times New Roman', serif");
+ $this->assertDef($d = "'\xE5\xAE\x8B\xE4\xBD\x93'");
+ $this->assertDef("\xE5\xAE\x8B\xE4\xBD\x93", $d);
+ $this->assertDef("'\\01'", "''");
+ $this->assertDef("'\\20'", "' '");
+ $this->assertDef("\\0020", "' '");
+ $this->assertDef("'\\000045'", "E");
+ $this->assertDef("','", false);
+ $this->assertDef("',' foobar','", "' foobar'");
+ $this->assertDef("'\\000045a'", "Ea");
+ $this->assertDef("'\\00045 a'", "Ea");
+ $this->assertDef("'\\00045 a'", "'E a'");
+ $this->assertDef("'\\\nf'", "f");
+ // No longer supported, except maybe in NoJS mode (see source
+ // file for more explanation)
+ //$this->assertDef($d = '"John\'s Font"');
+ //$this->assertDef("John's Font", $d);
+ //$this->assertDef("'\\','f'", "\"\\5C \", f");
+ //$this->assertDef("'\\27'", "\"'\"");
+ //$this->assertDef('"\\22"', "\"\\22 \"");
+ //$this->assertDef('"\\""', "\"\\22 \"");
+ //$this->assertDef('"\'"', "\"'\"");
+ }
+
+ function testAllowed() {
+ $this->config->set('CSS.AllowedFonts', array('serif', 'Times New Roman'));
+
+ $this->assertDef('serif');
+ $this->assertDef('sans-serif', false);
+ $this->assertDef('serif, sans-serif', 'serif');
+ $this->assertDef('Times New Roman', "'Times New Roman'");
+ $this->assertDef("'Times New Roman'");
+ $this->assertDef('foo', false);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FontTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FontTest.php
new file mode 100644
index 000000000..91870d13e
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/FontTest.php
@@ -0,0 +1,34 @@
+def = new HTMLPurifier_AttrDef_CSS_Font($config);
+
+ // hodgepodge of usage cases from W3C spec, but " -> '
+ $this->assertDef('12px/14px sans-serif');
+ $this->assertDef('80% sans-serif');
+ $this->assertDef("x-large/110% 'New Century Schoolbook', serif");
+ $this->assertDef('bold italic large Palatino, serif');
+ $this->assertDef('normal small-caps 120%/120% fantasy');
+ $this->assertDef("300 italic 1.3em/1.7em 'FB Armada', sans-serif");
+ $this->assertDef('600 9px Charcoal');
+ $this->assertDef('600 9px/ 12px Charcoal', '600 9px/12px Charcoal');
+
+ // spacing
+ $this->assertDef('12px / 14px sans-serif', '12px/14px sans-serif');
+
+ // system fonts
+ $this->assertDef('menu');
+
+ $this->assertDef('800', false);
+ $this->assertDef('600 9px//12px Charcoal', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ImportantDecoratorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ImportantDecoratorTest.php
new file mode 100644
index 000000000..c7fa8a0fa
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ImportantDecoratorTest.php
@@ -0,0 +1,49 @@
+mock = new HTMLPurifier_AttrDefMock();
+ $this->def = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($this->mock, true);
+ }
+
+ protected function setMock($input, $output = null) {
+ if ($output === null) $output = $input;
+ $this->mock->expectOnce('validate', array($input, $this->config, $this->context));
+ $this->mock->setReturnValue('validate', $output);
+ }
+
+ function testImportant() {
+ $this->setMock('23');
+ $this->assertDef('23 !important');
+ }
+
+ function testImportantInternalDefChanged() {
+ $this->setMock('23', '24');
+ $this->assertDef('23 !important', '24 !important');
+ }
+
+ function testImportantWithSpace() {
+ $this->setMock('23');
+ $this->assertDef('23 ! important ', '23 !important');
+ }
+
+ function testFakeImportant() {
+ $this->setMock('! foo important');
+ $this->assertDef('! foo important');
+ }
+
+ function testStrip() {
+ $this->def = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($this->mock, false);
+ $this->setMock('23');
+ $this->assertDef('23 ! important ', '23');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/LengthTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/LengthTest.php
new file mode 100644
index 000000000..9d9fc41f2
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/LengthTest.php
@@ -0,0 +1,48 @@
+def = new HTMLPurifier_AttrDef_CSS_Length();
+
+ $this->assertDef('0');
+ $this->assertDef('0px');
+ $this->assertDef('4.5px');
+ $this->assertDef('-4.5px');
+ $this->assertDef('3ex');
+ $this->assertDef('3em');
+ $this->assertDef('3in');
+ $this->assertDef('3cm');
+ $this->assertDef('3mm');
+ $this->assertDef('3pt');
+ $this->assertDef('3pc');
+
+ $this->assertDef('3PX', '3px');
+
+ $this->assertDef('3', false);
+ $this->assertDef('3miles', false);
+
+ }
+
+ function testNonNegative() {
+
+ $this->def = new HTMLPurifier_AttrDef_CSS_Length('0');
+
+ $this->assertDef('3cm');
+ $this->assertDef('-3mm', false);
+
+ }
+
+ function testBounding() {
+ $this->def = new HTMLPurifier_AttrDef_CSS_Length('-1in', '1in');
+ $this->assertDef('1cm');
+ $this->assertDef('-1cm');
+ $this->assertDef('0');
+ $this->assertDef('1em', false);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ListStyleTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ListStyleTest.php
new file mode 100644
index 000000000..070066705
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/ListStyleTest.php
@@ -0,0 +1,35 @@
+def = new HTMLPurifier_AttrDef_CSS_ListStyle($config);
+
+ $this->assertDef('lower-alpha');
+ $this->assertDef('upper-roman inside');
+ $this->assertDef('circle outside');
+ $this->assertDef('inside');
+ $this->assertDef('none');
+ $this->assertDef('url("foo.gif")');
+ $this->assertDef('circle url("foo.gif") inside');
+
+ // invalid values
+ $this->assertDef('outside inside', 'outside');
+
+ // ordering
+ $this->assertDef('url(foo.gif) none', 'none url("foo.gif")');
+ $this->assertDef('circle lower-alpha', 'circle');
+ // the spec is ambiguous about what happens in these
+ // cases, so we're going off the W3C CSS validator
+ $this->assertDef('disc none', 'disc');
+ $this->assertDef('none disc', 'none');
+
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/MultipleTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/MultipleTest.php
new file mode 100644
index 000000000..4461cb508
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/MultipleTest.php
@@ -0,0 +1,28 @@
+def = new HTMLPurifier_AttrDef_CSS_Multiple(
+ new HTMLPurifier_AttrDef_Integer()
+ );
+
+ $this->assertDef('1 2 3 4');
+ $this->assertDef('6');
+ $this->assertDef('4 5');
+ $this->assertDef(' 2 54 2 3', '2 54 2 3');
+ $this->assertDef("6\r3", '6 3');
+
+ $this->assertDef('asdf', false);
+ $this->assertDef('a s d f', false);
+ $this->assertDef('1 2 3 4 5', '1 2 3 4');
+ $this->assertDef('1 2 invalid 3', '1 2 3');
+
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/NumberTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/NumberTest.php
new file mode 100644
index 000000000..94e6ea8cf
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/NumberTest.php
@@ -0,0 +1,51 @@
+def = new HTMLPurifier_AttrDef_CSS_Number();
+
+ $this->assertDef('0');
+ $this->assertDef('0.0', '0');
+ $this->assertDef('1.0', '1');
+ $this->assertDef('34');
+ $this->assertDef('4.5');
+ $this->assertDef('.5');
+ $this->assertDef('0.5', '.5');
+ $this->assertDef('-56.9');
+
+ $this->assertDef('0.', '0');
+ $this->assertDef('.0', '0');
+ $this->assertDef('0.0', '0');
+
+ $this->assertDef('1.', '1');
+ $this->assertDef('.1', '.1');
+
+ $this->assertDef('1.0', '1');
+ $this->assertDef('0.1', '.1');
+
+ $this->assertDef('000', '0');
+ $this->assertDef(' 9', '9');
+ $this->assertDef('+5.0000', '5');
+ $this->assertDef('02.20', '2.2');
+ $this->assertDef('2.', '2');
+
+ $this->assertDef('.', false);
+ $this->assertDef('asdf', false);
+ $this->assertDef('0.5.6', false);
+
+ }
+
+ function testNonNegative() {
+
+ $this->def = new HTMLPurifier_AttrDef_CSS_Number(true);
+ $this->assertDef('23');
+ $this->assertDef('-12', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/PercentageTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/PercentageTest.php
new file mode 100644
index 000000000..f712af1d2
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/PercentageTest.php
@@ -0,0 +1,24 @@
+def = new HTMLPurifier_AttrDef_CSS_Percentage();
+
+ $this->assertDef('10%');
+ $this->assertDef('1.607%');
+ $this->assertDef('-567%');
+
+ $this->assertDef(' 100% ', '100%');
+
+ $this->assertDef('5', false);
+ $this->assertDef('asdf', false);
+ $this->assertDef('%', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/TextDecorationTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/TextDecorationTest.php
new file mode 100644
index 000000000..dd714d206
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/TextDecorationTest.php
@@ -0,0 +1,27 @@
+def = new HTMLPurifier_AttrDef_CSS_TextDecoration();
+
+ $this->assertDef('none');
+ $this->assertDef('none underline', 'underline');
+
+ $this->assertDef('underline');
+ $this->assertDef('overline');
+ $this->assertDef('line-through overline underline');
+ $this->assertDef('overline line-through');
+ $this->assertDef('UNDERLINE', 'underline');
+ $this->assertDef(' underline line-through ', 'underline line-through');
+
+ $this->assertDef('foobar underline', 'underline');
+ $this->assertDef('blink', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/URITest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/URITest.php
new file mode 100644
index 000000000..3d6f5791e
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSS/URITest.php
@@ -0,0 +1,29 @@
+def = new HTMLPurifier_AttrDef_CSS_URI();
+
+ $this->assertDef('', false);
+
+ // we could be nice but we won't be
+ $this->assertDef('http://www.example.com/', false);
+
+ $this->assertDef('url(', false);
+ $this->assertDef('url("")', true);
+ $result = 'url("http://www.example.com/")';
+ $this->assertDef('url(http://www.example.com/)', $result);
+ $this->assertDef('url("http://www.example.com/")', $result);
+ $this->assertDef("url('http://www.example.com/')", $result);
+ $this->assertDef(
+ ' url( "http://www.example.com/" ) ', $result);
+ $this->assertDef("url(http://www.example.com/foo,bar\)\'\()",
+ 'url("http://www.example.com/foo,bar%29%27%28")');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSSTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSSTest.php
new file mode 100644
index 000000000..56917aece
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/CSSTest.php
@@ -0,0 +1,164 @@
+def = new HTMLPurifier_AttrDef_CSS();
+ }
+
+ function test() {
+
+ // regular cases, singular
+ $this->assertDef('text-align:right;');
+ $this->assertDef('border-left-style:solid;');
+ $this->assertDef('border-style:solid dotted;');
+ $this->assertDef('clear:right;');
+ $this->assertDef('float:left;');
+ $this->assertDef('font-style:italic;');
+ $this->assertDef('font-variant:small-caps;');
+ $this->assertDef('font-weight:bold;');
+ $this->assertDef('list-style-position:outside;');
+ $this->assertDef('list-style-type:upper-roman;');
+ $this->assertDef('list-style:upper-roman inside;');
+ $this->assertDef('text-transform:capitalize;');
+ $this->assertDef('background-color:rgb(0,0,255);');
+ $this->assertDef('background-color:transparent;');
+ $this->assertDef('background:#333 url("chess.png") repeat fixed 50% top;');
+ $this->assertDef('color:#F00;');
+ $this->assertDef('border-top-color:#F00;');
+ $this->assertDef('border-color:#F00 #FF0;');
+ $this->assertDef('border-top-width:thin;');
+ $this->assertDef('border-top-width:12px;');
+ $this->assertDef('border-width:5px 1px 4px 2px;');
+ $this->assertDef('border-top-width:-12px;', false);
+ $this->assertDef('letter-spacing:normal;');
+ $this->assertDef('letter-spacing:2px;');
+ $this->assertDef('word-spacing:normal;');
+ $this->assertDef('word-spacing:3em;');
+ $this->assertDef('font-size:200%;');
+ $this->assertDef('font-size:larger;');
+ $this->assertDef('font-size:12pt;');
+ $this->assertDef('line-height:2;');
+ $this->assertDef('line-height:2em;');
+ $this->assertDef('line-height:20%;');
+ $this->assertDef('line-height:normal;');
+ $this->assertDef('line-height:-20%;', false);
+ $this->assertDef('margin-left:5px;');
+ $this->assertDef('margin-right:20%;');
+ $this->assertDef('margin-top:auto;');
+ $this->assertDef('margin:auto 5%;');
+ $this->assertDef('padding-bottom:5px;');
+ $this->assertDef('padding-top:20%;');
+ $this->assertDef('padding:20% 10%;');
+ $this->assertDef('padding-top:-20%;', false);
+ $this->assertDef('text-indent:3em;');
+ $this->assertDef('text-indent:5%;');
+ $this->assertDef('text-indent:-3em;');
+ $this->assertDef('width:50%;');
+ $this->assertDef('width:50px;');
+ $this->assertDef('width:auto;');
+ $this->assertDef('width:-50px;', false);
+ $this->assertDef('text-decoration:underline;');
+ $this->assertDef('font-family:sans-serif;');
+ $this->assertDef("font-family:Gill, 'Times New Roman', sans-serif;");
+ $this->assertDef('font:12px serif;');
+ $this->assertDef('border:1px solid #000;');
+ $this->assertDef('border-bottom:2em double #FF00FA;');
+ $this->assertDef('border-collapse:collapse;');
+ $this->assertDef('border-collapse:separate;');
+ $this->assertDef('caption-side:top;');
+ $this->assertDef('vertical-align:middle;');
+ $this->assertDef('vertical-align:12px;');
+ $this->assertDef('vertical-align:50%;');
+ $this->assertDef('table-layout:fixed;');
+ $this->assertDef('list-style-image:url("nice.jpg");');
+ $this->assertDef('list-style:disc url("nice.jpg") inside;');
+ $this->assertDef('background-image:url("foo.jpg");');
+ $this->assertDef('background-image:none;');
+ $this->assertDef('background-repeat:repeat-y;');
+ $this->assertDef('background-attachment:fixed;');
+ $this->assertDef('background-position:left 90%;');
+ $this->assertDef('border-spacing:1em;');
+ $this->assertDef('border-spacing:1em 2em;');
+
+ // duplicates
+ $this->assertDef('text-align:right;text-align:left;',
+ 'text-align:left;');
+
+ // a few composites
+ $this->assertDef('font-variant:small-caps;font-weight:900;');
+ $this->assertDef('float:right;text-align:right;');
+
+ // selective removal
+ $this->assertDef('text-transform:capitalize;destroy:it;',
+ 'text-transform:capitalize;');
+
+ // inherit works for everything
+ $this->assertDef('text-align:inherit;');
+
+ // bad props
+ $this->assertDef('nodice:foobar;', false);
+ $this->assertDef('position:absolute;', false);
+ $this->assertDef('background-image:url(\'javascript:alert\(\)\');', false);
+
+ // airy input
+ $this->assertDef(' font-weight : bold; color : #ff0000',
+ 'font-weight:bold;color:#ff0000;');
+
+ // case-insensitivity
+ $this->assertDef('FLOAT:LEFT;', 'float:left;');
+
+ // !important stripping
+ $this->assertDef('float:left !important;', 'float:left;');
+
+ }
+
+ function testProprietary() {
+ $this->config->set('CSS.Proprietary', true);
+
+ $this->assertDef('scrollbar-arrow-color:#ff0;');
+ $this->assertDef('scrollbar-base-color:#ff6347;');
+ $this->assertDef('scrollbar-darkshadow-color:#ffa500;');
+ $this->assertDef('scrollbar-face-color:#008080;');
+ $this->assertDef('scrollbar-highlight-color:#ff69b4;');
+ $this->assertDef('scrollbar-shadow-color:#f0f;');
+
+ $this->assertDef('opacity:.2;');
+ $this->assertDef('-moz-opacity:.2;');
+ $this->assertDef('-khtml-opacity:.2;');
+ $this->assertDef('filter:alpha(opacity=20);');
+
+ }
+
+ function testImportant() {
+ $this->config->set('CSS.AllowImportant', true);
+ $this->assertDef('float:left !important;');
+ }
+
+ function testTricky() {
+ $this->config->set('CSS.AllowTricky', true);
+ $this->assertDef('display:none;');
+ $this->assertDef('visibility:visible;');
+ $this->assertDef('overflow:scroll;');
+ }
+
+ function testForbidden() {
+ $this->config->set('CSS.ForbiddenProperties', 'float');
+ $this->assertDef('float:left;', false);
+ $this->assertDef('text-align:right;');
+ }
+
+ function testTrusted() {
+ $this->config->set('CSS.Trusted', true);
+ $this->assertDef('position:relative;');
+ $this->assertDef('left:2px;');
+ $this->assertDef('right:100%;');
+ $this->assertDef('top:auto;');
+ $this->assertDef('z-index:-2;');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/EnumTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/EnumTest.php
new file mode 100644
index 000000000..7722c1bc2
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/EnumTest.php
@@ -0,0 +1,37 @@
+def = new HTMLPurifier_AttrDef_Enum(array('one', 'two'));
+ $this->assertDef('one');
+ $this->assertDef('ONE', 'one');
+ }
+
+ function testCaseSensitive() {
+ $this->def = new HTMLPurifier_AttrDef_Enum(array('one', 'two'), true);
+ $this->assertDef('one');
+ $this->assertDef('ONE', false);
+ }
+
+ function testFixing() {
+ $this->def = new HTMLPurifier_AttrDef_Enum(array('one'));
+ $this->assertDef(' one ', 'one');
+ }
+
+ function test_make() {
+ $factory = new HTMLPurifier_AttrDef_Enum();
+
+ $def = $factory->make('foo,bar');
+ $def2 = new HTMLPurifier_AttrDef_Enum(array('foo', 'bar'));
+ $this->assertIdentical($def, $def2);
+
+ $def = $factory->make('s:foo,BAR');
+ $def2 = new HTMLPurifier_AttrDef_Enum(array('foo', 'BAR'), true);
+ $this->assertIdentical($def, $def2);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/BoolTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/BoolTest.php
new file mode 100644
index 000000000..060d0fc8f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/BoolTest.php
@@ -0,0 +1,22 @@
+def = new HTMLPurifier_AttrDef_HTML_Bool('foo');
+ $this->assertDef('foo');
+ $this->assertDef('', false);
+ $this->assertDef('bar', 'foo');
+ }
+
+ function test_make() {
+ $factory = new HTMLPurifier_AttrDef_HTML_Bool();
+ $def = $factory->make('foo');
+ $def2 = new HTMLPurifier_AttrDef_HTML_Bool('foo');
+ $this->assertIdentical($def, $def2);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/ClassTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/ClassTest.php
new file mode 100644
index 000000000..6effd3cde
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/ClassTest.php
@@ -0,0 +1,48 @@
+def = new HTMLPurifier_AttrDef_HTML_Class();
+ }
+ function testAllowedClasses() {
+ $this->config->set('Attr.AllowedClasses', array('foo'));
+ $this->assertDef('foo');
+ $this->assertDef('bar', false);
+ $this->assertDef('foo bar', 'foo');
+ }
+ function testForbiddenClasses() {
+ $this->config->set('Attr.ForbiddenClasses', array('bar'));
+ $this->assertDef('foo');
+ $this->assertDef('bar', false);
+ $this->assertDef('foo bar', 'foo');
+ }
+ function testDefault() {
+ $this->assertDef('valid');
+ $this->assertDef('a0-_');
+ $this->assertDef('-valid');
+ $this->assertDef('_valid');
+ $this->assertDef('double valid');
+
+ $this->assertDef('0stillvalid');
+ $this->assertDef('-0');
+
+ // test conditional replacement
+ $this->assertDef('validassoc 0valid', 'validassoc 0valid');
+
+ // test whitespace leniency
+ $this->assertDef(" double\nvalid\r", 'double valid');
+
+ // test case sensitivity
+ $this->assertDef('VALID');
+
+ // test duplicate removal
+ $this->assertDef('valid valid', 'valid');
+ }
+ function testXHTML11Behavior() {
+ $this->config->set('HTML.Doctype', 'XHTML 1.1');
+ $this->assertDef('0invalid', false);
+ $this->assertDef('valid valid', 'valid');
+ }
+}
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/ColorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/ColorTest.php
new file mode 100644
index 000000000..8b4a46347
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/ColorTest.php
@@ -0,0 +1,20 @@
+def = new HTMLPurifier_AttrDef_HTML_Color();
+ $this->assertDef('', false);
+ $this->assertDef('foo', false);
+ $this->assertDef('43', false);
+ $this->assertDef('red', '#FF0000');
+ $this->assertDef('#FF0000');
+ $this->assertDef('#453443');
+ $this->assertDef('453443', '#453443');
+ $this->assertDef('#345', '#334455');
+ $this->assertDef('120', '#112200');
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/FrameTargetTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/FrameTargetTest.php
new file mode 100644
index 000000000..7d3e24c75
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/FrameTargetTest.php
@@ -0,0 +1,28 @@
+def = new HTMLPurifier_AttrDef_HTML_FrameTarget();
+ }
+
+ function testNoneAllowed() {
+ $this->assertDef('', false);
+ $this->assertDef('foo', false);
+ $this->assertDef('_blank', false);
+ $this->assertDef('baz', false);
+ }
+
+ function test() {
+ $this->config->set('Attr.AllowedFrameTargets', 'foo,_blank');
+ $this->assertDef('', false);
+ $this->assertDef('foo');
+ $this->assertDef('_blank');
+ $this->assertDef('baz', false);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/IDTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/IDTest.php
new file mode 100644
index 000000000..245db16da
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/IDTest.php
@@ -0,0 +1,108 @@
+context->register('IDAccumulator', $id_accumulator);
+ $this->config->set('Attr.EnableID', true);
+ $this->def = new HTMLPurifier_AttrDef_HTML_ID();
+
+ }
+
+ function test() {
+
+ // valid ID names
+ $this->assertDef('alpha');
+ $this->assertDef('al_ha');
+ $this->assertDef('a0-:.');
+ $this->assertDef('a');
+
+ // invalid ID names
+ $this->assertDef('assertDef('0123', false);
+ $this->assertDef('.asa', false);
+
+ // test duplicate detection
+ $this->assertDef('once');
+ $this->assertDef('once', false);
+
+ // valid once whitespace stripped, but needs to be amended
+ $this->assertDef(' whee ', 'whee');
+
+ }
+
+ function testPrefix() {
+
+ $this->config->set('Attr.IDPrefix', 'user_');
+
+ $this->assertDef('alpha', 'user_alpha');
+ $this->assertDef('assertDef('once', 'user_once');
+ $this->assertDef('once', false);
+
+ // if already prefixed, leave alone
+ $this->assertDef('user_alas');
+ $this->assertDef('user_user_alas'); // how to bypass
+
+ }
+
+ function testTwoPrefixes() {
+
+ $this->config->set('Attr.IDPrefix', 'user_');
+ $this->config->set('Attr.IDPrefixLocal', 'story95_');
+
+ $this->assertDef('alpha', 'user_story95_alpha');
+ $this->assertDef('assertDef('once', 'user_story95_once');
+ $this->assertDef('once', false);
+
+ $this->assertDef('user_story95_alas');
+ $this->assertDef('user_alas', 'user_story95_user_alas'); // !
+ }
+
+ function testLocalPrefixWithoutMainPrefix() {
+ // no effect when IDPrefix isn't set
+ $this->config->set('Attr.IDPrefix', '');
+ $this->config->set('Attr.IDPrefixLocal', 'story95_');
+ $this->expectError('%Attr.IDPrefixLocal cannot be used unless '.
+ '%Attr.IDPrefix is set');
+ $this->assertDef('amherst');
+
+ }
+
+ // reference functionality is disabled for now
+ function disabled_testIDReference() {
+
+ $this->def = new HTMLPurifier_AttrDef_HTML_ID(true);
+
+ $this->assertDef('good_id');
+ $this->assertDef('good_id'); // duplicates okay
+ $this->assertDef('', false);
+
+ $this->def = new HTMLPurifier_AttrDef_HTML_ID();
+
+ $this->assertDef('good_id');
+ $this->assertDef('good_id', false); // duplicate now not okay
+
+ $this->def = new HTMLPurifier_AttrDef_HTML_ID(true);
+
+ $this->assertDef('good_id'); // reference still okay
+
+ }
+
+ function testRegexp() {
+
+ $this->config->set('Attr.IDBlacklistRegexp', '/^g_/');
+
+ $this->assertDef('good_id');
+ $this->assertDef('g_bad_id', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/LengthTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/LengthTest.php
new file mode 100644
index 000000000..d165e30b5
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/LengthTest.php
@@ -0,0 +1,32 @@
+def = new HTMLPurifier_AttrDef_HTML_Length();
+ }
+
+ function test() {
+
+ // pixel check
+ parent::test();
+
+ // percent check
+ $this->assertDef('25%');
+
+ // Firefox maintains percent, so will we
+ $this->assertDef('0%');
+
+ // 0% <= percent <= 100%
+ $this->assertDef('-15%', '0%');
+ $this->assertDef('120%', '100%');
+
+ // fractional percents, apparently, aren't allowed
+ $this->assertDef('56.5%', '56%');
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/LinkTypesTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/LinkTypesTest.php
new file mode 100644
index 000000000..d90b65b1f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/LinkTypesTest.php
@@ -0,0 +1,21 @@
+def = new HTMLPurifier_AttrDef_HTML_LinkTypes('rel');
+ $this->config->set('Attr.AllowedRel', array('nofollow', 'foo'));
+
+ $this->assertDef('', false);
+ $this->assertDef('nofollow', true);
+ $this->assertDef('nofollow foo', true);
+ $this->assertDef('nofollow bar', 'nofollow');
+ $this->assertDef('bar', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/MultiLengthTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/MultiLengthTest.php
new file mode 100644
index 000000000..eb6f34011
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/MultiLengthTest.php
@@ -0,0 +1,28 @@
+def = new HTMLPurifier_AttrDef_HTML_MultiLength();
+ }
+
+ function test() {
+
+ // length check
+ parent::test();
+
+ $this->assertDef('*');
+ $this->assertDef('1*', '*');
+ $this->assertDef('56*');
+
+ $this->assertDef('**', false); // plain old bad
+
+ $this->assertDef('5.4*', '5*'); // no decimals
+ $this->assertDef('-3*', false); // no negatives
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/NmtokensTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/NmtokensTest.php
new file mode 100644
index 000000000..bb64ff6e2
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/NmtokensTest.php
@@ -0,0 +1,35 @@
+def = new HTMLPurifier_AttrDef_HTML_Nmtokens();
+ }
+
+ function testDefault() {
+
+ $this->assertDef('valid');
+ $this->assertDef('a0-_');
+ $this->assertDef('-valid');
+ $this->assertDef('_valid');
+ $this->assertDef('double valid');
+
+ $this->assertDef('0invalid', false);
+ $this->assertDef('-0', false);
+
+ // test conditional replacement
+ $this->assertDef('validassoc 0invalid', 'validassoc');
+
+ // test whitespace leniency
+ $this->assertDef(" double\nvalid\r", 'double valid');
+
+ // test case sensitivity
+ $this->assertDef('VALID');
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/PixelsTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/PixelsTest.php
new file mode 100644
index 000000000..08f25be64
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/HTML/PixelsTest.php
@@ -0,0 +1,45 @@
+def = new HTMLPurifier_AttrDef_HTML_Pixels();
+ }
+
+ function test() {
+
+ $this->assertDef('1');
+ $this->assertDef('0');
+
+ $this->assertDef('2px', '2'); // rm px suffix
+
+ $this->assertDef('dfs', false); // totally invalid value
+
+ // conceivably we could repair this value, but we won't for now
+ $this->assertDef('9in', false);
+
+ // test trim
+ $this->assertDef(' 45 ', '45');
+
+ // no negatives
+ $this->assertDef('-2', '0');
+
+ // remove empty
+ $this->assertDef('', false);
+
+ // round down
+ $this->assertDef('4.9', '4');
+
+ }
+
+ function test_make() {
+ $factory = new HTMLPurifier_AttrDef_HTML_Pixels();
+ $this->def = $factory->make('30');
+ $this->assertDef('25');
+ $this->assertDef('35', '30');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/IntegerTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/IntegerTest.php
new file mode 100644
index 000000000..a941e31ab
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/IntegerTest.php
@@ -0,0 +1,61 @@
+def = new HTMLPurifier_AttrDef_Integer();
+
+ $this->assertDef('0');
+ $this->assertDef('1');
+ $this->assertDef('-1');
+ $this->assertDef('-10');
+ $this->assertDef('14');
+ $this->assertDef('+24', '24');
+ $this->assertDef(' 14 ', '14');
+ $this->assertDef('-0', '0');
+
+ $this->assertDef('-1.4', false);
+ $this->assertDef('3.4', false);
+ $this->assertDef('asdf', false); // must not return zero
+ $this->assertDef('2in', false); // must not return zero
+
+ }
+
+ function assertRange($negative, $zero, $positive) {
+ $this->assertDef('-100', $negative);
+ $this->assertDef('-1', $negative);
+ $this->assertDef('0', $zero);
+ $this->assertDef('1', $positive);
+ $this->assertDef('42', $positive);
+ }
+
+ function testRange() {
+
+ $this->def = new HTMLPurifier_AttrDef_Integer(false);
+ $this->assertRange(false, true, true); // non-negative
+
+ $this->def = new HTMLPurifier_AttrDef_Integer(false, false);
+ $this->assertRange(false, false, true); // positive
+
+
+ // fringe cases
+
+ $this->def = new HTMLPurifier_AttrDef_Integer(false, false, false);
+ $this->assertRange(false, false, false); // allow none
+
+ $this->def = new HTMLPurifier_AttrDef_Integer(true, false, false);
+ $this->assertRange(true, false, false); // negative
+
+ $this->def = new HTMLPurifier_AttrDef_Integer(false, true, false);
+ $this->assertRange(false, true, false); // zero
+
+ $this->def = new HTMLPurifier_AttrDef_Integer(true, true, false);
+ $this->assertRange(true, true, false); // non-positive
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/LangTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/LangTest.php
new file mode 100644
index 000000000..c59175556
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/LangTest.php
@@ -0,0 +1,85 @@
+def = new HTMLPurifier_AttrDef_Lang();
+
+ // basic good uses
+ $this->assertDef('en');
+ $this->assertDef('en-us');
+
+ $this->assertDef(' en ', 'en'); // trim
+ $this->assertDef('EN', 'en'); // case insensitivity
+
+ // (thanks Eugen Pankratz for noticing the typos!)
+ $this->assertDef('En-Us-Edison', 'en-us-edison'); // complex ci
+
+ $this->assertDef('fr en', false); // multiple languages
+ $this->assertDef('%', false); // bad character
+
+ // test overlong language according to syntax
+ $this->assertDef('thisistoolongsoitgetscut', false);
+
+ // primary subtag rules
+ // I'm somewhat hesitant to allow x and i as primary language codes,
+ // because they usually are never used in real life. However,
+ // theoretically speaking, having them alone is permissable, so
+ // I'll be lenient. No XML parser is going to complain anyway.
+ $this->assertDef('x');
+ $this->assertDef('i');
+ // real world use-cases
+ $this->assertDef('x-klingon');
+ $this->assertDef('i-mingo');
+ // because the RFC only defines two and three letter primary codes,
+ // anything with a length of four or greater is invalid, despite
+ // the syntax stipulation of 1 to 8 characters. Because the RFC
+ // specifically states that this reservation is in order to allow
+ // for future versions to expand, the adoption of a new RFC will
+ // require these test cases to be rewritten, even if backwards-
+ // compatibility is largely retained (i.e. this is not forwards
+ // compatible)
+ $this->assertDef('four', false);
+ // for similar reasons, disallow any other one character language
+ $this->assertDef('f', false);
+
+ // second subtag rules
+ // one letter subtags prohibited until revision. This is, however,
+ // less volatile than the restrictions on the primary subtags.
+ // Also note that this test-case tests fix-behavior: chop
+ // off subtags until you get a valid language code.
+ $this->assertDef('en-a', 'en');
+ // however, x is a reserved single-letter subtag that is allowed
+ $this->assertDef('en-x', 'en-x');
+ // 2-8 chars are permitted, but have special meaning that cannot
+ // be checked without maintaining country code lookup tables (for
+ // two characters) or special registration tables (for all above).
+ $this->assertDef('en-uk', true);
+
+ // further subtag rules: only syntactic constraints
+ $this->assertDef('en-us-edison');
+ $this->assertDef('en-us-toolonghaha', 'en-us');
+ $this->assertDef('en-us-a-silly-long-one');
+
+ // rfc 3066 stipulates that if a three letter and a two letter code
+ // are available, the two letter one MUST be used. Without a language
+ // code lookup table, we cannot implement this functionality.
+
+ // although the HTML protocol, technically speaking, allows you to
+ // omit language tags, this implicitly means that the parent element's
+ // language is the one applicable, which, in some cases, is incorrect.
+ // Thus, we allow und, only slightly defying the RFC's SHOULD NOT
+ // designation.
+ $this->assertDef('und');
+
+ // because attributes only allow one language, mul is allowed, complying
+ // with the RFC's SHOULD NOT designation.
+ $this->assertDef('mul');
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/SwitchTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/SwitchTest.php
new file mode 100644
index 000000000..21bafe697
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/SwitchTest.php
@@ -0,0 +1,34 @@
+with = new HTMLPurifier_AttrDefMock();
+ $this->without = new HTMLPurifier_AttrDefMock();
+ $this->def = new HTMLPurifier_AttrDef_Switch('tag', $this->with, $this->without);
+ }
+
+ function testWith() {
+ $token = new HTMLPurifier_Token_Start('tag');
+ $this->context->register('CurrentToken', $token);
+ $this->with->expectOnce('validate');
+ $this->with->setReturnValue('validate', 'foo');
+ $this->assertDef('bar', 'foo');
+ }
+
+ function testWithout() {
+ $token = new HTMLPurifier_Token_Start('other-tag');
+ $this->context->register('CurrentToken', $token);
+ $this->without->expectOnce('validate');
+ $this->without->setReturnValue('validate', 'foo');
+ $this->assertDef('bar', 'foo');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/TextTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/TextTest.php
new file mode 100644
index 000000000..458008aa8
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/TextTest.php
@@ -0,0 +1,17 @@
+def = new HTMLPurifier_AttrDef_Text();
+
+ $this->assertDef('This is spiffy text!');
+ $this->assertDef(" Casual\tCDATA parse\ncheck. ", 'Casual CDATA parse check.');
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/Email/SimpleCheckTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/Email/SimpleCheckTest.php
new file mode 100644
index 000000000..c310347e9
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/Email/SimpleCheckTest.php
@@ -0,0 +1,13 @@
+def = new HTMLPurifier_AttrDef_URI_Email_SimpleCheck();
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/EmailHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/EmailHarness.php
new file mode 100644
index 000000000..594e2ce29
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/EmailHarness.php
@@ -0,0 +1,31 @@
+assertDef('bob@example.com');
+ $this->assertDef(' bob@example.com ', 'bob@example.com');
+ $this->assertDef('bob.thebuilder@example.net');
+ $this->assertDef('Bob_the_Builder-the-2nd@example.org');
+ $this->assertDef('Bob%20the%20Builder@white-space.test');
+
+ // extended format, with real name
+ //$this->assertDef('Bob%20Builder%20%3Cbobby.bob.bob@it.is.example.com%3E');
+ //$this->assertDef('Bob Builder ');
+
+ // time to fail
+ $this->assertDef('bob', false);
+ $this->assertDef('bob@home@work', false);
+ $this->assertDef('@example.com', false);
+ $this->assertDef('bob@', false);
+ $this->assertDef('', false);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/HostTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/HostTest.php
new file mode 100644
index 000000000..b5827718b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/HostTest.php
@@ -0,0 +1,53 @@
+def = new HTMLPurifier_AttrDef_URI_Host();
+
+ $this->assertDef('[2001:DB8:0:0:8:800:200C:417A]'); // IPv6
+ $this->assertDef('124.15.6.89'); // IPv4
+ $this->assertDef('www.google.com'); // reg-name
+
+ // more domain name tests
+ $this->assertDef('test.');
+ $this->assertDef('sub.test.');
+ $this->assertDef('.test', false);
+ $this->assertDef('ff');
+ $this->assertDef('1f', false);
+ $this->assertDef('-f', false);
+ $this->assertDef('f1');
+ $this->assertDef('f-', false);
+ $this->assertDef('sub.ff');
+ $this->assertDef('sub.1f', false);
+ $this->assertDef('sub.-f', false);
+ $this->assertDef('sub.f1');
+ $this->assertDef('sub.f-', false);
+ $this->assertDef('ff.top');
+ $this->assertDef('1f.top');
+ $this->assertDef('-f.top', false);
+ $this->assertDef('ff.top');
+ $this->assertDef('f1.top');
+ $this->assertDef('f-.top', false);
+
+ $this->assertDef("\xE4\xB8\xAD\xE6\x96\x87.com.cn", false);
+
+ }
+
+ function testIDNA() {
+ if (!$GLOBALS['HTMLPurifierTest']['Net_IDNA2']) {
+ return false;
+ }
+ $this->config->set('Core.EnableIDNA', true);
+ $this->assertDef("\xE4\xB8\xAD\xE6\x96\x87.com.cn", "xn--fiq228c.com.cn");
+ $this->assertDef("\xe2\x80\x85.com", false); // rejected
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/IPv4Test.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/IPv4Test.php
new file mode 100644
index 000000000..0a4eb17ba
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/IPv4Test.php
@@ -0,0 +1,25 @@
+def = new HTMLPurifier_AttrDef_URI_IPv4();
+
+ $this->assertDef('127.0.0.1'); // standard IPv4, loopback, non-routable
+ $this->assertDef('0.0.0.0'); // standard IPv4, unspecified, non-routable
+ $this->assertDef('255.255.255.255'); // standard IPv4
+
+ $this->assertDef('300.0.0.0', false); // standard IPv4, out of range
+ $this->assertDef('124.15.6.89/60', false); // standard IPv4, prefix not allowed
+
+ $this->assertDef('', false); // nothing
+
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/IPv6Test.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/IPv6Test.php
new file mode 100644
index 000000000..083e818aa
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URI/IPv6Test.php
@@ -0,0 +1,43 @@
+def = new HTMLPurifier_AttrDef_URI_IPv6();
+
+ $this->assertDef('2001:DB8:0:0:8:800:200C:417A'); // unicast, full
+ $this->assertDef('FF01:0:0:0:0:0:0:101'); // multicast, full
+ $this->assertDef('0:0:0:0:0:0:0:1'); // loopback, full
+ $this->assertDef('0:0:0:0:0:0:0:0'); // unspecified, full
+ $this->assertDef('2001:DB8::8:800:200C:417A'); // unicast, compressed
+ $this->assertDef('FF01::101'); // multicast, compressed
+
+ $this->assertDef('::1'); // loopback, compressed, non-routable
+ $this->assertDef('::'); // unspecified, compressed, non-routable
+ $this->assertDef('0:0:0:0:0:0:13.1.68.3'); // IPv4-compatible IPv6 address, full, deprecated
+ $this->assertDef('0:0:0:0:0:FFFF:129.144.52.38'); // IPv4-mapped IPv6 address, full
+ $this->assertDef('::13.1.68.3'); // IPv4-compatible IPv6 address, compressed, deprecated
+ $this->assertDef('::FFFF:129.144.52.38'); // IPv4-mapped IPv6 address, compressed
+ $this->assertDef('2001:0DB8:0000:CD30:0000:0000:0000:0000/60'); // full, with prefix
+ $this->assertDef('2001:0DB8::CD30:0:0:0:0/60'); // compressed, with prefix
+ $this->assertDef('2001:0DB8:0:CD30::/60'); // compressed, with prefix #2
+ $this->assertDef('::/128'); // compressed, unspecified address type, non-routable
+ $this->assertDef('::1/128'); // compressed, loopback address type, non-routable
+ $this->assertDef('FF00::/8'); // compressed, multicast address type
+ $this->assertDef('FE80::/10'); // compressed, link-local unicast, non-routable
+ $this->assertDef('FEC0::/10'); // compressed, site-local unicast, deprecated
+
+ $this->assertDef('2001:DB8:0:0:8:800:200C:417A:221', false); // unicast, full
+ $this->assertDef('FF01::101::2', false); //multicast, compressed
+ $this->assertDef('', false); // nothing
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URITest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URITest.php
new file mode 100644
index 000000000..3044367a2
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDef/URITest.php
@@ -0,0 +1,146 @@
+def = new HTMLPurifier_AttrDef_URI();
+ parent::setUp();
+ }
+
+ function testIntegration() {
+ $this->assertDef('http://www.google.com/');
+ $this->assertDef('http:', '');
+ $this->assertDef('http:/foo', '/foo');
+ $this->assertDef('javascript:bad_stuff();', false);
+ $this->assertDef('ftp://www.example.com/');
+ $this->assertDef('news:rec.alt');
+ $this->assertDef('nntp://news.example.com/324234');
+ $this->assertDef('mailto:bob@example.com');
+ }
+
+ function testIntegrationWithPercentEncoder() {
+ $this->assertDef(
+ 'http://www.example.com/%56%fc%GJ%5%FC',
+ 'http://www.example.com/V%FC%25GJ%255%FC'
+ );
+ }
+
+ function testPercentEncoding() {
+ $this->assertDef(
+ 'http:colon:mercenary',
+ 'colon%3Amercenary'
+ );
+ }
+
+ function testPercentEncodingPreserve() {
+ $this->assertDef(
+ 'http://www.example.com/abcABC123-_.!~*()\''
+ );
+ }
+
+ function testEmbeds() {
+ $this->def = new HTMLPurifier_AttrDef_URI(true);
+ $this->assertDef('http://sub.example.com/alas?foo=asd');
+ $this->assertDef('mailto:foo@example.com', false);
+ }
+
+ function testConfigMunge() {
+ $this->config->set('URI.Munge', 'http://www.google.com/url?q=%s');
+ $this->assertDef(
+ 'http://www.example.com/',
+ 'http://www.google.com/url?q=http%3A%2F%2Fwww.example.com%2F'
+ );
+ $this->assertDef('index.html');
+ $this->assertDef('javascript:foobar();', false);
+ }
+
+ function testDefaultSchemeRemovedInBlank() {
+ $this->assertDef('http:', '');
+ }
+
+ function testDefaultSchemeRemovedInRelativeURI() {
+ $this->assertDef('http:/foo/bar', '/foo/bar');
+ }
+
+ function testDefaultSchemeNotRemovedInAbsoluteURI() {
+ $this->assertDef('http://example.com/foo/bar');
+ }
+
+ function testAltSchemeNotRemoved() {
+ $this->assertDef('mailto:this-looks-like-a-path@example.com');
+ }
+
+ function testResolveNullSchemeAmbiguity() {
+ $this->assertDef('///foo', '/foo');
+ }
+
+ function testResolveNullSchemeDoubleAmbiguity() {
+ $this->config->set('URI.Host', 'example.com');
+ $this->assertDef('////foo', '//example.com//foo');
+ }
+
+ function testURIDefinitionValidation() {
+ $parser = new HTMLPurifier_URIParser();
+ $uri = $parser->parse('http://example.com');
+ $this->config->set('URI.DefinitionID', 'HTMLPurifier_AttrDef_URITest->testURIDefinitionValidation');
+
+ generate_mock_once('HTMLPurifier_URIDefinition');
+ $uri_def = new HTMLPurifier_URIDefinitionMock();
+ $uri_def->expectOnce('filter', array($uri, '*', '*'));
+ $uri_def->setReturnValue('filter', true, array($uri, '*', '*'));
+ $uri_def->expectOnce('postFilter', array($uri, '*', '*'));
+ $uri_def->setReturnValue('postFilter', true, array($uri, '*', '*'));
+ $uri_def->setup = true;
+
+ // Since definitions are no longer passed by reference, we need
+ // to muck around with the cache to insert our mock. This is
+ // technically a little bad, since the cache shouldn't change
+ // behavior, but I don't feel too good about letting users
+ // overload entire definitions.
+ generate_mock_once('HTMLPurifier_DefinitionCache');
+ $cache_mock = new HTMLPurifier_DefinitionCacheMock();
+ $cache_mock->setReturnValue('get', $uri_def);
+
+ generate_mock_once('HTMLPurifier_DefinitionCacheFactory');
+ $factory_mock = new HTMLPurifier_DefinitionCacheFactoryMock();
+ $old = HTMLPurifier_DefinitionCacheFactory::instance();
+ HTMLPurifier_DefinitionCacheFactory::instance($factory_mock);
+ $factory_mock->setReturnValue('create', $cache_mock);
+
+ $this->assertDef('http://example.com');
+
+ HTMLPurifier_DefinitionCacheFactory::instance($old);
+ }
+
+ function test_make() {
+ $factory = new HTMLPurifier_AttrDef_URI();
+ $def = $factory->make('');
+ $def2 = new HTMLPurifier_AttrDef_URI();
+ $this->assertIdentical($def, $def2);
+
+ $def = $factory->make('embedded');
+ $def2 = new HTMLPurifier_AttrDef_URI(true);
+ $this->assertIdentical($def, $def2);
+ }
+
+ /*
+ function test_validate_configWhitelist() {
+
+ $this->config->set('URI.HostPolicy', 'DenyAll');
+ $this->config->set('URI.HostWhitelist', array(null, 'google.com'));
+
+ $this->assertDef('http://example.com/fo/google.com', false);
+ $this->assertDef('server.txt');
+ $this->assertDef('ftp://www.google.com/?t=a');
+ $this->assertDef('http://google.com.tricky.spamsite.net', false);
+
+ }
+ */
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDefHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDefHarness.php
new file mode 100644
index 000000000..b45b0ca53
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDefHarness.php
@@ -0,0 +1,27 @@
+config = HTMLPurifier_Config::createDefault();
+ $this->context = new HTMLPurifier_Context();
+ }
+
+ // cannot be used for accumulator
+ function assertDef($string, $expect = true) {
+ // $expect can be a string or bool
+ $result = $this->def->validate($string, $this->config, $this->context);
+ if ($expect === true) {
+ $this->assertIdentical($string, $result);
+ } else {
+ $this->assertIdentical($expect, $result);
+ }
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrDefTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrDefTest.php
new file mode 100644
index 000000000..d7466e37d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrDefTest.php
@@ -0,0 +1,32 @@
+assertIdentical('', $def->parseCDATA(''));
+ $this->assertIdentical('', $def->parseCDATA("\t\n\r \t\t"));
+ $this->assertIdentical('foo', $def->parseCDATA("\t\n\r foo\t\t"));
+ $this->assertIdentical('translate to space', $def->parseCDATA("translate\nto\tspace"));
+
+ }
+
+ function test_make() {
+
+ $def = new HTMLPurifier_AttrDefTestable();
+ $def2 = $def->make('');
+ $this->assertIdentical($def, $def2);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BackgroundTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BackgroundTest.php
new file mode 100644
index 000000000..0730ab4bc
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BackgroundTest.php
@@ -0,0 +1,40 @@
+obj = new HTMLPurifier_AttrTransform_Background();
+ }
+
+ function testEmptyInput() {
+ $this->assertResult( array() );
+ }
+
+ function testBasicTransform() {
+ $this->assertResult(
+ array('background' => 'logo.png'),
+ array('style' => 'background-image:url(logo.png);')
+ );
+ }
+
+ function testPrependNewCSS() {
+ $this->assertResult(
+ array('background' => 'logo.png', 'style' => 'font-weight:bold'),
+ array('style' => 'background-image:url(logo.png);font-weight:bold')
+ );
+ }
+
+ function testLenientTreatmentOfInvalidInput() {
+ // notice that we rely on the CSS validator later to fix this invalid
+ // stuff
+ $this->assertResult(
+ array('background' => 'logo.png);foo:('),
+ array('style' => 'background-image:url(logo.png);foo:();')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BdoDirTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BdoDirTest.php
new file mode 100644
index 000000000..cdf6f8a9b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BdoDirTest.php
@@ -0,0 +1,30 @@
+obj = new HTMLPurifier_AttrTransform_BdoDir();
+ }
+
+ function testAddDefaultDir() {
+ $this->assertResult( array(), array('dir' => 'ltr') );
+ }
+
+ function testPreserveExistingDir() {
+ $this->assertResult( array('dir' => 'rtl') );
+ }
+
+ function testAlternateDefault() {
+ $this->config->set('Attr.DefaultTextDir', 'rtl');
+ $this->assertResult(
+ array(),
+ array('dir' => 'rtl')
+ );
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BgColorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BgColorTest.php
new file mode 100644
index 000000000..13567b74e
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BgColorTest.php
@@ -0,0 +1,44 @@
+obj = new HTMLPurifier_AttrTransform_BgColor();
+ }
+
+ function testEmptyInput() {
+ $this->assertResult( array() );
+ }
+
+ function testBasicTransform() {
+ $this->assertResult(
+ array('bgcolor' => '#000000'),
+ array('style' => 'background-color:#000000;')
+ );
+ }
+
+ function testPrependNewCSS() {
+ $this->assertResult(
+ array('bgcolor' => '#000000', 'style' => 'font-weight:bold'),
+ array('style' => 'background-color:#000000;font-weight:bold')
+ );
+ }
+
+ function testLenientTreatmentOfInvalidInput() {
+ // this may change when we natively support the datatype and
+ // validate its contents before forwarding it on
+ $this->assertResult(
+ array('bgcolor' => '#F00'),
+ array('style' => 'background-color:#F00;')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BoolToCSSTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BoolToCSSTest.php
new file mode 100644
index 000000000..73f9d6b86
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BoolToCSSTest.php
@@ -0,0 +1,38 @@
+obj = new HTMLPurifier_AttrTransform_BoolToCSS('foo', 'bar:3in;');
+ }
+
+ function testEmptyInput() {
+ $this->assertResult( array() );
+ }
+
+ function testBasicTransform() {
+ $this->assertResult(
+ array('foo' => 'foo'),
+ array('style' => 'bar:3in;')
+ );
+ }
+
+ function testIgnoreValueOfBooleanAttribute() {
+ $this->assertResult(
+ array('foo' => 'no'),
+ array('style' => 'bar:3in;')
+ );
+ }
+
+ function testPrependCSS() {
+ $this->assertResult(
+ array('foo' => 'foo', 'style' => 'background-color:#F00;'),
+ array('style' => 'bar:3in;background-color:#F00;')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BorderTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BorderTest.php
new file mode 100644
index 000000000..d10aa28e6
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/BorderTest.php
@@ -0,0 +1,38 @@
+obj = new HTMLPurifier_AttrTransform_Border();
+ }
+
+ function testEmptyInput() {
+ $this->assertResult( array() );
+ }
+
+ function testBasicTransform() {
+ $this->assertResult(
+ array('border' => '1'),
+ array('style' => 'border:1px solid;')
+ );
+ }
+
+ function testLenientTreatmentOfInvalidInput() {
+ $this->assertResult(
+ array('border' => '10%'),
+ array('style' => 'border:10%px solid;')
+ );
+ }
+
+ function testPrependNewCSS() {
+ $this->assertResult(
+ array('border' => '23', 'style' => 'font-weight:bold;'),
+ array('style' => 'border:23px solid;font-weight:bold;')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/EnumToCSSTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/EnumToCSSTest.php
new file mode 100644
index 000000000..f0381fe88
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/EnumToCSSTest.php
@@ -0,0 +1,73 @@
+obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+ 'left' => 'text-align:left;',
+ 'right' => 'text-align:right;'
+ ));
+ }
+
+ function testEmptyInput() {
+ $this->assertResult( array() );
+ }
+
+ function testPreserveArraysWithoutInterestingAttributes() {
+ $this->assertResult( array('style' => 'font-weight:bold;') );
+ }
+
+ function testConvertAlignLeft() {
+ $this->assertResult(
+ array('align' => 'left'),
+ array('style' => 'text-align:left;')
+ );
+ }
+
+ function testConvertAlignRight() {
+ $this->assertResult(
+ array('align' => 'right'),
+ array('style' => 'text-align:right;')
+ );
+ }
+
+ function testRemoveInvalidAlign() {
+ $this->assertResult(
+ array('align' => 'invalid'),
+ array()
+ );
+ }
+
+ function testPrependNewCSS() {
+ $this->assertResult(
+ array('align' => 'left', 'style' => 'font-weight:bold;'),
+ array('style' => 'text-align:left;font-weight:bold;')
+ );
+
+ }
+
+ function testCaseInsensitive() {
+ $this->obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+ 'right' => 'text-align:right;'
+ ));
+ $this->assertResult(
+ array('align' => 'RIGHT'),
+ array('style' => 'text-align:right;')
+ );
+ }
+
+ function testCaseSensitive() {
+ $this->obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+ 'right' => 'text-align:right;'
+ ), true);
+ $this->assertResult(
+ array('align' => 'RIGHT'),
+ array()
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/ImgRequiredTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/ImgRequiredTest.php
new file mode 100644
index 000000000..99f0a03e9
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/ImgRequiredTest.php
@@ -0,0 +1,55 @@
+obj = new HTMLPurifier_AttrTransform_ImgRequired();
+ }
+
+ function testAddMissingAttr() {
+ $this->config->set('Core.RemoveInvalidImg', false);
+ $this->assertResult(
+ array(),
+ array('src' => '', 'alt' => 'Invalid image')
+ );
+ }
+
+ function testAlternateDefaults() {
+ $this->config->set('Attr.DefaultInvalidImage', 'blank.png');
+ $this->config->set('Attr.DefaultInvalidImageAlt', 'Pawned!');
+ $this->config->set('Attr.DefaultImageAlt', 'not pawned');
+ $this->config->set('Core.RemoveInvalidImg', false);
+ $this->assertResult(
+ array(),
+ array('src' => 'blank.png', 'alt' => 'Pawned!')
+ );
+ }
+
+ function testGenerateAlt() {
+ $this->assertResult(
+ array('src' => '/path/to/foobar.png'),
+ array('src' => '/path/to/foobar.png', 'alt' => 'foobar.png')
+ );
+ }
+
+ function testAddDefaultSrc() {
+ $this->config->set('Core.RemoveInvalidImg', false);
+ $this->assertResult(
+ array('alt' => 'intrigue'),
+ array('alt' => 'intrigue', 'src' => '')
+ );
+ }
+
+ function testAddDefaultAlt() {
+ $this->config->set('Attr.DefaultImageAlt', 'default');
+ $this->assertResult(
+ array('src' => ''),
+ array('src' => '', 'alt' => 'default')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/ImgSpaceTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/ImgSpaceTest.php
new file mode 100644
index 000000000..42e8738e4
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/ImgSpaceTest.php
@@ -0,0 +1,55 @@
+obj = new HTMLPurifier_AttrTransform_ImgSpace('vspace');
+ }
+
+ function testEmptyInput() {
+ $this->assertResult( array() );
+ }
+
+ function testVerticalBasicUsage() {
+ $this->assertResult(
+ array('vspace' => '1'),
+ array('style' => 'margin-top:1px;margin-bottom:1px;')
+ );
+ }
+
+ function testLenientHandlingOfInvalidInput() {
+ $this->assertResult(
+ array('vspace' => '10%'),
+ array('style' => 'margin-top:10%px;margin-bottom:10%px;')
+ );
+ }
+
+ function testPrependNewCSS() {
+ $this->assertResult(
+ array('vspace' => '23', 'style' => 'font-weight:bold;'),
+ array('style' => 'margin-top:23px;margin-bottom:23px;font-weight:bold;')
+ );
+ }
+
+ function testHorizontalBasicUsage() {
+ $this->obj = new HTMLPurifier_AttrTransform_ImgSpace('hspace');
+ $this->assertResult(
+ array('hspace' => '1'),
+ array('style' => 'margin-left:1px;margin-right:1px;')
+ );
+ }
+
+ function testInvalidConstructionParameter() {
+ $this->expectError('ispace is not valid space attribute');
+ $this->obj = new HTMLPurifier_AttrTransform_ImgSpace('ispace');
+ $this->assertResult(
+ array('ispace' => '1'),
+ array()
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/InputTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/InputTest.php
new file mode 100644
index 000000000..2603ff1be
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/InputTest.php
@@ -0,0 +1,94 @@
+obj = new HTMLPurifier_AttrTransform_Input();
+ }
+
+ function testEmptyInput() {
+ $this->assertResult(array());
+ }
+
+ function testInvalidCheckedWithEmpty() {
+ $this->assertResult(array('checked' => 'checked'), array());
+ }
+
+ function testInvalidCheckedWithPassword() {
+ $this->assertResult(array(
+ 'checked' => 'checked',
+ 'type' => 'password'
+ ), array(
+ 'type' => 'password'
+ ));
+ }
+
+ function testValidCheckedWithUcCheckbox() {
+ $this->assertResult(array(
+ 'checked' => 'checked',
+ 'type' => 'CHECKBOX',
+ 'value' => 'bar',
+ ));
+ }
+
+ function testInvalidMaxlength() {
+ $this->assertResult(array(
+ 'maxlength' => '10',
+ 'type' => 'checkbox',
+ 'value' => 'foo',
+ ), array(
+ 'type' => 'checkbox',
+ 'value' => 'foo',
+ ));
+ }
+
+ function testValidMaxLength() {
+ $this->assertResult(array(
+ 'maxlength' => '10',
+ ));
+ }
+
+ // these two are really bad test-cases
+
+ function testSizeWithCheckbox() {
+ $this->assertResult(array(
+ 'type' => 'checkbox',
+ 'value' => 'foo',
+ 'size' => '100px',
+ ), array(
+ 'type' => 'checkbox',
+ 'value' => 'foo',
+ 'size' => '100',
+ ));
+ }
+
+ function testSizeWithText() {
+ $this->assertResult(array(
+ 'type' => 'password',
+ 'size' => '100px', // spurious value, to indicate no validation takes place
+ ), array(
+ 'type' => 'password',
+ 'size' => '100px',
+ ));
+ }
+
+ function testInvalidSrc() {
+ $this->assertResult(array(
+ 'src' => 'img.png',
+ ), array());
+ }
+
+ function testMissingValue() {
+ $this->assertResult(array(
+ 'type' => 'checkbox',
+ ), array(
+ 'type' => 'checkbox',
+ 'value' => '',
+ ));
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/LangTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/LangTest.php
new file mode 100644
index 000000000..960ad20a0
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/LangTest.php
@@ -0,0 +1,46 @@
+obj = new HTMLPurifier_AttrTransform_Lang();
+ }
+
+ function testEmptyInput() {
+ $this->assertResult(array());
+ }
+
+ function testCopyLangToXMLLang() {
+ $this->assertResult(
+ array('lang' => 'en'),
+ array('lang' => 'en', 'xml:lang' => 'en')
+ );
+ }
+
+ function testPreserveAttributes() {
+ $this->assertResult(
+ array('src' => 'vert.png', 'lang' => 'fr'),
+ array('src' => 'vert.png', 'lang' => 'fr', 'xml:lang' => 'fr')
+ );
+ }
+
+ function testCopyXMLLangToLang() {
+ $this->assertResult(
+ array('xml:lang' => 'en'),
+ array('xml:lang' => 'en', 'lang' => 'en')
+ );
+ }
+
+ function testXMLLangOverridesLang() {
+ $this->assertResult(
+ array('lang' => 'fr', 'xml:lang' => 'de'),
+ array('lang' => 'de', 'xml:lang' => 'de')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/LengthTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/LengthTest.php
new file mode 100644
index 000000000..3fbaa0ccf
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/LengthTest.php
@@ -0,0 +1,45 @@
+obj = new HTMLPurifier_AttrTransform_Length('width');
+ }
+
+ function testEmptyInput() {
+ $this->assertResult( array() );
+ }
+
+ function testTransformPixel() {
+ $this->assertResult(
+ array('width' => '10'),
+ array('style' => 'width:10px;')
+ );
+ }
+
+ function testTransformPercentage() {
+ $this->assertResult(
+ array('width' => '10%'),
+ array('style' => 'width:10%;')
+ );
+ }
+
+ function testPrependNewCSS() {
+ $this->assertResult(
+ array('width' => '10%', 'style' => 'font-weight:bold'),
+ array('style' => 'width:10%;font-weight:bold')
+ );
+ }
+
+ function testLenientTreatmentOfInvalidInput() {
+ $this->assertResult(
+ array('width' => 'asdf'),
+ array('style' => 'width:asdf;')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/NameSyncTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/NameSyncTest.php
new file mode 100644
index 000000000..bae4a8d03
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/NameSyncTest.php
@@ -0,0 +1,40 @@
+obj = new HTMLPurifier_AttrTransform_NameSync();
+ $this->accumulator = new HTMLPurifier_IDAccumulator();
+ $this->context->register('IDAccumulator', $this->accumulator);
+ $this->config->set('Attr.EnableID', true);
+ }
+
+ function testEmpty() {
+ $this->assertResult( array() );
+ }
+
+ function testAllowSame() {
+ $this->assertResult(
+ array('name' => 'free', 'id' => 'free')
+ );
+ }
+
+ function testAllowDifferent() {
+ $this->assertResult(
+ array('name' => 'tryit', 'id' => 'thisgood')
+ );
+ }
+
+ function testCheckName() {
+ $this->accumulator->add('notok');
+ $this->assertResult(
+ array('name' => 'notok', 'id' => 'ok'),
+ array('id' => 'ok')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/NameTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/NameTest.php
new file mode 100644
index 000000000..10e121238
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransform/NameTest.php
@@ -0,0 +1,31 @@
+obj = new HTMLPurifier_AttrTransform_Name();
+ }
+
+ function testEmpty() {
+ $this->assertResult( array() );
+ }
+
+ function testTransformNameToID() {
+ $this->assertResult(
+ array('name' => 'free'),
+ array('id' => 'free')
+ );
+ }
+
+ function testExistingIDOverridesName() {
+ $this->assertResult(
+ array('name' => 'tryit', 'id' => 'tobad'),
+ array('id' => 'tobad')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransformHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransformHarness.php
new file mode 100644
index 000000000..d43c0108f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransformHarness.php
@@ -0,0 +1,13 @@
+func = 'transform';
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTransformTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransformTest.php
new file mode 100644
index 000000000..71a788580
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTransformTest.php
@@ -0,0 +1,45 @@
+prependCSS($attr, 'style:new;');
+ $this->assertIdentical(array('style' => 'style:new;'), $attr);
+
+ $attr = array('style' => 'style:original;');
+ $t->prependCSS($attr, 'style:new;');
+ $this->assertIdentical(array('style' => 'style:new;style:original;'), $attr);
+
+ $attr = array('style' => 'style:original;', 'misc' => 'un-related');
+ $t->prependCSS($attr, 'style:new;');
+ $this->assertIdentical(array('style' => 'style:new;style:original;', 'misc' => 'un-related'), $attr);
+
+ }
+
+ function test_confiscateAttr() {
+
+ $t = new HTMLPurifier_AttrTransformTestable();
+
+ $attr = array('flavor' => 'sweet');
+ $this->assertIdentical('sweet', $t->confiscateAttr($attr, 'flavor'));
+ $this->assertIdentical(array(), $attr);
+
+ $attr = array('flavor' => 'sweet');
+ $this->assertIdentical(null, $t->confiscateAttr($attr, 'color'));
+ $this->assertIdentical(array('flavor' => 'sweet'), $attr);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrTypesTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrTypesTest.php
new file mode 100644
index 000000000..d1ae43709
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrTypesTest.php
@@ -0,0 +1,26 @@
+assertIdentical(
+ $types->get('CDATA'),
+ new HTMLPurifier_AttrDef_Text()
+ );
+
+ $this->expectError('Cannot retrieve undefined attribute type foobar');
+ $types->get('foobar');
+
+ $this->assertIdentical(
+ $types->get('Enum#foo,bar'),
+ new HTMLPurifier_AttrDef_Enum(array('foo', 'bar'))
+ );
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/AttrValidator_ErrorsTest.php b/lib/htmlpurifier/tests/HTMLPurifier/AttrValidator_ErrorsTest.php
new file mode 100644
index 000000000..307d3292b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/AttrValidator_ErrorsTest.php
@@ -0,0 +1,66 @@
+language = HTMLPurifier_LanguageFactory::instance()->create($config, $this->context);
+ $this->context->register('Locale', $this->language);
+ $this->collector = new HTMLPurifier_ErrorCollector($this->context);
+ $this->context->register('Generator', new HTMLPurifier_Generator($config, $this->context));
+ }
+
+ protected function invoke($input) {
+ $validator = new HTMLPurifier_AttrValidator();
+ $validator->validateToken($input, $this->config, $this->context);
+ }
+
+ function testAttributesTransformedGlobalPre() {
+ $def = $this->config->getHTMLDefinition(true);
+ generate_mock_once('HTMLPurifier_AttrTransform');
+ $transform = new HTMLPurifier_AttrTransformMock();
+ $input = array('original' => 'value');
+ $output = array('class' => 'value'); // must be valid
+ $transform->setReturnValue('transform', $output, array($input, new AnythingExpectation(), new AnythingExpectation()));
+ $def->info_attr_transform_pre[] = $transform;
+
+ $token = new HTMLPurifier_Token_Start('span', $input, 1);
+ $this->invoke($token);
+
+ $result = $this->collector->getRaw();
+ $expect = array(
+ array(1, E_NOTICE, 'Attributes on transformed from original to class', array()),
+ );
+ $this->assertIdentical($result, $expect);
+ }
+
+ function testAttributesTransformedLocalPre() {
+ $this->config->set('HTML.TidyLevel', 'heavy');
+ $input = array('align' => 'right');
+ $output = array('style' => 'text-align:right;');
+ $token = new HTMLPurifier_Token_Start('p', $input, 1);
+ $this->invoke($token);
+ $result = $this->collector->getRaw();
+ $expect = array(
+ array(1, E_NOTICE, 'Attributes on transformed from align to style', array()),
+ );
+ $this->assertIdentical($result, $expect);
+ }
+
+ // too lazy to check for global post and global pre
+
+ function testAttributeRemoved() {
+ $token = new HTMLPurifier_Token_Start('p', array('foobar' => 'right'), 1);
+ $this->invoke($token);
+ $result = $this->collector->getRaw();
+ $expect = array(
+ array(1, E_ERROR, 'foobar attribute on
removed', array()),
+ );
+ $this->assertIdentical($result, $expect);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/ChameleonTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/ChameleonTest.php
new file mode 100644
index 000000000..82493f40e
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/ChameleonTest.php
@@ -0,0 +1,40 @@
+obj = new HTMLPurifier_ChildDef_Chameleon(
+ 'b | i', // allowed only when in inline context
+ 'b | i | div' // allowed only when in block context
+ );
+ $this->context->register('IsInline', $this->isInline);
+ }
+
+ function testInlineAlwaysAllowed() {
+ $this->isInline = true;
+ $this->assertResult(
+ 'Allowed. '
+ );
+ }
+
+ function testBlockNotAllowedInInline() {
+ $this->isInline = true;
+ $this->assertResult(
+ '
Not allowed.
', ''
+ );
+ }
+
+ function testBlockAllowedInNonInline() {
+ $this->isInline = false;
+ $this->assertResult(
+ 'Allowed.
'
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/CustomTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/CustomTest.php
new file mode 100644
index 000000000..5b138a3c1
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/CustomTest.php
@@ -0,0 +1,89 @@
+obj = new HTMLPurifier_ChildDef_Custom('(a,b?,c*,d+,(a,b)*)');
+
+ $this->assertEqual($this->obj->elements, array('a' => true,
+ 'b' => true, 'c' => true, 'd' => true));
+
+ $this->assertResult('', false);
+ $this->assertResult(' ', false);
+
+ $this->assertResult(' ');
+ $this->assertResult('Dob foo '.
+ 'foo ');
+
+ }
+
+ function testNesting() {
+ $this->obj = new HTMLPurifier_ChildDef_Custom('(a,b,(c|d))+');
+ $this->assertEqual($this->obj->elements, array('a' => true,
+ 'b' => true, 'c' => true, 'd' => true));
+ $this->assertResult('', false);
+ $this->assertResult(' ');
+ $this->assertResult(' ', false);
+ }
+
+ function testNestedEitherOr() {
+ $this->obj = new HTMLPurifier_ChildDef_Custom('b,(a|(c|d))+');
+ $this->assertEqual($this->obj->elements, array('a' => true,
+ 'b' => true, 'c' => true, 'd' => true));
+ $this->assertResult('', false);
+ $this->assertResult(' ');
+ $this->assertResult(' ');
+ $this->assertResult(' ');
+ $this->assertResult(' ', false);
+ }
+
+ function testNestedQuantifier() {
+ $this->obj = new HTMLPurifier_ChildDef_Custom('(b,c+)*');
+ $this->assertEqual($this->obj->elements, array('b' => true, 'c' => true));
+ $this->assertResult('');
+ $this->assertResult(' ');
+ $this->assertResult(' ');
+ $this->assertResult(' ');
+ $this->assertResult(' ', false);
+ }
+
+ function testEitherOr() {
+
+ $this->obj = new HTMLPurifier_ChildDef_Custom('a|b');
+ $this->assertEqual($this->obj->elements, array('a' => true, 'b' => true));
+ $this->assertResult('', false);
+ $this->assertResult(' ');
+ $this->assertResult(' ');
+ $this->assertResult(' ', false);
+
+ }
+
+ function testCommafication() {
+
+ $this->obj = new HTMLPurifier_ChildDef_Custom('a,b');
+ $this->assertEqual($this->obj->elements, array('a' => true, 'b' => true));
+ $this->assertResult(' ');
+ $this->assertResult(' ', false);
+
+ }
+
+ function testPcdata() {
+ $this->obj = new HTMLPurifier_ChildDef_Custom('#PCDATA,a');
+ $this->assertEqual($this->obj->elements, array('#PCDATA' => true, 'a' => true));
+ $this->assertResult('foo ');
+ $this->assertResult(' ', false);
+ }
+
+ function testWhitespace() {
+ $this->obj = new HTMLPurifier_ChildDef_Custom('a');
+ $this->assertEqual($this->obj->elements, array('a' => true));
+ $this->assertResult('foo ', false);
+ $this->assertResult(' ');
+ $this->assertResult(' ');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/ListTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/ListTest.php
new file mode 100644
index 000000000..02dcab0fb
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/ListTest.php
@@ -0,0 +1,50 @@
+obj = new HTMLPurifier_ChildDef_List();
+ }
+
+ function testEmptyInput() {
+ $this->assertResult('', false);
+ }
+
+ function testSingleLi() {
+ $this->assertResult(' ');
+ }
+
+ function testSomeLi() {
+ $this->assertResult('asdf ');
+ }
+
+ function testIllegal() {
+ // XXX actually this never gets triggered in practice
+ $this->assertResult(' ', ' ');
+ }
+
+ function testOlAtBeginning() {
+ $this->assertResult(' ', ' ');
+ }
+
+ function testOlAtBeginningWithOtherJunk() {
+ $this->assertResult(' ', ' ');
+ }
+
+ function testOlInMiddle() {
+ $this->assertResult('Foo Bar ', 'FooBar ');
+ }
+
+ function testMultipleOl() {
+ $this->assertResult(' ', ' ');
+ }
+
+ function testUlAtBeginning() {
+ $this->assertResult('', ' ');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/OptionalTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/OptionalTest.php
new file mode 100644
index 000000000..a5f34f7b1
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/OptionalTest.php
@@ -0,0 +1,33 @@
+obj = new HTMLPurifier_ChildDef_Optional('b | i');
+ }
+
+ function testBasicUsage() {
+ $this->assertResult('Bold text ', 'Bold text ');
+ }
+
+ function testRemoveForbiddenText() {
+ $this->assertResult('Not allowed text', '');
+ }
+
+ function testEmpty() {
+ $this->assertResult('');
+ }
+
+ function testWhitespace() {
+ $this->assertResult(' ');
+ }
+
+ function testMultipleWhitespace() {
+ $this->assertResult(' ');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/RequiredTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/RequiredTest.php
new file mode 100644
index 000000000..8bb4f45ee
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/RequiredTest.php
@@ -0,0 +1,73 @@
+assertIdentical($def->elements,
+ array(
+ 'foobar' => true
+ ,'bang' => true
+ ,'gizmo' => true
+ ));
+ }
+
+ function testPrepareArray() {
+ $def = new HTMLPurifier_ChildDef_Required(array('href', 'src'));
+ $this->assertIdentical($def->elements,
+ array(
+ 'href' => true
+ ,'src' => true
+ ));
+ }
+
+ function setUp() {
+ parent::setUp();
+ $this->obj = new HTMLPurifier_ChildDef_Required('dt | dd');
+ }
+
+ function testEmptyInput() {
+ $this->assertResult('', false);
+ }
+
+ function testRemoveIllegalTagsAndElements() {
+ $this->assertResult(
+ 'Term Text in an illegal location'.
+ 'Definition Illegal tag ',
+ 'Term Definition ');
+ $this->assertResult('How do you do!', false);
+ }
+
+ function testIgnoreWhitespace() {
+ // whitespace shouldn't trigger it
+ $this->assertResult("\nDefinition ");
+ }
+
+ function testPreserveWhitespaceAfterRemoval() {
+ $this->assertResult(
+ 'Definition ',
+ 'Definition '
+ );
+ }
+
+ function testDeleteNodeIfOnlyWhitespace() {
+ $this->assertResult("\t ", false);
+ }
+
+ function testPCDATAAllowed() {
+ $this->obj = new HTMLPurifier_ChildDef_Required('#PCDATA | b');
+ $this->assertResult('Out Bold text ', 'Out Bold text ');
+ }
+
+ function testPCDATAAllowedWithEscaping() {
+ $this->obj = new HTMLPurifier_ChildDef_Required('#PCDATA | b');
+ $this->config->set('Core.EscapeInvalidChildren', true);
+ $this->assertResult(
+ 'Out Bold text ',
+ 'Out Bold text <img />'
+ );
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/StrictBlockquoteTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/StrictBlockquoteTest.php
new file mode 100644
index 000000000..52594b1a0
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/StrictBlockquoteTest.php
@@ -0,0 +1,83 @@
+obj = new HTMLPurifier_ChildDef_StrictBlockquote('div | p');
+ }
+
+ function testEmptyInput() {
+ $this->assertResult('');
+ }
+
+ function testPreserveValidP() {
+ $this->assertResult('Valid
');
+ }
+
+ function testPreserveValidDiv() {
+ $this->assertResult('Still valid
');
+ }
+
+ function testWrapTextWithP() {
+ $this->assertResult('Needs wrap', 'Needs wrap
');
+ }
+
+ function testNoWrapForWhitespaceOrValidElements() {
+ $this->assertResult('Do not wrap
Whitespace
');
+ }
+
+ function testWrapTextNextToValidElements() {
+ $this->assertResult(
+ 'Wrap'. 'Do not wrap
',
+ 'Wrap
Do not wrap
'
+ );
+ }
+
+ function testWrapInlineElements() {
+ $this->assertResult(
+ 'Do not
'.'Wrap ',
+ 'Do not
Wrap
'
+ );
+ }
+
+ function testWrapAndRemoveInvalidTags() {
+ $this->assertResult(
+ 'Not allowed Paragraph.Hmm.
',
+ 'Not allowedParagraph.
Hmm.
'
+ );
+ }
+
+ function testWrapComplicatedSring() {
+ $this->assertResult(
+ $var = 'He said perhaps we should nuke them.',
+ "$var
"
+ );
+ }
+
+ function testWrapAndRemoveInvalidTagsComplex() {
+ $this->assertResult(
+ 'Bar People Conniving.'. 'Fools!
',
+ 'Bar'. 'People Conniving.
Fools!
'
+ );
+ }
+
+ function testAlternateWrapper() {
+ $this->config->set('HTML.BlockWrapper', 'div');
+ $this->assertResult('Needs wrap', 'Needs wrap
');
+
+ }
+
+ function testError() {
+ $this->expectError('Cannot use non-block element as block wrapper');
+ $this->obj = new HTMLPurifier_ChildDef_StrictBlockquote('div | p');
+ $this->config->set('HTML.BlockWrapper', 'dav');
+ $this->config->set('Cache.DefinitionImpl', null);
+ $this->assertResult('Needs wrap', 'Needs wrap
');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/TableTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/TableTest.php
new file mode 100644
index 000000000..2f72d187a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ChildDef/TableTest.php
@@ -0,0 +1,75 @@
+obj = new HTMLPurifier_ChildDef_Table();
+ }
+
+ function testEmptyInput() {
+ $this->assertResult('', false);
+ }
+
+ function testSingleRow() {
+ $this->assertResult(' ');
+ }
+
+ function testComplexContents() {
+ $this->assertResult(''.
+ 'asdf ');
+ $this->assertResult(' ');
+ }
+
+ function testReorderContents() {
+ $this->assertResult(
+ '1 ',
+ '1 ');
+ }
+
+ function testXhtml11Illegal() {
+ $this->assertResult(
+ 'a a ',
+ 'a a '
+ );
+ }
+
+ function testTrOverflowAndClose() {
+ $this->assertResult(
+ 'a b c d ',
+ 'a b c d '
+ );
+ }
+
+ function testDuplicateProcessing() {
+ $this->assertResult(
+ '1 1 ',
+ '1 1 '
+ );
+ }
+
+ function testRemoveText() {
+ $this->assertResult('foo', false);
+ }
+
+ function testStickyWhitespaceOnTr() {
+ $this->config->set('Output.Newline', "\n");
+ $this->assertResult("\n \n \n ");
+ }
+
+ function testStickyWhitespaceOnTSection() {
+ $this->config->set('Output.Newline', "\n");
+ $this->assertResult(
+ "\n\t \n\t\t \n\t\t\t",
+ "\n\t\t \n\t \n\t\t\t"
+ );
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ChildDefHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/ChildDefHarness.php
new file mode 100644
index 000000000..4b4d2f5b6
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ChildDefHarness.php
@@ -0,0 +1,16 @@
+obj = null;
+ $this->func = 'validateChildren';
+ $this->to_tokens = true;
+ $this->to_html = true;
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ComplexHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/ComplexHarness.php
new file mode 100644
index 000000000..8e806c63c
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ComplexHarness.php
@@ -0,0 +1,106 @@
+lexer = new HTMLPurifier_Lexer_DirectLex();
+ parent::__construct();
+ }
+
+ /**
+ * Asserts a specific result from a one parameter + config/context function
+ * @param $input Input parameter
+ * @param $expect Expectation
+ * @param $config Configuration array in form of Ns.Directive => Value.
+ * Has no effect if $this->config is set.
+ * @param $context_array Context array in form of Key => Value or an actual
+ * context object.
+ */
+ protected function assertResult($input, $expect = true) {
+
+ if ($this->to_tokens && is_string($input)) {
+ // $func may cause $input to change, so "clone" another copy
+ // to sacrifice
+ $input = $this->tokenize($temp = $input);
+ $input_c = $this->tokenize($temp);
+ } else {
+ $input_c = $input;
+ }
+
+ // call the function
+ $func = $this->func;
+ $result = $this->obj->$func($input_c, $this->config, $this->context);
+
+ // test a bool result
+ if (is_bool($result)) {
+ $this->assertIdentical($expect, $result);
+ return;
+ } elseif (is_bool($expect)) {
+ $expect = $input;
+ }
+
+ if ($this->to_html) {
+ $result = $this->generate($result);
+ if (is_array($expect)) {
+ $expect = $this->generate($expect);
+ }
+ }
+ $this->assertIdentical($expect, $result);
+
+ if ($expect !== $result) {
+ echo '' . var_dump($result) . ' ';
+ }
+
+ }
+
+ /**
+ * Tokenize HTML into tokens, uses member variables for common variables
+ */
+ protected function tokenize($html) {
+ return $this->lexer->tokenizeHTML($html, $this->config, $this->context);
+ }
+
+ /**
+ * Generate textual HTML from tokens
+ */
+ protected function generate($tokens) {
+ $generator = new HTMLPurifier_Generator($this->config, $this->context);
+ return $generator->generateFromTokens($tokens);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/InterchangeTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/InterchangeTest.php
new file mode 100644
index 000000000..0d539ea2c
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/InterchangeTest.php
@@ -0,0 +1,21 @@
+interchange = new HTMLPurifier_ConfigSchema_Interchange();
+ }
+
+ function testAddDirective() {
+ $v = new HTMLPurifier_ConfigSchema_Interchange_Directive();
+ $v->id = new HTMLPurifier_ConfigSchema_Interchange_Id('Namespace.Directive');
+ $this->interchange->addDirective($v);
+ $this->assertIdentical($v, $this->interchange->directives['Namespace.Directive']);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/aliasesAliasCollision.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/aliasesAliasCollision.vtest
new file mode 100644
index 000000000..ed3857c40
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/aliasesAliasCollision.vtest
@@ -0,0 +1,13 @@
+ERROR: Alias 'Ns.BothWantThisName' in aliases in directive 'Ns.Dir2' collides with alias for directive 'Ns.Dir'
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: int
+DEFAULT: 3
+ALIASES: Ns.BothWantThisName
+----
+Ns.Dir2
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 'a'
+ALIASES: Ns.BothWantThisName
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/aliasesDirectiveCollision.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/aliasesDirectiveCollision.vtest
new file mode 100644
index 000000000..582a481a4
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/aliasesDirectiveCollision.vtest
@@ -0,0 +1,12 @@
+ERROR: Alias 'Ns.Innocent' in aliases in directive 'Ns.Dir' collides with another directive
+----
+Ns.Innocent
+DESCRIPTION: Innocent directive
+TYPE: int
+DEFAULT: 3
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 'a'
+ALIASES: Ns.Innocent
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/allowedIsString.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/allowedIsString.vtest
new file mode 100644
index 000000000..9ecc5f930
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/allowedIsString.vtest
@@ -0,0 +1,7 @@
+ERROR: Value 3 in allowed in directive 'Ns.Dir' must be a string
+----
+ID: Ns.Dir
+TYPE: string
+DESCRIPTION: Description
+DEFAULT: 'asdf'
+ALLOWED: 'asdf', 3
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/allowedNotEmpty.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/allowedNotEmpty.vtest
new file mode 100644
index 000000000..1e08fab0d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/allowedNotEmpty.vtest
@@ -0,0 +1,7 @@
+ERROR: Allowed in directive 'Ns.Dir' must not be empty
+----
+ID: Ns.Dir
+TYPE: string
+DESCRIPTION: Description
+DEFAULT: 'asdf'
+ALLOWED:
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultIsAllowed.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultIsAllowed.vtest
new file mode 100644
index 000000000..ef1944707
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultIsAllowed.vtest
@@ -0,0 +1,7 @@
+ERROR: Default in directive 'Ns.Dir' must be an allowed value
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 'a'
+ALLOWED: 'b'
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultNullWithAllowed.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultNullWithAllowed.vtest
new file mode 100644
index 000000000..7ba3c85c0
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultNullWithAllowed.vtest
@@ -0,0 +1,5 @@
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string/null
+DEFAULT: null
+ALLOWED: 'a'
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultType.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultType.vtest
new file mode 100644
index 000000000..79ea043ac
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/defaultType.vtest
@@ -0,0 +1,6 @@
+ERROR: Expected type string, got integer in DEFAULT in directive hash 'Ns.Dir'
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 0
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/descriptionNotEmpty.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/descriptionNotEmpty.vtest
new file mode 100644
index 000000000..d09ddc77b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/descriptionNotEmpty.vtest
@@ -0,0 +1,5 @@
+ERROR: Description in directive 'Ns.Dir' must not be empty
+----
+Ns.Dir
+TYPE: int
+DEFAULT: 0
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/ignoreNamespace.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/ignoreNamespace.vtest
new file mode 100644
index 000000000..3fc28d3a4
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/ignoreNamespace.vtest
@@ -0,0 +1,3 @@
+Ns
+DESCRIPTION: Namespace
+
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeDefined.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeDefined.vtest
new file mode 100644
index 000000000..4bb8abeb2
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeDefined.vtest
@@ -0,0 +1,5 @@
+ERROR: TYPE in directive hash 'Ns.Dir' not defined
+----
+Ns.Dir
+DESCRIPTION: Notice that TYPE is missing
+DEFAULT: 0
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeExists.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeExists.vtest
new file mode 100644
index 000000000..f9851f536
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeExists.vtest
@@ -0,0 +1,6 @@
+ERROR: Invalid type 'foobar' in DEFAULT in directive hash 'Ns.Dir'
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: foobar
+DEFAULT: 0
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeWithAllowedIsStringType.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeWithAllowedIsStringType.vtest
new file mode 100644
index 000000000..bf4e2b21b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeWithAllowedIsStringType.vtest
@@ -0,0 +1,7 @@
+ERROR: Type in directive 'Ns.Dir' must be a string type when used with allowed or value aliases
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: int
+DEFAULT: 3
+ALLOWED: 1, 2, 3
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeWithValueAliasesIsStringType.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeWithValueAliasesIsStringType.vtest
new file mode 100644
index 000000000..59cf4333a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/typeWithValueAliasesIsStringType.vtest
@@ -0,0 +1,7 @@
+ERROR: Type in directive 'Ns.Dir' must be a string type when used with allowed or value aliases
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: int
+DEFAULT: 3
+VALUE-ALIASES: 2 => 3
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/unique.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/unique.vtest
new file mode 100644
index 000000000..c83649e8d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/unique.vtest
@@ -0,0 +1,11 @@
+ERROR: Cannot redefine directive 'Ns.Dir'
+----
+ID: Ns.Dir
+DESCRIPTION: Version 1
+TYPE: int
+DEFAULT: 0
+----
+ID: Ns.Dir
+DESCRIPTION: Version 2
+TYPE: int
+DEFAULT: 0
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesAliasIsString.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesAliasIsString.vtest
new file mode 100644
index 000000000..b9f28eee1
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesAliasIsString.vtest
@@ -0,0 +1,7 @@
+ERROR: Alias 3 in valueAliases in directive 'Ns.Dir' must be a string
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 'a'
+VALUE-ALIASES: 3 => 'a'
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesAliasNotAllowed.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesAliasNotAllowed.vtest
new file mode 100644
index 000000000..ef9c14883
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesAliasNotAllowed.vtest
@@ -0,0 +1,8 @@
+ERROR: Alias 'b' in valueAliases in directive 'Ns.Dir' must not be an allowed value
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 'a'
+ALLOWED: 'a', 'b', 'c'
+VALUE-ALIASES: 'b' => 'c'
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesNotAliasSelf.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesNotAliasSelf.vtest
new file mode 100644
index 000000000..4c417fd5f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesNotAliasSelf.vtest
@@ -0,0 +1,7 @@
+ERROR: Alias 'bar' in valueAliases in directive 'Ns.Dir' must not be an alias to itself
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 'foo'
+VALUE-ALIASES: 'bar' => 'bar'
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesRealAllowed.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesRealAllowed.vtest
new file mode 100644
index 000000000..89502d34a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesRealAllowed.vtest
@@ -0,0 +1,8 @@
+ERROR: Alias 'c' in valueAliases in directive 'Ns.Dir' must be an alias to an allowed value
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 'a'
+ALLOWED: 'a', 'b'
+VALUE-ALIASES: 'c' => 'd'
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesRealIsString.vtest b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesRealIsString.vtest
new file mode 100644
index 000000000..92ec197dc
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/Validator/directive/valueAliasesRealIsString.vtest
@@ -0,0 +1,7 @@
+ERROR: Alias target 3 from alias 'b' in valueAliases in directive 'Ns.Dir' must be a string
+----
+Ns.Dir
+DESCRIPTION: Directive
+TYPE: string
+DEFAULT: 'a'
+VALUE-ALIASES: 'b' => 3
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorAtomTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorAtomTest.php
new file mode 100644
index 000000000..38625136e
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorAtomTest.php
@@ -0,0 +1,92 @@
+expectException(new HTMLPurifier_ConfigSchema_Exception($msg));
+ }
+
+ protected function makeAtom($value) {
+ $obj = new stdClass();
+ $obj->property = $value;
+ // Note that 'property' and 'context' are magic wildcard values
+ return new HTMLPurifier_ConfigSchema_ValidatorAtom('context', $obj, 'property');
+ }
+
+ function testAssertIsString() {
+ $this->makeAtom('foo')->assertIsString();
+ }
+
+ function testAssertIsStringFail() {
+ $this->expectValidationException("Property in context must be a string");
+ $this->makeAtom(3)->assertIsString();
+ }
+
+ function testAssertNotNull() {
+ $this->makeAtom('foo')->assertNotNull();
+ }
+
+ function testAssertNotNullFail() {
+ $this->expectValidationException("Property in context must not be null");
+ $this->makeAtom(null)->assertNotNull();
+ }
+
+ function testAssertAlnum() {
+ $this->makeAtom('foo2')->assertAlnum();
+ }
+
+ function testAssertAlnumFail() {
+ $this->expectValidationException("Property in context must be alphanumeric");
+ $this->makeAtom('%a')->assertAlnum();
+ }
+
+ function testAssertAlnumFailIsString() {
+ $this->expectValidationException("Property in context must be a string");
+ $this->makeAtom(3)->assertAlnum();
+ }
+
+ function testAssertNotEmpty() {
+ $this->makeAtom('foo')->assertNotEmpty();
+ }
+
+ function testAssertNotEmptyFail() {
+ $this->expectValidationException("Property in context must not be empty");
+ $this->makeAtom('')->assertNotEmpty();
+ }
+
+ function testAssertIsBool() {
+ $this->makeAtom(false)->assertIsBool();
+ }
+
+ function testAssertIsBoolFail() {
+ $this->expectValidationException("Property in context must be a boolean");
+ $this->makeAtom('0')->assertIsBool();
+ }
+
+ function testAssertIsArray() {
+ $this->makeAtom(array())->assertIsArray();
+ }
+
+ function testAssertIsArrayFail() {
+ $this->expectValidationException("Property in context must be an array");
+ $this->makeAtom('asdf')->assertIsArray();
+ }
+
+
+ function testAssertIsLookup() {
+ $this->makeAtom(array('foo' => true))->assertIsLookup();
+ }
+
+ function testAssertIsLookupFail() {
+ $this->expectValidationException("Property in context must be a lookup array");
+ $this->makeAtom(array('foo' => 4))->assertIsLookup();
+ }
+
+ function testAssertIsLookupFailIsArray() {
+ $this->expectValidationException("Property in context must be an array");
+ $this->makeAtom('asdf')->assertIsLookup();
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorTest.php
new file mode 100644
index 000000000..9cbf36e2d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorTest.php
@@ -0,0 +1,101 @@
+validator = new HTMLPurifier_ConfigSchema_Validator();
+ $this->interchange = new HTMLPurifier_ConfigSchema_Interchange();
+ }
+
+ function testDirectiveIntegrityViolation() {
+ $d = $this->makeDirective('Ns.Dir');
+ $d->id = new HTMLPurifier_ConfigSchema_Interchange_Id('Ns.Dir2');
+ $this->expectValidationException("Integrity violation: key 'Ns.Dir' does not match internal id 'Ns.Dir2'");
+ $this->validator->validate($this->interchange);
+ }
+
+ function testDirectiveTypeNotEmpty() {
+ $d = $this->makeDirective('Ns.Dir');
+ $d->default = 0;
+ $d->description = 'Description';
+
+ $this->expectValidationException("Type in directive 'Ns.Dir' must not be empty");
+ $this->validator->validate($this->interchange);
+ }
+
+ function testDirectiveDefaultInvalid() {
+ $d = $this->makeDirective('Ns.Dir');
+ $d->default = 'asdf';
+ $d->type = 'int';
+ $d->description = 'Description';
+
+ $this->expectValidationException("Default in directive 'Ns.Dir' had error: Expected type int, got string");
+ $this->validator->validate($this->interchange);
+ }
+
+ function testDirectiveIdIsString() {
+ $d = $this->makeDirective(3);
+ $d->default = 0;
+ $d->type = 'int';
+ $d->description = 'Description';
+
+ $this->expectValidationException("Key in id '3' in directive '3' must be a string");
+ $this->validator->validate($this->interchange);
+ }
+
+ function testDirectiveTypeAllowsNullIsBool() {
+ $d = $this->makeDirective('Ns.Dir');
+ $d->default = 0;
+ $d->type = 'int';
+ $d->description = 'Description';
+ $d->typeAllowsNull = 'yes';
+
+ $this->expectValidationException("TypeAllowsNull in directive 'Ns.Dir' must be a boolean");
+ $this->validator->validate($this->interchange);
+ }
+
+ function testDirectiveValueAliasesIsArray() {
+ $d = $this->makeDirective('Ns.Dir');
+ $d->default = 'a';
+ $d->type = 'string';
+ $d->description = 'Description';
+ $d->valueAliases = 2;
+
+ $this->expectValidationException("ValueAliases in directive 'Ns.Dir' must be an array");
+ $this->validator->validate($this->interchange);
+ }
+
+ function testDirectiveAllowedIsLookup() {
+ $d = $this->makeDirective('Ns.Dir');
+ $d->default = 'foo';
+ $d->type = 'string';
+ $d->description = 'Description';
+ $d->allowed = array('foo' => 1);
+
+ $this->expectValidationException("Allowed in directive 'Ns.Dir' must be a lookup array");
+ $this->validator->validate($this->interchange);
+ }
+
+ // helper functions
+
+
+ protected function makeDirective($key) {
+ $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
+ $directive->id = new HTMLPurifier_ConfigSchema_Interchange_Id($key);
+ $this->interchange->addDirective($directive);
+ return $directive;
+ }
+
+ protected function expectValidationException($msg) {
+ $this->expectException(new HTMLPurifier_ConfigSchema_Exception($msg));
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorTestCase.php b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorTestCase.php
new file mode 100644
index 000000000..87fa14d0d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchema/ValidatorTestCase.php
@@ -0,0 +1,44 @@
+_path = $path;
+ $this->_parser = new HTMLPurifier_StringHashParser();
+ $this->_builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
+ parent::__construct($path);
+ }
+
+ public function setup() {
+ $this->validator = new HTMLPurifier_ConfigSchema_Validator();
+ }
+
+ function testValidator() {
+ $hashes = $this->_parser->parseMultiFile($this->_path);
+ $interchange = new HTMLPurifier_ConfigSchema_Interchange();
+ $error = null;
+ foreach ($hashes as $hash) {
+ if (!isset($hash['ID'])) {
+ if (isset($hash['ERROR'])) {
+ $this->expectException(
+ new HTMLPurifier_ConfigSchema_Exception($hash['ERROR'])
+ );
+ }
+ continue;
+ }
+ $this->_builder->build($interchange, new HTMLPurifier_StringHash($hash));
+ }
+ $this->validator->validate($interchange);
+ $this->pass();
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchemaTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchemaTest.php
new file mode 100644
index 000000000..dc3bf99eb
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigSchemaTest.php
@@ -0,0 +1,99 @@
+schema = new HTMLPurifier_ConfigSchema();
+ }
+
+ function test_define() {
+ $this->schema->add('Car.Seats', 5, 'int', false);
+
+ $this->assertIdentical($this->schema->defaults['Car.Seats'], 5);
+ $this->assertIdentical($this->schema->info['Car.Seats']->type, HTMLPurifier_VarParser::INT);
+
+ $this->schema->add('Car.Age', null, 'int', true);
+
+ $this->assertIdentical($this->schema->defaults['Car.Age'], null);
+ $this->assertIdentical($this->schema->info['Car.Age']->type, HTMLPurifier_VarParser::INT);
+
+ }
+
+ function test_defineAllowedValues() {
+ $this->schema->add('QuantumNumber.Spin', 0.5, 'float', false);
+ $this->schema->add('QuantumNumber.Current', 's', 'string', false);
+ $this->schema->add('QuantumNumber.Difficulty', null, 'string', true);
+
+ $this->schema->addAllowedValues( // okay, since default is null
+ 'QuantumNumber.Difficulty', array('easy' => true, 'medium' => true, 'hard' => true)
+ );
+
+ $this->assertIdentical($this->schema->defaults['QuantumNumber.Difficulty'], null);
+ $this->assertIdentical($this->schema->info['QuantumNumber.Difficulty']->type, HTMLPurifier_VarParser::STRING);
+ $this->assertIdentical($this->schema->info['QuantumNumber.Difficulty']->allow_null, true);
+ $this->assertIdentical($this->schema->info['QuantumNumber.Difficulty']->allowed,
+ array(
+ 'easy' => true,
+ 'medium' => true,
+ 'hard' => true
+ )
+ );
+
+ }
+
+ function test_defineValueAliases() {
+ $this->schema->add('Abbrev.HTH', 'Happy to Help', 'string', false);
+ $this->schema->addAllowedValues(
+ 'Abbrev.HTH', array(
+ 'Happy to Help' => true,
+ 'Hope that Helps' => true,
+ 'HAIL THE HAND!' => true,
+ )
+ );
+ $this->schema->addValueAliases(
+ 'Abbrev.HTH', array(
+ 'happy' => 'Happy to Help',
+ 'hope' => 'Hope that Helps'
+ )
+ );
+ $this->schema->addValueAliases( // delayed addition
+ 'Abbrev.HTH', array(
+ 'hail' => 'HAIL THE HAND!'
+ )
+ );
+
+ $this->assertIdentical($this->schema->defaults['Abbrev.HTH'], 'Happy to Help');
+ $this->assertIdentical($this->schema->info['Abbrev.HTH']->type, HTMLPurifier_VarParser::STRING);
+ $this->assertIdentical($this->schema->info['Abbrev.HTH']->allowed,
+ array(
+ 'Happy to Help' => true,
+ 'Hope that Helps' => true,
+ 'HAIL THE HAND!' => true
+ )
+ );
+ $this->assertIdentical($this->schema->info['Abbrev.HTH']->aliases,
+ array(
+ 'happy' => 'Happy to Help',
+ 'hope' => 'Hope that Helps',
+ 'hail' => 'HAIL THE HAND!'
+ )
+ );
+
+ }
+
+ function testAlias() {
+ $this->schema->add('Home.Rug', 3, 'int', false);
+ $this->schema->addAlias('Home.Carpet', 'Home.Rug');
+
+ $this->assertTrue(!isset($this->schema->defaults['Home.Carpet']));
+ $this->assertIdentical($this->schema->info['Home.Carpet']->key, 'Home.Rug');
+ $this->assertIdentical($this->schema->info['Home.Carpet']->isAlias, true);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-create.ini b/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-create.ini
new file mode 100644
index 000000000..31412f99a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-create.ini
@@ -0,0 +1,4 @@
+[Cake]
+Sprinkles = 42
+
+; vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-finalize.ini b/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-finalize.ini
new file mode 100644
index 000000000..3ab185fad
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-finalize.ini
@@ -0,0 +1,4 @@
+[Poem]
+Meter = alexandrine
+
+; vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-loadIni.ini b/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-loadIni.ini
new file mode 100644
index 000000000..cfa5a907f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest-loadIni.ini
@@ -0,0 +1,6 @@
+[Shortcut]
+Copy = q
+Cut = t
+Paste = p
+
+; vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest.php
new file mode 100644
index 000000000..3d36fc057
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ConfigTest.php
@@ -0,0 +1,557 @@
+schema = new HTMLPurifier_ConfigSchema();
+ }
+
+ // test functionality based on ConfigSchema
+
+ function testNormal() {
+ $this->schema->add('Element.Abbr', 'H', 'string', false);
+ $this->schema->add('Element.Name', 'hydrogen', 'istring', false);
+ $this->schema->add('Element.Number', 1, 'int', false);
+ $this->schema->add('Element.Mass', 1.00794, 'float', false);
+ $this->schema->add('Element.Radioactive', false, 'bool', false);
+ $this->schema->add('Element.Isotopes', array(1 => true, 2 => true, 3 => true), 'lookup', false);
+ $this->schema->add('Element.Traits', array('nonmetallic', 'odorless', 'flammable'), 'list', false);
+ $this->schema->add('Element.IsotopeNames', array(1 => 'protium', 2 => 'deuterium', 3 => 'tritium'), 'hash', false);
+ $this->schema->add('Element.Object', new stdClass(), 'mixed', false);
+
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->autoFinalize = false;
+ $config->chatty = false;
+
+ // test default value retrieval
+ $this->assertIdentical($config->get('Element.Abbr'), 'H');
+ $this->assertIdentical($config->get('Element.Name'), 'hydrogen');
+ $this->assertIdentical($config->get('Element.Number'), 1);
+ $this->assertIdentical($config->get('Element.Mass'), 1.00794);
+ $this->assertIdentical($config->get('Element.Radioactive'), false);
+ $this->assertIdentical($config->get('Element.Isotopes'), array(1 => true, 2 => true, 3 => true));
+ $this->assertIdentical($config->get('Element.Traits'), array('nonmetallic', 'odorless', 'flammable'));
+ $this->assertIdentical($config->get('Element.IsotopeNames'), array(1 => 'protium', 2 => 'deuterium', 3 => 'tritium'));
+ $this->assertIdentical($config->get('Element.Object'), new stdClass());
+
+ // test setting values
+ $config->set('Element.Abbr', 'Pu');
+ $config->set('Element.Name', 'PLUTONIUM'); // test decaps
+ $config->set('Element.Number', '94'); // test parsing
+ $config->set('Element.Mass', '244.'); // test parsing
+ $config->set('Element.Radioactive', true);
+ $config->set('Element.Isotopes', array(238, 239)); // test inversion
+ $config->set('Element.Traits', 'nuclear, heavy, actinide'); // test parsing
+ $config->set('Element.IsotopeNames', array(238 => 'Plutonium-238', 239 => 'Plutonium-239'));
+ $config->set('Element.Object', false); // unmodeled
+
+ $this->expectError('Cannot set undefined directive Element.Metal to value');
+ $config->set('Element.Metal', true);
+
+ $this->expectError('Value for Element.Radioactive is of invalid type, should be bool');
+ $config->set('Element.Radioactive', 'very');
+
+ // test value retrieval
+ $this->assertIdentical($config->get('Element.Abbr'), 'Pu');
+ $this->assertIdentical($config->get('Element.Name'), 'plutonium');
+ $this->assertIdentical($config->get('Element.Number'), 94);
+ $this->assertIdentical($config->get('Element.Mass'), 244.);
+ $this->assertIdentical($config->get('Element.Radioactive'), true);
+ $this->assertIdentical($config->get('Element.Isotopes'), array(238 => true, 239 => true));
+ $this->assertIdentical($config->get('Element.Traits'), array('nuclear', 'heavy', 'actinide'));
+ $this->assertIdentical($config->get('Element.IsotopeNames'), array(238 => 'Plutonium-238', 239 => 'Plutonium-239'));
+ $this->assertIdentical($config->get('Element.Object'), false);
+
+ $this->expectError('Cannot retrieve value of undefined directive Element.Metal');
+ $config->get('Element.Metal');
+
+ }
+
+ function testEnumerated() {
+
+ // case sensitive
+ $this->schema->add('Instrument.Manufacturer', 'Yamaha', 'string', false);
+ $this->schema->addAllowedValues('Instrument.Manufacturer', array(
+ 'Yamaha' => true, 'Conn-Selmer' => true, 'Vandoren' => true,
+ 'Laubin' => true, 'Buffet' => true, 'other' => true));
+ $this->schema->addValueAliases('Instrument.Manufacturer', array(
+ 'Selmer' => 'Conn-Selmer'));
+
+ // case insensitive
+ $this->schema->add('Instrument.Family', 'woodwind', 'istring', false);
+ $this->schema->addAllowedValues('Instrument.Family', array(
+ 'brass' => true, 'woodwind' => true, 'percussion' => true,
+ 'string' => true, 'keyboard' => true, 'electronic' => true));
+ $this->schema->addValueAliases('Instrument.Family', array(
+ 'synth' => 'electronic'));
+
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->autoFinalize = false;
+ $config->chatty = false;
+
+ // case sensitive
+
+ $config->set('Instrument.Manufacturer', 'Vandoren');
+ $this->assertIdentical($config->get('Instrument.Manufacturer'), 'Vandoren');
+
+ $config->set('Instrument.Manufacturer', 'Selmer');
+ $this->assertIdentical($config->get('Instrument.Manufacturer'), 'Conn-Selmer');
+
+ $this->expectError('Value not supported, valid values are: Yamaha, Conn-Selmer, Vandoren, Laubin, Buffet, other');
+ $config->set('Instrument.Manufacturer', 'buffet');
+
+ // case insensitive
+
+ $config->set('Instrument.Family', 'brass');
+ $this->assertIdentical($config->get('Instrument.Family'), 'brass');
+
+ $config->set('Instrument.Family', 'PERCUSSION');
+ $this->assertIdentical($config->get('Instrument.Family'), 'percussion');
+
+ $config->set('Instrument.Family', 'synth');
+ $this->assertIdentical($config->get('Instrument.Family'), 'electronic');
+
+ $config->set('Instrument.Family', 'Synth');
+ $this->assertIdentical($config->get('Instrument.Family'), 'electronic');
+
+ }
+
+ function testNull() {
+
+ $this->schema->add('ReportCard.English', null, 'string', true);
+ $this->schema->add('ReportCard.Absences', 0, 'int', false);
+
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->autoFinalize = false;
+ $config->chatty = false;
+
+ $config->set('ReportCard.English', 'B-');
+ $this->assertIdentical($config->get('ReportCard.English'), 'B-');
+
+ $config->set('ReportCard.English', null); // not yet graded
+ $this->assertIdentical($config->get('ReportCard.English'), null);
+
+ // error
+ $this->expectError('Value for ReportCard.Absences is of invalid type, should be int');
+ $config->set('ReportCard.Absences', null);
+
+ }
+
+ function testAliases() {
+
+ $this->schema->add('Home.Rug', 3, 'int', false);
+ $this->schema->addAlias('Home.Carpet', 'Home.Rug');
+
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->autoFinalize = false;
+ $config->chatty = false;
+
+ $this->assertIdentical($config->get('Home.Rug'), 3);
+
+ $this->expectError('Cannot get value from aliased directive, use real name Home.Rug');
+ $config->get('Home.Carpet');
+
+ $this->expectError('Home.Carpet is an alias, preferred directive name is Home.Rug');
+ $config->set('Home.Carpet', 999);
+ $this->assertIdentical($config->get('Home.Rug'), 999);
+
+ }
+
+ // test functionality based on method
+
+ function test_getBatch() {
+
+ $this->schema->add('Variables.TangentialAcceleration', 'a_tan', 'string', false);
+ $this->schema->add('Variables.AngularAcceleration', 'alpha', 'string', false);
+
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->autoFinalize = false;
+ $config->chatty = false;
+
+ // grab a namespace
+ $this->assertIdentical(
+ $config->getBatch('Variables'),
+ array(
+ 'TangentialAcceleration' => 'a_tan',
+ 'AngularAcceleration' => 'alpha'
+ )
+ );
+
+ // grab a non-existant namespace
+ $this->expectError('Cannot retrieve undefined namespace Constants');
+ $config->getBatch('Constants');
+
+ }
+
+ function test_loadIni() {
+
+ $this->schema->add('Shortcut.Copy', 'c', 'istring', false);
+ $this->schema->add('Shortcut.Paste', 'v', 'istring', false);
+ $this->schema->add('Shortcut.Cut', 'x', 'istring', false);
+
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->autoFinalize = false;
+
+ $config->loadIni(dirname(__FILE__) . '/ConfigTest-loadIni.ini');
+
+ $this->assertIdentical($config->get('Shortcut.Copy'), 'q');
+ $this->assertIdentical($config->get('Shortcut.Paste'), 'p');
+ $this->assertIdentical($config->get('Shortcut.Cut'), 't');
+
+ }
+
+ function test_getHTMLDefinition() {
+
+ // we actually want to use the old copy, because the definition
+ // generation routines have dependencies on configuration values
+
+ $config = HTMLPurifier_Config::createDefault();
+ $config->set('HTML.Doctype', 'XHTML 1.0 Strict');
+ $config->autoFinalize = false;
+
+ $def = $config->getCSSDefinition();
+ $this->assertIsA($def, 'HTMLPurifier_CSSDefinition');
+
+ $def = $config->getHTMLDefinition();
+ $def2 = $config->getHTMLDefinition();
+ $this->assertIsA($def, 'HTMLPurifier_HTMLDefinition');
+ $this->assertTrue($def === $def2);
+ $this->assertTrue($def->setup);
+
+ $old_def = clone $def2;
+
+ $config->set('HTML.Doctype', 'HTML 4.01 Transitional');
+ $def = $config->getHTMLDefinition();
+ $this->assertIsA($def, 'HTMLPurifier_HTMLDefinition');
+ $this->assertTrue($def !== $old_def);
+ $this->assertTrue($def->setup);
+
+ }
+
+ function test_getHTMLDefinition_deprecatedRawError() {
+ $config = HTMLPurifier_Config::createDefault();
+ $config->chatty = false;
+ // test deprecated retrieval of raw definition
+ $config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->test_getHTMLDefinition()');
+ $config->set('HTML.DefinitionRev', 3);
+ $this->expectError("Useless DefinitionID declaration");
+ $def = $config->getHTMLDefinition(true);
+ $this->assertEqual(false, $def->setup);
+
+ // auto initialization
+ $config->getHTMLDefinition();
+ $this->assertTrue($def->setup);
+ }
+
+ function test_getHTMLDefinition_optimizedRawError() {
+ $this->expectException(new HTMLPurifier_Exception("Cannot set optimized = true when raw = false"));
+ $config = HTMLPurifier_Config::createDefault();
+ $config->getHTMLDefinition(false, true);
+ }
+
+ function test_getHTMLDefinition_rawAfterSetupError() {
+ $this->expectException(new HTMLPurifier_Exception("Cannot retrieve raw definition after it has already been setup"));
+ $config = HTMLPurifier_Config::createDefault();
+ $config->chatty = false;
+ $config->getHTMLDefinition();
+ $config->getHTMLDefinition(true);
+ }
+
+ function test_getHTMLDefinition_inconsistentOptimizedError() {
+ $this->expectError("Useless DefinitionID declaration");
+ $this->expectException(new HTMLPurifier_Exception("Inconsistent use of optimized and unoptimized raw definition retrievals"));
+ $config = HTMLPurifier_Config::create(array('HTML.DefinitionID' => 'HTMLPurifier_ConfigTest->test_getHTMLDefinition_inconsistentOptimizedError'));
+ $config->chatty = false;
+ $config->getHTMLDefinition(true, false);
+ $config->getHTMLDefinition(true, true);
+ }
+
+ function test_getHTMLDefinition_inconsistentOptimizedError2() {
+ $this->expectException(new HTMLPurifier_Exception("Inconsistent use of optimized and unoptimized raw definition retrievals"));
+ $config = HTMLPurifier_Config::create(array('HTML.DefinitionID' => 'HTMLPurifier_ConfigTest->test_getHTMLDefinition_inconsistentOptimizedError2'));
+ $config->chatty = false;
+ $config->getHTMLDefinition(true, true);
+ $config->getHTMLDefinition(true, false);
+ }
+
+ function test_getHTMLDefinition_rawError() {
+ $config = HTMLPurifier_Config::createDefault();
+ $this->expectException(new HTMLPurifier_Exception('Cannot retrieve raw version without specifying %HTML.DefinitionID'));
+ $def = $config->getHTMLDefinition(true, true);
+ }
+
+ function test_getCSSDefinition() {
+ $config = HTMLPurifier_Config::createDefault();
+ $def = $config->getCSSDefinition();
+ $this->assertIsA($def, 'HTMLPurifier_CSSDefinition');
+ }
+
+ function test_getDefinition() {
+ $this->schema->add('Cache.DefinitionImpl', null, 'string', true);
+ $config = new HTMLPurifier_Config($this->schema);
+ $this->expectException(new HTMLPurifier_Exception("Definition of Crust type not supported"));
+ $config->getDefinition('Crust');
+ }
+
+ function test_loadArray() {
+ // setup a few dummy namespaces/directives for our testing
+ $this->schema->add('Zoo.Aadvark', 0, 'int', false);
+ $this->schema->add('Zoo.Boar', 0, 'int', false);
+ $this->schema->add('Zoo.Camel', 0, 'int', false);
+ $this->schema->add('Zoo.Others', array(), 'list', false);
+
+ $config_manual = new HTMLPurifier_Config($this->schema);
+ $config_loadabbr = new HTMLPurifier_Config($this->schema);
+ $config_loadfull = new HTMLPurifier_Config($this->schema);
+
+ $config_manual->set('Zoo.Aadvark', 3);
+ $config_manual->set('Zoo.Boar', 5);
+ $config_manual->set('Zoo.Camel', 2000); // that's a lotta camels!
+ $config_manual->set('Zoo.Others', array('Peacock', 'Dodo')); // wtf!
+
+ // condensed form
+ $config_loadabbr->loadArray(array(
+ 'Zoo.Aadvark' => 3,
+ 'Zoo.Boar' => 5,
+ 'Zoo.Camel' => 2000,
+ 'Zoo.Others' => array('Peacock', 'Dodo')
+ ));
+
+ // fully expanded form
+ $config_loadfull->loadArray(array(
+ 'Zoo' => array(
+ 'Aadvark' => 3,
+ 'Boar' => 5,
+ 'Camel' => 2000,
+ 'Others' => array('Peacock', 'Dodo')
+ )
+ ));
+
+ $this->assertIdentical($config_manual, $config_loadabbr);
+ $this->assertIdentical($config_manual, $config_loadfull);
+
+ }
+
+ function test_create() {
+
+ $this->schema->add('Cake.Sprinkles', 666, 'int', false);
+ $this->schema->add('Cake.Flavor', 'vanilla', 'string', false);
+
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->set('Cake.Sprinkles', 42);
+
+ // test flat pass-through
+ $created_config = HTMLPurifier_Config::create($config, $this->schema);
+ $this->assertIdentical($config, $created_config);
+
+ // test loadArray
+ $created_config = HTMLPurifier_Config::create(array('Cake.Sprinkles' => 42), $this->schema);
+ $this->assertIdentical($config, $created_config);
+
+ // test loadIni
+ $created_config = HTMLPurifier_Config::create(dirname(__FILE__) . '/ConfigTest-create.ini', $this->schema);
+ $this->assertIdentical($config, $created_config);
+
+ }
+
+ function test_finalize() {
+
+ // test finalization
+
+ $this->schema->add('Poem.Meter', 'iambic', 'string', false);
+
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->autoFinalize = false;
+ $config->chatty = false;
+
+ $config->set('Poem.Meter', 'irregular');
+
+ $config->finalize();
+
+ $this->expectError('Cannot set directive after finalization');
+ $config->set('Poem.Meter', 'vedic');
+
+ $this->expectError('Cannot load directives after finalization');
+ $config->loadArray(array('Poem.Meter' => 'octosyllable'));
+
+ $this->expectError('Cannot load directives after finalization');
+ $config->loadIni(dirname(__FILE__) . '/ConfigTest-finalize.ini');
+
+ }
+
+ function test_loadArrayFromForm() {
+
+ $this->schema->add('Pancake.Mix', 'buttermilk', 'string', false);
+ $this->schema->add('Pancake.Served', true, 'bool', false);
+ $this->schema->add('Toppings.Syrup', true, 'bool', false);
+ $this->schema->add('Toppings.Flavor', 'maple', 'string', false);
+ $this->schema->add('Toppings.Strawberries', 3, 'int', false);
+ $this->schema->add('Toppings.Calories', 2000, 'int', true);
+ $this->schema->add('Toppings.DefinitionID', null, 'string', true);
+ $this->schema->add('Toppings.DefinitionRev', 1, 'int', false);
+ $this->schema->add('Toppings.Protected', 1, 'int', false);
+
+ $get = array(
+ 'breakfast' => array(
+ 'Pancake.Mix' => 'nasty',
+ 'Pancake.Served' => '0',
+ 'Toppings.Syrup' => '0',
+ 'Toppings.Flavor' => "juice",
+ 'Toppings.Strawberries' => '999',
+ 'Toppings.Calories' => '',
+ 'Null_Toppings.Calories' => '1',
+ 'Toppings.DefinitionID' => '',
+ 'Toppings.DefinitionRev' => '65',
+ 'Toppings.Protected' => '4',
+ )
+ );
+
+ $config_expect = HTMLPurifier_Config::create(array(
+ 'Pancake.Served' => false,
+ 'Toppings.Syrup' => false,
+ 'Toppings.Flavor' => "juice",
+ 'Toppings.Strawberries' => 999,
+ 'Toppings.Calories' => null
+ ), $this->schema);
+
+ $config_result = HTMLPurifier_Config::loadArrayFromForm(
+ $get, 'breakfast',
+ array('Pancake.Served', 'Toppings', '-Toppings.Protected'),
+ false, // mq fix
+ $this->schema
+ );
+
+ $this->assertEqual($config_expect, $config_result);
+
+ /*
+ MAGIC QUOTES NOT TESTED!!!
+
+ $get = array(
+ 'breakfast' => array(
+ 'Pancake.Mix' => 'n\\asty'
+ )
+ );
+ $config_expect = HTMLPurifier_Config::create(array(
+ 'Pancake.Mix' => 'n\\asty'
+ ));
+ $config_result = HTMLPurifier_Config::loadArrayFromForm($get, 'breakfast', true, false);
+ $this->assertEqual($config_expect, $config_result);
+ */
+ }
+
+ function test_getAllowedDirectivesForForm() {
+ $this->schema->add('Unused.Unused', 'Foobar', 'string', false);
+ $this->schema->add('Partial.Allowed', true, 'bool', false);
+ $this->schema->add('Partial.Unused', 'Foobar', 'string', false);
+ $this->schema->add('All.Allowed', true, 'bool', false);
+ $this->schema->add('All.Blacklisted', 'Foobar', 'string', false); // explicitly blacklisted
+ $this->schema->add('All.DefinitionID', 'Foobar', 'string', true); // auto-blacklisted
+ $this->schema->add('All.DefinitionRev', 2, 'int', false); // auto-blacklisted
+
+ $input = array('Partial.Allowed', 'All', '-All.Blacklisted');
+ $output = HTMLPurifier_Config::getAllowedDirectivesForForm($input, $this->schema);
+ $expect = array(
+ array('Partial', 'Allowed'),
+ array('All', 'Allowed')
+ );
+
+ $this->assertEqual($output, $expect);
+
+ }
+
+ function testDeprecatedAPI() {
+ $this->schema->add('Foo.Bar', 2, 'int', false);
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->chatty = false;
+ $this->expectError('Using deprecated API: use $config->set(\'Foo.Bar\', ...) instead');
+ $config->set('Foo', 'Bar', 4);
+ $this->expectError('Using deprecated API: use $config->get(\'Foo.Bar\') instead');
+ $this->assertIdentical($config->get('Foo', 'Bar'), 4);
+ }
+
+ function testInherit() {
+ $this->schema->add('Phantom.Masked', 25, 'int', false);
+ $this->schema->add('Phantom.Unmasked', 89, 'int', false);
+ $this->schema->add('Phantom.Latemasked', 11, 'int', false);
+ $config = new HTMLPurifier_Config($this->schema);
+ $config->set('Phantom.Masked', 800);
+ $subconfig = HTMLPurifier_Config::inherit($config);
+ $config->set('Phantom.Latemasked', 100, 'int', false);
+ $this->assertIdentical($subconfig->get('Phantom.Masked'), 800);
+ $this->assertIdentical($subconfig->get('Phantom.Unmasked'), 89);
+ $this->assertIdentical($subconfig->get('Phantom.Latemasked'), 100);
+ }
+
+ function testSerialize() {
+ $config = HTMLPurifier_Config::createDefault();
+ $config->set('HTML.Allowed', 'a');
+ $config2 = unserialize($config->serialize());
+ $this->assertIdentical($config->get('HTML.Allowed'), $config2->get('HTML.Allowed'));
+ }
+
+ function testDefinitionCachingNothing() {
+ list($mock, $config) = $this->setupCacheMock('HTML');
+ // should not touch the cache
+ $mock->expectNever('get');
+ $mock->expectNever('add');
+ $mock->expectNever('set');
+ $config->getDefinition('HTML', true);
+ $config->getDefinition('HTML', true);
+ $config->getDefinition('HTML');
+ $this->teardownCacheMock();
+ }
+
+ function testDefinitionCachingOptimized() {
+ list($mock, $config) = $this->setupCacheMock('HTML');
+ $mock->expectNever('set');
+ $config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->testDefinitionCachingOptimized');
+ $mock->expectOnce('get');
+ $mock->setReturnValue('get', null);
+ $this->assertTrue($config->maybeGetRawHTMLDefinition());
+ $this->assertTrue($config->maybeGetRawHTMLDefinition());
+ $mock->expectOnce('add');
+ $config->getDefinition('HTML');
+ $this->teardownCacheMock();
+ }
+
+ function testDefinitionCachingOptimizedHit() {
+ $fake_config = HTMLPurifier_Config::createDefault();
+ $fake_def = $fake_config->getHTMLDefinition();
+ list($mock, $config) = $this->setupCacheMock('HTML');
+ // should never frob cache
+ $mock->expectNever('add');
+ $mock->expectNever('set');
+ $config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->testDefinitionCachingOptimizedHit');
+ $mock->expectOnce('get');
+ $mock->setReturnValue('get', $fake_def);
+ $this->assertNull($config->maybeGetRawHTMLDefinition());
+ $config->getDefinition('HTML');
+ $config->getDefinition('HTML');
+ $this->teardownCacheMock();
+ }
+
+ protected function setupCacheMock($type) {
+ // inject our definition cache mock globally (borrowed from
+ // DefinitionFactoryTest)
+ generate_mock_once("HTMLPurifier_DefinitionCacheFactory");
+ $factory = new HTMLPurifier_DefinitionCacheFactoryMock();
+ $this->oldFactory = HTMLPurifier_DefinitionCacheFactory::instance();
+ HTMLPurifier_DefinitionCacheFactory::instance($factory);
+ generate_mock_once("HTMLPurifier_DefinitionCache");
+ $mock = new HTMLPurifier_DefinitionCacheMock();
+ $config = HTMLPurifier_Config::createDefault();
+ $factory->setReturnValue('create', $mock, array($type, $config));
+ return array($mock, $config);
+ }
+ protected function teardownCacheMock() {
+ HTMLPurifier_DefinitionCacheFactory::instance($this->oldFactory);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ContextTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ContextTest.php
new file mode 100644
index 000000000..c5cef1651
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ContextTest.php
@@ -0,0 +1,84 @@
+context = new HTMLPurifier_Context();
+ }
+
+ function testStandardUsage() {
+
+ generate_mock_once('HTMLPurifier_IDAccumulator');
+
+ $this->assertFalse($this->context->exists('IDAccumulator'));
+
+ $accumulator = new HTMLPurifier_IDAccumulatorMock();
+ $this->context->register('IDAccumulator', $accumulator);
+ $this->assertTrue($this->context->exists('IDAccumulator'));
+
+ $accumulator_2 =& $this->context->get('IDAccumulator');
+ $this->assertReference($accumulator, $accumulator_2);
+
+ $this->context->destroy('IDAccumulator');
+ $this->assertFalse($this->context->exists('IDAccumulator'));
+
+ $this->expectError('Attempted to retrieve non-existent variable IDAccumulator');
+ $accumulator_3 =& $this->context->get('IDAccumulator');
+ $this->assertNull($accumulator_3);
+
+ $this->expectError('Attempted to destroy non-existent variable IDAccumulator');
+ $this->context->destroy('IDAccumulator');
+
+ }
+
+ function testReRegister() {
+
+ $var = true;
+ $this->context->register('OnceOnly', $var);
+
+ $this->expectError('Name OnceOnly produces collision, cannot re-register');
+ $this->context->register('OnceOnly', $var);
+
+ // destroy it, now registration is okay
+ $this->context->destroy('OnceOnly');
+ $this->context->register('OnceOnly', $var);
+
+ }
+
+ function test_loadArray() {
+
+ // references can be *really* wonky!
+
+ $context_manual = new HTMLPurifier_Context();
+ $context_load = new HTMLPurifier_Context();
+
+ $var1 = 1;
+ $var2 = 2;
+
+ $context_manual->register('var1', $var1);
+ $context_manual->register('var2', $var2);
+
+ // you MUST set up the references when constructing the array,
+ // otherwise the registered version will be a copy
+ $array = array(
+ 'var1' => &$var1,
+ 'var2' => &$var2
+ );
+
+ $context_load->loadArray($array);
+ $this->assertIdentical($context_manual, $context_load);
+
+ $var1 = 10;
+ $var2 = 20;
+
+ $this->assertIdentical($context_manual, $context_load);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/Decorator/CleanupTest.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/Decorator/CleanupTest.php
new file mode 100644
index 000000000..afcb0e39f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/Decorator/CleanupTest.php
@@ -0,0 +1,56 @@
+cache = new HTMLPurifier_DefinitionCache_Decorator_Cleanup();
+ parent::setup();
+ }
+
+ function setupMockForSuccess($op) {
+ $this->mock->expectOnce($op, array($this->def, $this->config));
+ $this->mock->setReturnValue($op, true, array($this->def, $this->config));
+ $this->mock->expectNever('cleanup');
+ }
+
+ function setupMockForFailure($op) {
+ $this->mock->expectOnce($op, array($this->def, $this->config));
+ $this->mock->setReturnValue($op, false, array($this->def, $this->config));
+ $this->mock->expectOnce('cleanup', array($this->config));
+ }
+
+ function test_get() {
+ $this->mock->expectOnce('get', array($this->config));
+ $this->mock->setReturnValue('get', true, array($this->config));
+ $this->mock->expectNever('cleanup');
+ $this->assertEqual($this->cache->get($this->config), $this->def);
+ }
+
+ function test_get_failure() {
+ $this->mock->expectOnce('get', array($this->config));
+ $this->mock->setReturnValue('get', false, array($this->config));
+ $this->mock->expectOnce('cleanup', array($this->config));
+ $this->assertEqual($this->cache->get($this->config), false);
+ }
+
+ function test_set() {
+ $this->setupMockForSuccess('set');
+ $this->assertEqual($this->cache->set($this->def, $this->config), true);
+ }
+
+ function test_replace() {
+ $this->setupMockForSuccess('replace');
+ $this->assertEqual($this->cache->replace($this->def, $this->config), true);
+ }
+
+ function test_add() {
+ $this->setupMockForSuccess('add');
+ $this->assertEqual($this->cache->add($this->def, $this->config), true);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/Decorator/MemoryTest.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/Decorator/MemoryTest.php
new file mode 100644
index 000000000..55f2f249c
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/Decorator/MemoryTest.php
@@ -0,0 +1,70 @@
+cache = new HTMLPurifier_DefinitionCache_Decorator_Memory();
+ parent::setup();
+ }
+
+ function setupMockForSuccess($op) {
+ $this->mock->expectOnce($op, array($this->def, $this->config));
+ $this->mock->setReturnValue($op, true, array($this->def, $this->config));
+ $this->mock->expectNever('get');
+ }
+
+ function setupMockForFailure($op) {
+ $this->mock->expectOnce($op, array($this->def, $this->config));
+ $this->mock->setReturnValue($op, false, array($this->def, $this->config));
+ $this->mock->expectOnce('get', array($this->config));
+ }
+
+ function test_get() {
+ $this->mock->expectOnce('get', array($this->config)); // only ONE call!
+ $this->mock->setReturnValue('get', $this->def, array($this->config));
+ $this->assertEqual($this->cache->get($this->config), $this->def);
+ $this->assertEqual($this->cache->get($this->config), $this->def);
+ }
+
+ function test_set() {
+ $this->setupMockForSuccess('set', 'get');
+ $this->assertEqual($this->cache->set($this->def, $this->config), true);
+ $this->assertEqual($this->cache->get($this->config), $this->def);
+ }
+
+ function test_set_failure() {
+ $this->setupMockForFailure('set', 'get');
+ $this->assertEqual($this->cache->set($this->def, $this->config), false);
+ $this->cache->get($this->config);
+ }
+
+ function test_replace() {
+ $this->setupMockForSuccess('replace', 'get');
+ $this->assertEqual($this->cache->replace($this->def, $this->config), true);
+ $this->assertEqual($this->cache->get($this->config), $this->def);
+ }
+
+ function test_replace_failure() {
+ $this->setupMockForFailure('replace', 'get');
+ $this->assertEqual($this->cache->replace($this->def, $this->config), false);
+ $this->cache->get($this->config);
+ }
+
+ function test_add() {
+ $this->setupMockForSuccess('add', 'get');
+ $this->assertEqual($this->cache->add($this->def, $this->config), true);
+ $this->assertEqual($this->cache->get($this->config), $this->def);
+ }
+
+ function test_add_failure() {
+ $this->setupMockForFailure('add', 'get');
+ $this->assertEqual($this->cache->add($this->def, $this->config), false);
+ $this->cache->get($this->config);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/DecoratorHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/DecoratorHarness.php
new file mode 100644
index 000000000..64951a3ed
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/DecoratorHarness.php
@@ -0,0 +1,23 @@
+mock = new HTMLPurifier_DefinitionCacheMock();
+ $this->mock->type = 'Test';
+ $this->cache = $this->cache->decorate($this->mock);
+ $this->def = $this->generateDefinition();
+ $this->config = $this->generateConfigMock();
+ }
+
+ function teardown() {
+ unset($this->mock);
+ unset($this->cache);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/DecoratorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/DecoratorTest.php
new file mode 100644
index 000000000..f64967970
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/DecoratorTest.php
@@ -0,0 +1,42 @@
+type = 'Test';
+
+ $cache = new HTMLPurifier_DefinitionCache_Decorator();
+ $cache = $cache->decorate($mock);
+
+ $this->assertIdentical($cache->type, $mock->type);
+
+ $def = $this->generateDefinition();
+ $config = $this->generateConfigMock();
+
+ $mock->expectOnce('add', array($def, $config));
+ $cache->add($def, $config);
+
+ $mock->expectOnce('set', array($def, $config));
+ $cache->set($def, $config);
+
+ $mock->expectOnce('replace', array($def, $config));
+ $cache->replace($def, $config);
+
+ $mock->expectOnce('get', array($config));
+ $cache->get($config);
+
+ $mock->expectOnce('flush', array($config));
+ $cache->flush($config);
+
+ $mock->expectOnce('cleanup', array($config));
+ $cache->cleanup($config);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/SerializerTest.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/SerializerTest.php
new file mode 100644
index 000000000..f6fec51ef
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/SerializerTest.php
@@ -0,0 +1,225 @@
+generateConfigMock('serial');
+ $config->setReturnValue('get', 2, array('Test.DefinitionRev'));
+ $config->version = '1.0.0';
+
+ $config_md5 = '1.0.0,serial,2';
+
+ $file = realpath(
+ $rel_file = HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer/Test/' .
+ $config_md5 . '.ser'
+ );
+ if($file && file_exists($file)) unlink($file); // prevent previous failures from causing problems
+
+ $this->assertIdentical($config_md5, $cache->generateKey($config));
+
+ $def_original = $this->generateDefinition();
+
+ $cache->add($def_original, $config);
+ $this->assertFileExist($rel_file);
+
+ $file_generated = $cache->generateFilePath($config);
+ $this->assertIdentical(realpath($rel_file), realpath($file_generated));
+
+ $def_1 = $cache->get($config);
+ // $this->assertIdentical($def_original, $def_1);
+
+ $def_original->info_random = 'changed';
+
+ $cache->set($def_original, $config);
+ $def_2 = $cache->get($config);
+
+ // $this->assertIdentical($def_original, $def_2);
+ // $this->assertNotEqual ($def_original, $def_1);
+
+ $def_original->info_random = 'did it change?';
+
+ $this->assertFalse($cache->add($def_original, $config));
+ $def_3 = $cache->get($config);
+
+ // $this->assertNotEqual ($def_original, $def_3); // did not change!
+ // $this->assertIdentical($def_3, $def_2);
+
+ $cache->replace($def_original, $config);
+ $def_4 = $cache->get($config);
+ // $this->assertIdentical($def_original, $def_4);
+
+ $cache->remove($config);
+ $this->assertFileNotExist($file);
+
+ $this->assertFalse($cache->replace($def_original, $config));
+ $def_5 = $cache->get($config);
+ $this->assertFalse($def_5);
+
+ }
+
+ function test_errors() {
+ $cache = new HTMLPurifier_DefinitionCache_Serializer('Test');
+ $def = $this->generateDefinition();
+ $def->setup = true;
+ $def->type = 'NotTest';
+ $config = $this->generateConfigMock('testfoo');
+
+ $this->expectError('Cannot use definition of type NotTest in cache for Test');
+ $cache->add($def, $config);
+
+ $this->expectError('Cannot use definition of type NotTest in cache for Test');
+ $cache->set($def, $config);
+
+ $this->expectError('Cannot use definition of type NotTest in cache for Test');
+ $cache->replace($def, $config);
+ }
+
+ function test_flush() {
+
+ $cache = new HTMLPurifier_DefinitionCache_Serializer('Test');
+
+ $config1 = $this->generateConfigMock('test1');
+ $config2 = $this->generateConfigMock('test2');
+ $config3 = $this->generateConfigMock('test3');
+
+ $def1 = $this->generateDefinition(array('info_candles' => 1));
+ $def2 = $this->generateDefinition(array('info_candles' => 2));
+ $def3 = $this->generateDefinition(array('info_candles' => 3));
+
+ $cache->add($def1, $config1);
+ $cache->add($def2, $config2);
+ $cache->add($def3, $config3);
+
+ $this->assertEqual($def1, $cache->get($config1));
+ $this->assertEqual($def2, $cache->get($config2));
+ $this->assertEqual($def3, $cache->get($config3));
+
+ $cache->flush($config1); // only essential directive is %Cache.SerializerPath
+
+ $this->assertFalse($cache->get($config1));
+ $this->assertFalse($cache->get($config2));
+ $this->assertFalse($cache->get($config3));
+
+ }
+
+ function testCleanup() {
+
+ $cache = new HTMLPurifier_DefinitionCache_Serializer('Test');
+
+ // in order of age, oldest first
+ // note that configurations are all identical, but version/revision
+ // are different
+
+ $config1 = $this->generateConfigMock();
+ $config1->version = '0.9.0';
+ $config1->setReturnValue('get', 574, array('Test.DefinitionRev'));
+ $def1 = $this->generateDefinition(array('info' => 1));
+
+ $config2 = $this->generateConfigMock();
+ $config2->version = '1.0.0beta';
+ $config2->setReturnValue('get', 1, array('Test.DefinitionRev'));
+ $def2 = $this->generateDefinition(array('info' => 3));
+
+ $cache->set($def1, $config1);
+ $cache->cleanup($config1);
+ $this->assertEqual($def1, $cache->get($config1)); // no change
+
+ $cache->cleanup($config2);
+ $this->assertFalse($cache->get($config1));
+ $this->assertFalse($cache->get($config2));
+
+ }
+
+ function testCleanupOnlySameID() {
+
+ $cache = new HTMLPurifier_DefinitionCache_Serializer('Test');
+
+ $config1 = $this->generateConfigMock('serial1');
+ $config1->version = '1.0.0';
+ $config1->setReturnValue('get', 1, array('Test.DefinitionRev'));
+ $def1 = $this->generateDefinition(array('info' => 1));
+
+ $config2 = $this->generateConfigMock('serial2');
+ $config2->version = '1.0.0';
+ $config2->setReturnValue('get', 34, array('Test.DefinitionRev'));
+ $def2 = $this->generateDefinition(array('info' => 3));
+
+ $cache->set($def1, $config1);
+ $cache->cleanup($config1);
+ $this->assertEqual($def1, $cache->get($config1)); // no change
+
+ $cache->set($def2, $config2);
+ $cache->cleanup($config2);
+ $this->assertEqual($def1, $cache->get($config1));
+ $this->assertEqual($def2, $cache->get($config2));
+
+ $cache->flush($config1);
+ }
+
+ /**
+ * Asserts that a file exists, ignoring the stat cache
+ */
+ function assertFileExist($file) {
+ clearstatcache();
+ $this->assertTrue(file_exists($file), 'Expected ' . $file . ' exists');
+ }
+
+ /**
+ * Asserts that a file does not exist, ignoring the stat cache
+ */
+ function assertFileNotExist($file) {
+ clearstatcache();
+ $this->assertFalse(file_exists($file), 'Expected ' . $file . ' does not exist');
+ }
+
+ function testAlternatePath() {
+
+ $cache = new HTMLPurifier_DefinitionCache_Serializer('Test');
+ $config = $this->generateConfigMock('serial');
+ $config->version = '1.0.0';
+ $config->setReturnValue('get', 1, array('Test.DefinitionRev'));
+ $dir = dirname(__FILE__) . '/SerializerTest';
+ $config->setReturnValue('get', $dir, array('Cache.SerializerPath'));
+
+ $def_original = $this->generateDefinition();
+ $cache->add($def_original, $config);
+ $this->assertFileExist($dir . '/Test/1.0.0,serial,1.ser');
+
+ unlink($dir . '/Test/1.0.0,serial,1.ser');
+ rmdir( $dir . '/Test');
+
+ }
+
+ function testAlternatePermissions() {
+
+ $cache = new HTMLPurifier_DefinitionCache_Serializer('Test');
+ $config = $this->generateConfigMock('serial');
+ $config->version = '1.0.0';
+ $config->setReturnValue('get', 1, array('Test.DefinitionRev'));
+ $dir = dirname(__FILE__) . '/SerializerTest';
+ $config->setReturnValue('get', $dir, array('Cache.SerializerPath'));
+ $config->setReturnValue('get', 0777, array('Cache.SerializerPermissions'));
+
+ $def_original = $this->generateDefinition();
+ $cache->add($def_original, $config);
+ $this->assertFileExist($dir . '/Test/1.0.0,serial,1.ser');
+
+ $this->assertEqual(0666, 0777 & fileperms($dir . '/Test/1.0.0,serial,1.ser'));
+ $this->assertEqual(0777, 0777 & fileperms($dir . '/Test'));
+
+ unlink($dir . '/Test/1.0.0,serial,1.ser');
+ rmdir( $dir . '/Test');
+
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/SerializerTest/README b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/SerializerTest/README
new file mode 100644
index 000000000..2e35c1c3d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCache/SerializerTest/README
@@ -0,0 +1,3 @@
+This is a dummy file to prevent Git from ignoring this empty directory.
+
+ vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheFactoryTest.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheFactoryTest.php
new file mode 100644
index 000000000..d50ef8be1
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheFactoryTest.php
@@ -0,0 +1,70 @@
+factory = new HTMLPurifier_DefinitionCacheFactory();
+ $this->oldFactory = HTMLPurifier_DefinitionCacheFactory::instance();
+ HTMLPurifier_DefinitionCacheFactory::instance($this->factory);
+ }
+
+ public function tearDown() {
+ HTMLPurifier_DefinitionCacheFactory::instance($this->oldFactory);
+ }
+
+ function test_create() {
+ $cache = $this->factory->create('Test', $this->config);
+ $this->assertEqual($cache, new HTMLPurifier_DefinitionCache_Serializer('Test'));
+ }
+
+ function test_create_withDecorator() {
+ $this->factory->addDecorator('Memory');
+ $cache = $this->factory->create('Test', $this->config);
+ $cache_real = new HTMLPurifier_DefinitionCache_Decorator_Memory();
+ $cache_real = $cache_real->decorate(new HTMLPurifier_DefinitionCache_Serializer('Test'));
+ $this->assertEqual($cache, $cache_real);
+ }
+
+ function test_create_withDecoratorObject() {
+ $this->factory->addDecorator(new HTMLPurifier_DefinitionCache_Decorator_Memory());
+ $cache = $this->factory->create('Test', $this->config);
+ $cache_real = new HTMLPurifier_DefinitionCache_Decorator_Memory();
+ $cache_real = $cache_real->decorate(new HTMLPurifier_DefinitionCache_Serializer('Test'));
+ $this->assertEqual($cache, $cache_real);
+ }
+
+ function test_create_recycling() {
+ $cache = $this->factory->create('Test', $this->config);
+ $cache2 = $this->factory->create('Test', $this->config);
+ $this->assertReference($cache, $cache2);
+ }
+
+ function test_create_invalid() {
+ $this->config->set('Cache.DefinitionImpl', 'Invalid');
+ $this->expectError('Unrecognized DefinitionCache Invalid, using Serializer instead');
+ $cache = $this->factory->create('Test', $this->config);
+ $this->assertIsA($cache, 'HTMLPurifier_DefinitionCache_Serializer');
+ }
+
+ function test_null() {
+ $this->config->set('Cache.DefinitionImpl', null);
+ $cache = $this->factory->create('Test', $this->config);
+ $this->assertEqual($cache, new HTMLPurifier_DefinitionCache_Null('Test'));
+ }
+
+ function test_register() {
+ generate_mock_once('HTMLPurifier_DefinitionCache');
+ $this->config->set('Cache.DefinitionImpl', 'TestCache');
+ $this->factory->register('TestCache', $class = 'HTMLPurifier_DefinitionCacheMock');
+ $cache = $this->factory->create('Test', $this->config);
+ $this->assertIsA($cache, $class);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheHarness.php
new file mode 100644
index 000000000..ab3cef451
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheHarness.php
@@ -0,0 +1,34 @@
+setReturnValue('getBatchSerial', $serial, array('Test'));
+ $config->version = '1.0.0';
+ return $config;
+ }
+
+ /**
+ * Returns an anonymous def that has been setup and named Test
+ */
+ protected function generateDefinition($member_vars = array()) {
+ $def = new HTMLPurifier_DefinitionTestable();
+ $def->setup = true;
+ $def->type = 'Test';
+ foreach ($member_vars as $key => $val) {
+ $def->$key = $val;
+ }
+ return $def;
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheTest.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheTest.php
new file mode 100644
index 000000000..5ad2ff9cb
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionCacheTest.php
@@ -0,0 +1,32 @@
+version = '1.0.0'; // hopefully no conflicts
+ $config->setReturnValue('get', 10, array('Test.DefinitionRev'));
+ $config->setReturnValue('getBatchSerial', 'hash', array('Test'));
+
+ $this->assertIdentical($cache->isOld('1.0.0,hash,10', $config), false);
+ $this->assertIdentical($cache->isOld('1.5.0,hash,1', $config), true);
+
+ $this->assertIdentical($cache->isOld('0.9.0,hash,1', $config), true);
+ $this->assertIdentical($cache->isOld('1.0.0,hash,1', $config), true);
+ $this->assertIdentical($cache->isOld('1.0.0beta,hash,11', $config), true);
+
+ $this->assertIdentical($cache->isOld('0.9.0,hash2,1', $config), true);
+ $this->assertIdentical($cache->isOld('1.0.0,hash2,1', $config), false); // if hash is different, don't touch!
+ $this->assertIdentical($cache->isOld('1.0.0beta,hash2,11', $config), true);
+ $this->assertIdentical($cache->isOld('1.0.0-dev,hash2,11', $config), true);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionTest.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionTest.php
new file mode 100644
index 000000000..38676ad7a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionTest.php
@@ -0,0 +1,20 @@
+expectOnce('doSetup', array($config));
+ $def->setup($config);
+ }
+ function test_setup_redundant() {
+ $def = new HTMLPurifier_DefinitionTestable();
+ $config = HTMLPurifier_Config::createDefault();
+ $def->expectNever('doSetup');
+ $def->setup = true;
+ $def->setup($config);
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/DefinitionTestable.php b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionTestable.php
new file mode 100644
index 000000000..312c57bb4
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/DefinitionTestable.php
@@ -0,0 +1,8 @@
+register(
+ $name = 'XHTML 1.0 Transitional',
+ $xml = true,
+ $modules = array('module-one', 'module-two'),
+ $tidyModules = array('lenient-module'),
+ $aliases = array('X10T')
+ );
+
+ $d2 = new HTMLPurifier_Doctype($name, $xml, $modules, $tidyModules, $aliases);
+
+ $this->assertIdentical($d, $d2);
+ $this->assertSame($d, $registry->get('XHTML 1.0 Transitional'));
+
+ // test shorthand
+ $d = $registry->register(
+ $name = 'XHTML 1.0 Strict', true, 'module', 'Tidy', 'X10S'
+ );
+ $d2 = new HTMLPurifier_Doctype($name, true, array('module'), array('Tidy'), array('X10S'));
+
+ $this->assertIdentical($d, $d2);
+
+ }
+
+ function test_get() {
+
+ // see also alias and register tests
+
+ $registry = new HTMLPurifier_DoctypeRegistry();
+
+ $this->expectError('Doctype XHTML 2.0 does not exist');
+ $registry->get('XHTML 2.0');
+
+ // prevent XSS
+ $this->expectError('Doctype <foo> does not exist');
+ $registry->get('');
+
+ }
+
+ function testAliases() {
+
+ $registry = new HTMLPurifier_DoctypeRegistry();
+
+ $d1 = $registry->register('Doc1', true, array(), array(), array('1'));
+
+ $this->assertSame($d1, $registry->get('Doc1'));
+ $this->assertSame($d1, $registry->get('1'));
+
+ $d2 = $registry->register('Doc2', true, array(), array(), array('2'));
+
+ $this->assertSame($d2, $registry->get('Doc2'));
+ $this->assertSame($d2, $registry->get('2'));
+
+ $d3 = $registry->register('1', true, array(), array(), array());
+
+ // literal name overrides alias
+ $this->assertSame($d3, $registry->get('1'));
+
+ $d4 = $registry->register('One', true, array(), array(), array('1'));
+
+ $this->assertSame($d4, $registry->get('One'));
+ // still it overrides
+ $this->assertSame($d3, $registry->get('1'));
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ElementDefTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ElementDefTest.php
new file mode 100644
index 000000000..500312b3c
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ElementDefTest.php
@@ -0,0 +1,91 @@
+standalone = true;
+ $def1->attr = array(
+ 0 => array('old-include'),
+ 'old-attr' => $old,
+ 'overloaded-attr' => $overloaded_old,
+ 'removed-attr' => $removed,
+ );
+ $def1->attr_transform_pre =
+ $def1->attr_transform_post = array(
+ 'old-transform' => $old,
+ 'overloaded-transform' => $overloaded_old,
+ 'removed-transform' => $removed,
+ );
+ $def1->child = $overloaded_old;
+ $def1->content_model = 'old';
+ $def1->content_model_type = $overloaded_old;
+ $def1->descendants_are_inline = false;
+ $def1->excludes = array(
+ 'old' => true,
+ 'removed-old' => true
+ );
+
+ $def2->standalone = false;
+ $def2->attr = array(
+ 0 => array('new-include'),
+ 'new-attr' => $new,
+ 'overloaded-attr' => $overloaded_new,
+ 'removed-attr' => false,
+ );
+ $def2->attr_transform_pre =
+ $def2->attr_transform_post = array(
+ 'new-transform' => $new,
+ 'overloaded-transform' => $overloaded_new,
+ 'removed-transform' => false,
+ );
+ $def2->child = $new;
+ $def2->content_model = '#SUPER | new';
+ $def2->content_model_type = $overloaded_new;
+ $def2->descendants_are_inline = true;
+ $def2->excludes = array(
+ 'new' => true,
+ 'removed-old' => false
+ );
+
+ $def1->mergeIn($def2);
+ $def1->mergeIn($def3); // empty, has no effect
+
+ $this->assertIdentical($def1->standalone, true);
+ $this->assertIdentical($def1->attr, array(
+ 0 => array('old-include', 'new-include'),
+ 'old-attr' => $old,
+ 'overloaded-attr' => $overloaded_new,
+ 'new-attr' => $new,
+ ));
+ $this->assertIdentical($def1->attr_transform_pre, $def1->attr_transform_post);
+ $this->assertIdentical($def1->attr_transform_pre, array(
+ 'old-transform' => $old,
+ 'overloaded-transform' => $overloaded_new,
+ 'new-transform' => $new,
+ ));
+ $this->assertIdentical($def1->child, $new);
+ $this->assertIdentical($def1->content_model, 'old | new');
+ $this->assertIdentical($def1->content_model_type, $overloaded_new);
+ $this->assertIdentical($def1->descendants_are_inline, true);
+ $this->assertIdentical($def1->excludes, array(
+ 'old' => true,
+ 'new' => true
+ ));
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/EncoderTest.php b/lib/htmlpurifier/tests/HTMLPurifier/EncoderTest.php
new file mode 100644
index 000000000..6084c39f3
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/EncoderTest.php
@@ -0,0 +1,215 @@
+_entity_lookup = HTMLPurifier_EntityLookup::instance();
+ parent::setUp();
+ }
+
+ function assertCleanUTF8($string, $expect = null) {
+ if ($expect === null) $expect = $string;
+ $this->assertIdentical(HTMLPurifier_Encoder::cleanUTF8($string), $expect, 'iconv: %s');
+ $this->assertIdentical(HTMLPurifier_Encoder::cleanUTF8($string, true), $expect, 'PHP: %s');
+ }
+
+ function test_cleanUTF8() {
+ $this->assertCleanUTF8('Normal string.');
+ $this->assertCleanUTF8("Test\tAllowed\nControl\rCharacters");
+ $this->assertCleanUTF8("null byte: \0", 'null byte: ');
+ $this->assertCleanUTF8("\1\2\3\4\5\6\7", '');
+ $this->assertCleanUTF8("\x7F", ''); // one byte invalid SGML char
+ $this->assertCleanUTF8("\xC2\x80", ''); // two byte invalid SGML
+ $this->assertCleanUTF8("\xF3\xBF\xBF\xBF"); // valid four byte
+ $this->assertCleanUTF8("\xDF\xFF", ''); // malformed UTF8
+ // invalid codepoints
+ $this->assertCleanUTF8("\xED\xB0\x80", '');
+ }
+
+ function test_convertToUTF8_noConvert() {
+ // UTF-8 means that we don't touch it
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
+ "\xF6", // this is invalid
+ 'Expected identical [Binary: F6]'
+ );
+ }
+
+ function test_convertToUTF8_spuriousEncoding() {
+ $this->config->set('Core.Encoding', 'utf99');
+ $this->expectError('Invalid encoding utf99');
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
+ ''
+ );
+ }
+
+ function test_convertToUTF8_iso8859_1() {
+ $this->config->set('Core.Encoding', 'ISO-8859-1');
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
+ "\xC3\xB6"
+ );
+ }
+
+ function test_convertToUTF8_withoutIconv() {
+ $this->config->set('Core.Encoding', 'ISO-8859-1');
+ $this->config->set('Test.ForceNoIconv', true);
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
+ "\xC3\xB6"
+ );
+
+ }
+
+ function getZhongWen() {
+ return "\xE4\xB8\xAD\xE6\x96\x87 (Chinese)";
+ }
+
+ function test_convertFromUTF8_utf8() {
+ // UTF-8 means that we don't touch it
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
+ "\xC3\xB6"
+ );
+ }
+
+ function test_convertFromUTF8_iso8859_1() {
+ $this->config->set('Core.Encoding', 'ISO-8859-1');
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
+ "\xF6",
+ 'Expected identical [Binary: F6]'
+ );
+ }
+
+ function test_convertFromUTF8_iconvNoChars() {
+ if (!function_exists('iconv')) return;
+ $this->config->set('Core.Encoding', 'ISO-8859-1');
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
+ " (Chinese)"
+ );
+ }
+
+ function test_convertFromUTF8_phpNormal() {
+ // Plain PHP implementation has slightly different behavior
+ $this->config->set('Core.Encoding', 'ISO-8859-1');
+ $this->config->set('Test.ForceNoIconv', true);
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
+ "\xF6",
+ 'Expected identical [Binary: F6]'
+ );
+ }
+
+ function test_convertFromUTF8_phpNoChars() {
+ $this->config->set('Core.Encoding', 'ISO-8859-1');
+ $this->config->set('Test.ForceNoIconv', true);
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
+ "?? (Chinese)"
+ );
+ }
+
+ function test_convertFromUTF8_withProtection() {
+ // Preserve the characters!
+ $this->config->set('Core.Encoding', 'ISO-8859-1');
+ $this->config->set('Core.EscapeNonASCIICharacters', true);
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
+ "中文 (Chinese)"
+ );
+ }
+
+ function test_convertFromUTF8_withProtectionButUtf8() {
+ // Preserve the characters!
+ $this->config->set('Core.EscapeNonASCIICharacters', true);
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
+ "中文 (Chinese)"
+ );
+ }
+
+ function test_convertToASCIIDumbLossless() {
+
+ // Uppercase thorn letter
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertToASCIIDumbLossless("\xC3\x9Eorn"),
+ "Þorn"
+ );
+
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertToASCIIDumbLossless("an"),
+ "an"
+ );
+
+ // test up to four bytes
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertToASCIIDumbLossless("\xF3\xA0\x80\xA0"),
+ ""
+ );
+
+ }
+
+ function assertASCIISupportCheck($enc, $ret) {
+ $test = HTMLPurifier_Encoder::testEncodingSupportsASCII($enc, true);
+ if ($test === false) return;
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::testEncodingSupportsASCII($enc),
+ $ret
+ );
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::testEncodingSupportsASCII($enc, true),
+ $ret
+ );
+ }
+
+ function test_testEncodingSupportsASCII() {
+ $this->assertASCIISupportCheck('Shift_JIS', array("\xC2\xA5" => '\\', "\xE2\x80\xBE" => '~'));
+ $this->assertASCIISupportCheck('JOHAB', array("\xE2\x82\xA9" => '\\'));
+ $this->assertASCIISupportCheck('ISO-8859-1', array());
+ $this->assertASCIISupportCheck('dontexist', array()); // canary
+ }
+
+ function testShiftJIS() {
+ if (!function_exists('iconv')) return;
+ $this->config->set('Core.Encoding', 'Shift_JIS');
+ // This actually looks like a Yen, but we're going to treat it differently
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8('\\~', $this->config, $this->context),
+ '\\~'
+ );
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertToUTF8('\\~', $this->config, $this->context),
+ '\\~'
+ );
+ }
+
+ function testIconvTruncateBug() {
+ if (!function_exists('iconv')) return;
+ if (HTMLPurifier_Encoder::testIconvTruncateBug() !== HTMLPurifier_Encoder::ICONV_TRUNCATES) return;
+ $this->config->set('Core.Encoding', 'ISO-8859-1');
+ $this->assertIdentical(
+ HTMLPurifier_Encoder::convertFromUTF8("\xE4\xB8\xAD" . str_repeat('a', 10000), $this->config, $this->context),
+ str_repeat('a', 10000)
+ );
+ }
+
+ function testIconvChunking() {
+ if (!function_exists('iconv')) return;
+ if (HTMLPurifier_Encoder::testIconvTruncateBug() !== HTMLPurifier_Encoder::ICONV_TRUNCATES) return;
+ $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "a\xF3\xA0\x80\xA0b", 4), 'ab');
+ $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aa\xE4\xB8\xADb", 4), 'aab');
+ $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aaa\xCE\xB1b", 4), 'aaab');
+ $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aaaa\xF3\xA0\x80\xA0b", 4), 'aaaab');
+ $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aaaa\xE4\xB8\xADb", 4), 'aaaab');
+ $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aaaa\xCE\xB1b", 4), 'aaaab');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/EntityLookupTest.php b/lib/htmlpurifier/tests/HTMLPurifier/EntityLookupTest.php
new file mode 100644
index 000000000..e715f64a2
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/EntityLookupTest.php
@@ -0,0 +1,27 @@
+assertIdentical('â', $lookup->table['acirc']);
+
+ // special char
+ $this->assertIdentical('"', $lookup->table['quot']);
+ $this->assertIdentical('“', $lookup->table['ldquo']);
+ $this->assertIdentical('<', $lookup->table['lt']); // expressed strangely in source file
+
+ // symbol char
+ $this->assertIdentical('θ', $lookup->table['theta']);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/EntityParserTest.php b/lib/htmlpurifier/tests/HTMLPurifier/EntityParserTest.php
new file mode 100644
index 000000000..17ef62a18
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/EntityParserTest.php
@@ -0,0 +1,85 @@
+EntityParser = new HTMLPurifier_EntityParser();
+ $this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
+ }
+
+ function test_substituteNonSpecialEntities() {
+ $char_theta = $this->_entity_lookup->table['theta'];
+ $this->assertIdentical($char_theta,
+ $this->EntityParser->substituteNonSpecialEntities('θ') );
+ $this->assertIdentical('"',
+ $this->EntityParser->substituteNonSpecialEntities('"') );
+
+ // numeric tests, adapted from Feyd
+ $args = array();
+ $args[] = array(1114112,false );
+ $args[] = array(1114111,'F48FBFBF'); // 0x0010FFFF
+ $args[] = array(1048576,'F4808080'); // 0x00100000
+ $args[] = array(1048575,'F3BFBFBF'); // 0x000FFFFF
+ $args[] = array(262144, 'F1808080'); // 0x00040000
+ $args[] = array(262143, 'F0BFBFBF'); // 0x0003FFFF
+ $args[] = array(65536, 'F0908080'); // 0x00010000
+ $args[] = array(65535, 'EFBFBF' ); // 0x0000FFFF
+ $args[] = array(57344, 'EE8080' ); // 0x0000E000
+ $args[] = array(57343, false ); // 0x0000DFFF these are ill-formed
+ $args[] = array(56040, false ); // 0x0000DAE8 these are ill-formed
+ $args[] = array(55296, false ); // 0x0000D800 these are ill-formed
+ $args[] = array(55295, 'ED9FBF' ); // 0x0000D7FF
+ $args[] = array(53248, 'ED8080' ); // 0x0000D000
+ $args[] = array(53247, 'ECBFBF' ); // 0x0000CFFF
+ $args[] = array(4096, 'E18080' ); // 0x00001000
+ $args[] = array(4095, 'E0BFBF' ); // 0x00000FFF
+ $args[] = array(2048, 'E0A080' ); // 0x00000800
+ $args[] = array(2047, 'DFBF' ); // 0x000007FF
+ $args[] = array(128, 'C280' ); // 0x00000080 invalid SGML char
+ $args[] = array(127, '7F' ); // 0x0000007F invalid SGML char
+ $args[] = array(0, '00' ); // 0x00000000 invalid SGML char
+
+ $args[] = array(20108, 'E4BA8C' ); // 0x00004E8C
+ $args[] = array(77, '4D' ); // 0x0000004D
+ $args[] = array(66306, 'F0908C82'); // 0x00010302
+ $args[] = array(1072, 'D0B0' ); // 0x00000430
+
+ foreach ($args as $arg) {
+ $string = '' . $arg[0] . ';' . // decimal
+ '' . dechex($arg[0]) . ';'; // hex
+ $expect = '';
+ if ($arg[1] !== false) {
+ // this is only for PHP 5, the below is PHP 5 and PHP 4
+ //$chars = str_split($arg[1], 2);
+ $chars = array();
+ // strlen must be called in loop because strings size changes
+ for ($i = 0; strlen($arg[1]) > $i; $i += 2) {
+ $chars[] = $arg[1][$i] . $arg[1][$i+1];
+ }
+ foreach ($chars as $char) {
+ $expect .= chr(hexdec($char));
+ }
+ $expect .= $expect; // double it
+ }
+ $this->assertIdentical(
+ $this->EntityParser->substituteNonSpecialEntities($string),
+ $expect,
+ 'Identical expectation [Hex: '. dechex($arg[0]) .']'
+ );
+ }
+
+ }
+
+ function test_substituteSpecialEntities() {
+ $this->assertIdentical(
+ "'",
+ $this->EntityParser->substituteSpecialEntities(''')
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ErrorCollectorEMock.php b/lib/htmlpurifier/tests/HTMLPurifier/ErrorCollectorEMock.php
new file mode 100644
index 000000000..bbd096569
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ErrorCollectorEMock.php
@@ -0,0 +1,48 @@
+_context = $context;
+ }
+
+ public function expectContext($key, $value) {
+ $this->_expected_context[$key] = $value;
+ }
+ public function expectContextAt($step, $key, $value) {
+ $this->_expected_context_at[$step][$key] = $value;
+ }
+
+ public function send($v1, $v2) {
+ // test for context
+ $context = SimpleTest::getContext();
+ $test = $context->getTest();
+ $mock = $this->mock;
+
+ foreach ($this->_expected_context as $key => $value) {
+ $test->assertEqual($value, $this->_context->get($key));
+ }
+ $step = $mock->getCallCount('send');
+ if (isset($this->_expected_context_at[$step])) {
+ foreach ($this->_expected_context_at[$step] as $key => $value) {
+ $test->assertEqual($value, $this->_context->get($key));
+ }
+ }
+ // boilerplate mock code, does not have return value or references
+ $args = func_get_args();
+ $mock->invoke('send', $args);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ErrorCollectorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/ErrorCollectorTest.php
new file mode 100644
index 000000000..09becba53
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ErrorCollectorTest.php
@@ -0,0 +1,157 @@
+language = new HTMLPurifier_LanguageMock();
+ $this->language->setReturnValue('getErrorName', 'Error', array(E_ERROR));
+ $this->language->setReturnValue('getErrorName', 'Warning', array(E_WARNING));
+ $this->language->setReturnValue('getErrorName', 'Notice', array(E_NOTICE));
+ // this might prove to be troublesome if we need to set config
+ $this->generator = new HTMLPurifier_Generator($this->config, $this->context);
+ $this->line = false;
+ $this->context->register('Locale', $this->language);
+ $this->context->register('CurrentLine', $this->line);
+ $this->context->register('Generator', $this->generator);
+ $this->collector = new HTMLPurifier_ErrorCollector($this->context);
+ }
+
+ function test() {
+
+ $language = $this->language;
+ $language->setReturnValue('getMessage', 'Message 1', array('message-1'));
+ $language->setReturnValue('formatMessage', 'Message 2', array('message-2', array(1 => 'param')));
+ $language->setReturnValue('formatMessage', ' at line 23', array('ErrorCollector: At line', array('line' => 23)));
+ $language->setReturnValue('formatMessage', ' at line 3', array('ErrorCollector: At line', array('line' => 3)));
+
+ $this->line = 23;
+ $this->collector->send(E_ERROR, 'message-1');
+
+ $this->line = 3;
+ $this->collector->send(E_WARNING, 'message-2', 'param');
+
+ $result = array(
+ 0 => array(23, E_ERROR, 'Message 1', array()),
+ 1 => array(3, E_WARNING, 'Message 2', array())
+ );
+
+ $this->assertIdentical($this->collector->getRaw(), $result);
+
+ /*
+ $formatted_result =
+ 'Warning : Message 2 at line 3 '.
+ 'Error : Message 1 at line 23 ';
+
+ $this->assertIdentical($this->collector->getHTMLFormatted($this->config), $formatted_result);
+ */
+
+ }
+
+ function testNoErrors() {
+ $this->language->setReturnValue('getMessage', 'No errors', array('ErrorCollector: No errors'));
+
+ $formatted_result = 'No errors
';
+ $this->assertIdentical(
+ $this->collector->getHTMLFormatted($this->config),
+ $formatted_result
+ );
+ }
+
+ function testNoLineNumbers() {
+ $this->language->setReturnValue('getMessage', 'Message 1', array('message-1'));
+ $this->language->setReturnValue('getMessage', 'Message 2', array('message-2'));
+
+ $this->collector->send(E_ERROR, 'message-1');
+ $this->collector->send(E_ERROR, 'message-2');
+
+ $result = array(
+ 0 => array(false, E_ERROR, 'Message 1', array()),
+ 1 => array(false, E_ERROR, 'Message 2', array())
+ );
+ $this->assertIdentical($this->collector->getRaw(), $result);
+
+ /*
+ $formatted_result =
+ 'Error : Message 1 '.
+ 'Error : Message 2 ';
+ $this->assertIdentical($this->collector->getHTMLFormatted($this->config), $formatted_result);
+ */
+ }
+
+ function testContextSubstitutions() {
+
+ $current_token = false;
+ $this->context->register('CurrentToken', $current_token);
+
+ // 0
+ $current_token = new HTMLPurifier_Token_Start('a', array('href' => 'http://example.com'), 32);
+ $this->language->setReturnValue('formatMessage', 'Token message',
+ array('message-data-token', array('CurrentToken' => $current_token)));
+ $this->collector->send(E_NOTICE, 'message-data-token');
+
+ $current_attr = 'href';
+ $this->language->setReturnValue('formatMessage', '$CurrentAttr.Name => $CurrentAttr.Value',
+ array('message-attr', array('CurrentToken' => $current_token)));
+
+ // 1
+ $this->collector->send(E_NOTICE, 'message-attr'); // test when context isn't available
+
+ // 2
+ $this->context->register('CurrentAttr', $current_attr);
+ $this->collector->send(E_NOTICE, 'message-attr');
+
+ $result = array(
+ 0 => array(32, E_NOTICE, 'Token message', array()),
+ 1 => array(32, E_NOTICE, '$CurrentAttr.Name => $CurrentAttr.Value', array()),
+ 2 => array(32, E_NOTICE, 'href => http://example.com', array())
+ );
+ $this->assertIdentical($this->collector->getRaw(), $result);
+
+ }
+
+ /*
+ function testNestedErrors() {
+ $this->language->setReturnValue('getMessage', 'Message 1', array('message-1'));
+ $this->language->setReturnValue('getMessage', 'Message 2', array('message-2'));
+ $this->language->setReturnValue('formatMessage', 'End Message', array('end-message', array(1 => 'param')));
+ $this->language->setReturnValue('formatMessage', ' at line 4', array('ErrorCollector: At line', array('line' => 4)));
+
+ $this->line = 4;
+ $this->collector->start();
+ $this->collector->send(E_WARNING, 'message-1');
+ $this->collector->send(E_NOTICE, 'message-2');
+ $this->collector->end(E_NOTICE, 'end-message', 'param');
+
+ $expect = array(
+ 0 => array(4, E_NOTICE, 'End Message', array(
+ 0 => array(4, E_WARNING, 'Message 1', array()),
+ 1 => array(4, E_NOTICE, 'Message 2', array()),
+ )),
+ );
+ $result = $this->collector->getRaw();
+ $this->assertIdentical($result, $expect);
+
+ $formatted_expect =
+ 'Notice : End Message at line 4'.
+ 'Warning : Message 1 at line 4 '.
+ 'Notice : Message 2 at line 4 '.
+ ' ';
+ $formatted_result = $this->collector->getHTMLFormatted($this->config);
+ $this->assertIdentical($formatted_result, $formatted_expect);
+
+ }
+ */
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/ErrorsHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/ErrorsHarness.php
new file mode 100644
index 000000000..f7c673ca5
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/ErrorsHarness.php
@@ -0,0 +1,38 @@
+config = HTMLPurifier_Config::create(array('Core.CollectErrors' => true));
+ $this->context = new HTMLPurifier_Context();
+ generate_mock_once('HTMLPurifier_ErrorCollector');
+ $this->collector = new HTMLPurifier_ErrorCollectorEMock();
+ $this->collector->prepare($this->context);
+ $this->context->register('ErrorCollector', $this->collector);
+ $this->callCount = 0;
+ }
+
+ protected function expectNoErrorCollection() {
+ $this->collector->expectNever('send');
+ }
+
+ protected function expectErrorCollection() {
+ $args = func_get_args();
+ $this->collector->expectOnce('send', $args);
+ }
+
+ protected function expectContext($key, $value) {
+ $this->collector->expectContext($key, $value);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Filter/ExtractStyleBlocksTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Filter/ExtractStyleBlocksTest.php
new file mode 100644
index 000000000..3466d6aa2
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Filter/ExtractStyleBlocksTest.php
@@ -0,0 +1,231 @@
+config->set('Filter.ExtractStyleBlocks', true);
+ $purifier = new HTMLPurifier($this->config);
+ $result = $purifier->purify('Test');
+ $this->assertIdentical($result, 'Test');
+ $this->assertIdentical($purifier->context->get('StyleBlocks'),
+ array(
+ ".foo {\ntext-align:center;\n}",
+ "* {\nfont-size:12pt;\n}"
+ )
+ );
+ }
+
+ function assertExtractStyleBlocks($html, $expect = true, $styles = array()) {
+ $filter = new HTMLPurifier_Filter_ExtractStyleBlocks(); // disable cleaning
+ if ($expect === true) $expect = $html;
+ $this->config->set('Filter.ExtractStyleBlocks.TidyImpl', false);
+ $result = $filter->preFilter($html, $this->config, $this->context);
+ $this->assertIdentical($result, $expect);
+ $this->assertIdentical($this->context->get('StyleBlocks'), $styles);
+ }
+
+ function test_extractStyleBlocks_preserve() {
+ $this->assertExtractStyleBlocks('Foobar');
+ }
+
+ function test_extractStyleBlocks_allStyle() {
+ $this->assertExtractStyleBlocks('', '', array('foo'));
+ }
+
+ function test_extractStyleBlocks_multipleBlocks() {
+ $this->assertExtractStyleBlocks(
+ "NOP",
+ "NOP",
+ array('1', '2', '4')
+ );
+ }
+
+ function test_extractStyleBlocks_blockWithAttributes() {
+ $this->assertExtractStyleBlocks(
+ '',
+ '',
+ array('css')
+ );
+ }
+
+ function test_extractStyleBlocks_styleWithPadding() {
+ $this->assertExtractStyleBlocks(
+ "AlasAwesome \n Trendy!",
+ "AlasAwesome \n Trendy!",
+ array('foo')
+ );
+ }
+
+ function assertCleanCSS($input, $expect = true) {
+ $filter = new HTMLPurifier_Filter_ExtractStyleBlocks();
+ if ($expect === true) $expect = $input;
+ $this->normalize($input);
+ $this->normalize($expect);
+ $result = $filter->cleanCSS($input, $this->config, $this->context);
+ $this->assertIdentical($result, $expect);
+ }
+
+ function test_cleanCSS_malformed() {
+ $this->assertCleanCSS('', '');
+ }
+
+ function test_cleanCSS_selector() {
+ $this->assertCleanCSS("a .foo #id div.cl#foo {\nfont-weight:700;\n}");
+ }
+
+ function test_cleanCSS_angledBrackets() {
+ // [Content] No longer can smuggle in angled brackets using
+ // font-family; when we add support for 'content', reinstate
+ // this test.
+ //$this->assertCleanCSS(
+ // ".class {\nfont-family:'';\n}",
+ // ".class {\nfont-family:\"\\3C /style\\3E \";\n}"
+ //);
+ }
+
+ function test_cleanCSS_angledBrackets2() {
+ // CSSTidy's behavior in this case is wrong, and should be fixed
+ //$this->assertCleanCSS(
+ // "span[title=\"\"] {\nfont-size:12pt;\n}",
+ // "span[title=\"\\3C /style\\3E \"] {\nfont-size:12pt;\n}"
+ //);
+ }
+
+ function test_cleanCSS_bogus() {
+ $this->assertCleanCSS("div {bogus:tree;}", "div {\n}");
+ }
+
+ /* [CONTENT]
+ function test_cleanCSS_escapeCodes() {
+ $this->assertCleanCSS(
+ ".class {\nfont-family:\"\\3C /style\\3E \";\n}"
+ );
+ }
+
+ function test_cleanCSS_noEscapeCodes() {
+ $this->config->set('Filter.ExtractStyleBlocks.Escaping', false);
+ $this->assertCleanCSS(
+ ".class {\nfont-family:\"\";\n}"
+ );
+ }
+ */
+
+ function test_cleanCSS_scope() {
+ $this->config->set('Filter.ExtractStyleBlocks.Scope', '#foo');
+ $this->assertCleanCSS(
+ "p {\ntext-indent:1em;\n}",
+ "#foo p {\ntext-indent:1em;\n}"
+ );
+ }
+
+ function test_cleanCSS_scopeWithSelectorCommas() {
+ $this->config->set('Filter.ExtractStyleBlocks.Scope', '#foo');
+ $this->assertCleanCSS(
+ "b, i {\ntext-decoration:underline;\n}",
+ "#foo b, #foo i {\ntext-decoration:underline;\n}"
+ );
+ }
+
+ function test_cleanCSS_scopeWithNaughtySelector() {
+ $this->config->set('Filter.ExtractStyleBlocks.Scope', '#foo');
+ $this->assertCleanCSS(" + p {\ntext-indent:1em;\n}", '');
+ }
+
+ function test_cleanCSS_scopeWithMultipleNaughtySelectors() {
+ $this->config->set('Filter.ExtractStyleBlocks.Scope', '#foo');
+ $this->assertCleanCSS(" ++ ++ p {\ntext-indent:1em;\n}", '');
+ }
+
+ function test_cleanCSS_scopeWithCommas() {
+ $this->config->set('Filter.ExtractStyleBlocks.Scope', '#foo, .bar');
+ $this->assertCleanCSS(
+ "p {\ntext-indent:1em;\n}",
+ "#foo p, .bar p {\ntext-indent:1em;\n}"
+ );
+ }
+
+ function test_cleanCSS_scopeAllWithCommas() {
+ $this->config->set('Filter.ExtractStyleBlocks.Scope', '#foo, .bar');
+ $this->assertCleanCSS(
+ "p, div {\ntext-indent:1em;\n}",
+ "#foo p, .bar p, #foo div, .bar div {\ntext-indent:1em;\n}"
+ );
+ }
+
+ function test_cleanCSS_scopeWithConflicts() {
+ $this->config->set('Filter.ExtractStyleBlocks.Scope', 'p');
+ $this->assertCleanCSS(
+"div {
+text-align:right;
+}
+
+p div {
+text-align:left;
+}",
+
+"p div {
+text-align:right;
+}
+
+p p div {
+text-align:left;
+}"
+ );
+ }
+
+ function test_removeComments() {
+ $this->assertCleanCSS(
+"",
+"div {
+text-align:right;
+}"
+ );
+ }
+
+ function test_atSelector() {
+ $this->assertCleanCSS(
+"{
+ b { text-align: center; }
+}",
+""
+ );
+ }
+
+ function test_selectorValidation() {
+ $this->assertCleanCSS(
+"&, & {
+text-align: center;
+}",
+""
+ );
+ $this->assertCleanCSS(
+"&, b {
+text-align:center;
+}",
+"b {
+text-align:center;
+}"
+ );
+ $this->assertCleanCSS(
+"& a #foo:hover.bar +b > i {
+text-align:center;
+}",
+"a #foo:hover.bar + b \\3E i {
+text-align:center;
+}"
+ );
+ $this->assertCleanCSS("doesnt-exist { text-align:center }", "");
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/GeneratorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/GeneratorTest.php
new file mode 100644
index 000000000..46b1dcf6b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/GeneratorTest.php
@@ -0,0 +1,288 @@
+_entity_lookup = HTMLPurifier_EntityLookup::instance();
+ }
+
+ public function setUp() {
+ parent::setUp();
+ $this->config->set('Output.Newline', "\n");
+ }
+
+ /**
+ * Creates a generator based on config and context member variables.
+ */
+ protected function createGenerator() {
+ return new HTMLPurifier_Generator($this->config, $this->context);
+ }
+
+ protected function assertGenerateFromToken($token, $html) {
+ $generator = $this->createGenerator();
+ $result = $generator->generateFromToken($token);
+ $this->assertIdentical($result, $html);
+ }
+
+ function test_generateFromToken_text() {
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Text('Foobar.<>'),
+ 'Foobar.<>'
+ );
+ }
+
+ function test_generateFromToken_startWithAttr() {
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Start('a',
+ array('href' => 'dyn?a=foo&b=bar')
+ ),
+ ''
+ );
+ }
+
+ function test_generateFromToken_end() {
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_End('b'),
+ ' '
+ );
+ }
+
+ function test_generateFromToken_emptyWithAttr() {
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Empty('br',
+ array('style' => 'font-family:"Courier New";')
+ ),
+ ' '
+ );
+ }
+
+ function test_generateFromToken_startNoAttr() {
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Start('asdf'),
+ ''
+ );
+ }
+
+ function test_generateFromToken_emptyNoAttr() {
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Empty('br'),
+ ' '
+ );
+ }
+
+ function test_generateFromToken_error() {
+ $this->expectError('Cannot generate HTML from non-HTMLPurifier_Token object');
+ $this->assertGenerateFromToken( null, '' );
+ }
+
+ function test_generateFromToken_unicode() {
+ $theta_char = $this->_entity_lookup->table['theta'];
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Text($theta_char),
+ $theta_char
+ );
+ }
+
+ function test_generateFromToken_backtick() {
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Start('img', array('alt' => '`foo')),
+ ' '
+ );
+ }
+
+ function test_generateFromToken_backtickDisabled() {
+ $this->config->set('Output.FixInnerHTML', false);
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Start('img', array('alt' => '`')),
+ ' '
+ );
+ }
+
+ function test_generateFromToken_backtickNoChange() {
+ $this->assertGenerateFromToken(
+ new HTMLPurifier_Token_Start('img', array('alt' => '`foo` bar')),
+ ' '
+ );
+ }
+
+ function assertGenerateAttributes($attr, $expect, $element = false) {
+ $generator = $this->createGenerator();
+ $result = $generator->generateAttributes($attr, $element);
+ $this->assertIdentical($result, $expect);
+ }
+
+ function test_generateAttributes_blank() {
+ $this->assertGenerateAttributes(array(), '');
+ }
+
+ function test_generateAttributes_basic() {
+ $this->assertGenerateAttributes(
+ array('href' => 'dyn?a=foo&b=bar'),
+ 'href="dyn?a=foo&b=bar"'
+ );
+ }
+
+ function test_generateAttributes_doubleQuote() {
+ $this->assertGenerateAttributes(
+ array('style' => 'font-family:"Courier New";'),
+ 'style="font-family:"Courier New";"'
+ );
+ }
+
+ function test_generateAttributes_singleQuote() {
+ $this->assertGenerateAttributes(
+ array('style' => 'font-family:\'Courier New\';'),
+ 'style="font-family:\'Courier New\';"'
+ );
+ }
+
+ function test_generateAttributes_multiple() {
+ $this->assertGenerateAttributes(
+ array('src' => 'picture.jpg', 'alt' => 'Short & interesting'),
+ 'src="picture.jpg" alt="Short & interesting"'
+ );
+ }
+
+ function test_generateAttributes_specialChar() {
+ $theta_char = $this->_entity_lookup->table['theta'];
+ $this->assertGenerateAttributes(
+ array('title' => 'Theta is ' . $theta_char),
+ 'title="Theta is ' . $theta_char . '"'
+ );
+ }
+
+
+ function test_generateAttributes_minimized() {
+ $this->config->set('HTML.Doctype', 'HTML 4.01 Transitional');
+ $this->assertGenerateAttributes(
+ array('compact' => 'compact'), 'compact', 'menu'
+ );
+ }
+
+ function test_generateFromTokens() {
+
+ $this->assertGeneration(
+ array(
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('Foobar!'),
+ new HTMLPurifier_Token_End('b')
+ ),
+ 'Foobar! '
+ );
+
+ }
+
+ protected function assertGeneration($tokens, $expect) {
+ $generator = new HTMLPurifier_Generator($this->config, $this->context);
+ $result = $generator->generateFromTokens($tokens);
+ $this->assertIdentical($expect, $result);
+ }
+
+ function test_generateFromTokens_Scripting() {
+ $this->assertGeneration(
+ array(
+ new HTMLPurifier_Token_Start('script'),
+ new HTMLPurifier_Token_Text('alert(3 < 5);'),
+ new HTMLPurifier_Token_End('script')
+ ),
+ ""
+ );
+ }
+
+ function test_generateFromTokens_Scripting_missingCloseTag() {
+ $this->assertGeneration(
+ array(
+ new HTMLPurifier_Token_Start('script'),
+ new HTMLPurifier_Token_Text('alert(3 < 5);'),
+ ),
+ ""
+ );
+ }
+
+ function test_generateFromTokens_Scripting_disableWrapper() {
+ $this->config->set('Output.CommentScriptContents', false);
+ $this->assertGeneration(
+ array(
+ new HTMLPurifier_Token_Start('script'),
+ new HTMLPurifier_Token_Text('alert(3 < 5);'),
+ new HTMLPurifier_Token_End('script')
+ ),
+ ""
+ );
+ }
+
+ function test_generateFromTokens_XHTMLoff() {
+ $this->config->set('HTML.XHTML', false);
+
+ // omit trailing slash
+ $this->assertGeneration(
+ array( new HTMLPurifier_Token_Empty('br') ),
+ ' '
+ );
+
+ // there should be a test for attribute minimization, but it is
+ // impossible for something like that to happen due to our current
+ // definitions! fix it later
+
+ // namespaced attributes must be dropped
+ $this->assertGeneration(
+ array( new HTMLPurifier_Token_Start('p', array('xml:lang'=>'fr')) ),
+ ''
+ );
+
+ }
+
+ function test_generateFromTokens_TidyFormat() {
+ // abort test if tidy isn't loaded
+ if (!extension_loaded('tidy')) return;
+
+ // just don't test; Tidy is exploding on me.
+ return;
+
+ $this->config->set('Core.TidyFormat', true);
+ $this->config->set('Output.Newline', "\n");
+
+ // nice wrapping please
+ $this->assertGeneration(
+ array(
+ new HTMLPurifier_Token_Start('div'),
+ new HTMLPurifier_Token_Text('Text'),
+ new HTMLPurifier_Token_End('div')
+ ),
+ "
\n Text\n
\n"
+ );
+
+ }
+
+ function test_generateFromTokens_sortAttr() {
+ $this->config->set('Output.SortAttr', true);
+
+ $this->assertGeneration(
+ array( new HTMLPurifier_Token_Start('p', array('b'=>'c', 'a'=>'d')) ),
+ ''
+ );
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLDefinitionTest.php b/lib/htmlpurifier/tests/HTMLPurifier/HTMLDefinitionTest.php
new file mode 100644
index 000000000..6640cb0d0
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLDefinitionTest.php
@@ -0,0 +1,355 @@
+config->set('Cache.DefinitionImpl', null);
+ parent::expectError($error);
+ }
+
+ function test_parseTinyMCEAllowedList() {
+
+ $def = new HTMLPurifier_HTMLDefinition();
+
+ // note: this is case-sensitive, but its config schema
+ // counterpart is not. This is generally a good thing for users,
+ // but it's a slight internal inconsistency
+
+ $this->assertEqual(
+ $def->parseTinyMCEAllowedList(''),
+ array(array(), array())
+ );
+
+ $this->assertEqual(
+ $def->parseTinyMCEAllowedList('a,b,c'),
+ array(array('a' => true, 'b' => true, 'c' => true), array())
+ );
+
+ $this->assertEqual(
+ $def->parseTinyMCEAllowedList('a[x|y|z]'),
+ array(array('a' => true), array('a.x' => true, 'a.y' => true, 'a.z' => true))
+ );
+
+ $this->assertEqual(
+ $def->parseTinyMCEAllowedList('*[id]'),
+ array(array(), array('*.id' => true))
+ );
+
+ $this->assertEqual(
+ $def->parseTinyMCEAllowedList('a[*]'),
+ array(array('a' => true), array('a.*' => true))
+ );
+
+ $this->assertEqual(
+ $def->parseTinyMCEAllowedList('span[style],strong,a[href|title]'),
+ array(array('span' => true, 'strong' => true, 'a' => true),
+ array('span.style' => true, 'a.href' => true, 'a.title' => true))
+ );
+
+ $this->assertEqual(
+ // alternate form:
+ $def->parseTinyMCEAllowedList(
+'span[style]
+strong
+a[href|title]
+'),
+ $val = array(array('span' => true, 'strong' => true, 'a' => true),
+ array('span.style' => true, 'a.href' => true, 'a.title' => true))
+ );
+
+ $this->assertEqual(
+ $def->parseTinyMCEAllowedList(' span [ style ], strong'."\n\t".'a[href | title]'),
+ $val
+ );
+
+ }
+
+ function test_Allowed() {
+
+ $config1 = HTMLPurifier_Config::create(array(
+ 'HTML.AllowedElements' => array('b', 'i', 'p', 'a'),
+ 'HTML.AllowedAttributes' => array('a@href', '*@id')
+ ));
+
+ $config2 = HTMLPurifier_Config::create(array(
+ 'HTML.Allowed' => 'b,i,p,a[href],*[id]'
+ ));
+
+ $this->assertEqual($config1->getHTMLDefinition(), $config2->getHTMLDefinition());
+
+ }
+
+ function assertPurification_AllowedElements_p() {
+ $this->assertPurification('
Jelly
', 'Jelly
');
+ }
+
+ function test_AllowedElements() {
+ $this->config->set('HTML.AllowedElements', 'p');
+ $this->assertPurification_AllowedElements_p();
+ }
+
+ function test_AllowedElements_multiple() {
+ $this->config->set('HTML.AllowedElements', 'p,div');
+ $this->assertPurification('', '');
+ }
+
+ function test_AllowedElements_invalidElement() {
+ $this->config->set('HTML.AllowedElements', 'obviously_invalid,p');
+ $this->expectError(new PatternExpectation("/Element 'obviously_invalid' is not supported/"));
+ $this->assertPurification_AllowedElements_p();
+ }
+
+ function test_AllowedElements_invalidElement_xssAttempt() {
+ $this->config->set('HTML.AllowedElements', '', ''
+ );
+ }
+
+ function testPreserve() {
+ $this->assertResult(
+ ''
+ );
+ }
+
+ function testCDATAEnclosure() {
+ $this->assertResult(
+''
+ );
+ }
+
+ function testAllAttributes() {
+ $this->assertResult(
+ ''
+ );
+ }
+
+ function testUnsupportedAttributes() {
+ $this->assertResult(
+ '',
+ ''
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/TargetBlankTest.php b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/TargetBlankTest.php
new file mode 100644
index 000000000..a757fecb3
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/TargetBlankTest.php
@@ -0,0 +1,20 @@
+config->set('HTML.TargetBlank', true);
+ }
+
+ function testTargetBlank() {
+ $this->assertResult(
+ 'a b c ',
+ 'a b c '
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/TidyTest.php b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/TidyTest.php
new file mode 100644
index 000000000..e80aeb16d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModule/TidyTest.php
@@ -0,0 +1,224 @@
+fixesForLevel['light'][] = 'light-fix';
+ $module->fixesForLevel['medium'][] = 'medium-fix';
+ $module->fixesForLevel['heavy'][] = 'heavy-fix';
+
+ $this->assertIdentical(
+ array(),
+ $module->getFixesForLevel('none')
+ );
+ $this->assertIdentical(
+ array('light-fix' => true),
+ $module->getFixesForLevel('light')
+ );
+ $this->assertIdentical(
+ array('light-fix' => true, 'medium-fix' => true),
+ $module->getFixesForLevel('medium')
+ );
+ $this->assertIdentical(
+ array('light-fix' => true, 'medium-fix' => true, 'heavy-fix' => true),
+ $module->getFixesForLevel('heavy')
+ );
+
+ $this->expectError('Tidy level turbo not recognized');
+ $module->getFixesForLevel('turbo');
+
+ }
+
+ function test_setup() {
+
+ $i = 0; // counter, helps us isolate expectations
+
+ // initialize partial mock
+ $module = new HTMLPurifier_HTMLModule_Tidy_TestForConstruct();
+ $module->fixesForLevel['light'] = array('light-fix-1', 'light-fix-2');
+ $module->fixesForLevel['medium'] = array('medium-fix-1', 'medium-fix-2');
+ $module->fixesForLevel['heavy'] = array('heavy-fix-1', 'heavy-fix-2');
+
+ $j = 0;
+ $fixes = array(
+ 'light-fix-1' => $lf1 = $j++,
+ 'light-fix-2' => $lf2 = $j++,
+ 'medium-fix-1' => $mf1 = $j++,
+ 'medium-fix-2' => $mf2 = $j++,
+ 'heavy-fix-1' => $hf1 = $j++,
+ 'heavy-fix-2' => $hf2 = $j++
+ );
+ $module->setReturnValue('makeFixes', $fixes);
+
+ $config = HTMLPurifier_Config::create(array(
+ 'HTML.TidyLevel' => 'none'
+ ));
+ $module->expectAt($i++, 'populate', array(array()));
+ $module->setup($config);
+
+ // basic levels
+
+ $config = HTMLPurifier_Config::create(array(
+ 'HTML.TidyLevel' => 'light'
+ ));
+ $module->expectAt($i++, 'populate', array(array(
+ 'light-fix-1' => $lf1,
+ 'light-fix-2' => $lf2
+ )));
+ $module->setup($config);
+
+ $config = HTMLPurifier_Config::create(array(
+ 'HTML.TidyLevel' => 'heavy'
+ ));
+ $module->expectAt($i++, 'populate', array(array(
+ 'light-fix-1' => $lf1,
+ 'light-fix-2' => $lf2,
+ 'medium-fix-1' => $mf1,
+ 'medium-fix-2' => $mf2,
+ 'heavy-fix-1' => $hf1,
+ 'heavy-fix-2' => $hf2
+ )));
+ $module->setup($config);
+
+ // fine grained tuning
+
+ $config = HTMLPurifier_Config::create(array(
+ 'HTML.TidyLevel' => 'none',
+ 'HTML.TidyAdd' => array('light-fix-1', 'medium-fix-1')
+ ));
+ $module->expectAt($i++, 'populate', array(array(
+ 'light-fix-1' => $lf1,
+ 'medium-fix-1' => $mf1
+ )));
+ $module->setup($config);
+
+ $config = HTMLPurifier_Config::create(array(
+ 'HTML.TidyLevel' => 'medium',
+ 'HTML.TidyRemove' => array('light-fix-1', 'medium-fix-1')
+ ));
+ $module->expectAt($i++, 'populate', array(array(
+ 'light-fix-2' => $lf2,
+ 'medium-fix-2' => $mf2
+ )));
+ $module->setup($config);
+
+ }
+
+ function test_makeFixesForLevel() {
+
+ $module = new HTMLPurifier_HTMLModule_Tidy();
+ $module->defaultLevel = 'heavy';
+
+ $module->makeFixesForLevel(array(
+ 'fix-1' => 0,
+ 'fix-2' => 1,
+ 'fix-3' => 2
+ ));
+
+ $this->assertIdentical($module->fixesForLevel['heavy'], array('fix-1', 'fix-2', 'fix-3'));
+ $this->assertIdentical($module->fixesForLevel['medium'], array());
+ $this->assertIdentical($module->fixesForLevel['light'], array());
+
+ }
+ function test_makeFixesForLevel_undefinedLevel() {
+
+ $module = new HTMLPurifier_HTMLModule_Tidy();
+ $module->defaultLevel = 'bananas';
+
+ $this->expectError('Default level bananas does not exist');
+
+ $module->makeFixesForLevel(array(
+ 'fix-1' => 0
+ ));
+
+ }
+
+ function test_getFixType() {
+
+ // syntax needs documenting
+
+ $module = new HTMLPurifier_HTMLModule_Tidy();
+
+ $this->assertIdentical(
+ $module->getFixType('a'),
+ array('tag_transform', array('element' => 'a'))
+ );
+
+ $this->assertIdentical(
+ $module->getFixType('a@href'),
+ $reuse = array('attr_transform_pre', array('element' => 'a', 'attr' => 'href'))
+ );
+
+ $this->assertIdentical(
+ $module->getFixType('a@href#pre'),
+ $reuse
+ );
+
+ $this->assertIdentical(
+ $module->getFixType('a@href#post'),
+ array('attr_transform_post', array('element' => 'a', 'attr' => 'href'))
+ );
+
+ $this->assertIdentical(
+ $module->getFixType('xml:foo@xml:bar'),
+ array('attr_transform_pre', array('element' => 'xml:foo', 'attr' => 'xml:bar'))
+ );
+
+ $this->assertIdentical(
+ $module->getFixType('blockquote#child'),
+ array('child', array('element' => 'blockquote'))
+ );
+
+ $this->assertIdentical(
+ $module->getFixType('@lang'),
+ array('attr_transform_pre', array('attr' => 'lang'))
+ );
+
+ $this->assertIdentical(
+ $module->getFixType('@lang#post'),
+ array('attr_transform_post', array('attr' => 'lang'))
+ );
+
+ }
+
+ function test_populate() {
+
+ $i = 0;
+
+ $module = new HTMLPurifier_HTMLModule_Tidy();
+ $module->populate(array(
+ 'element' => $element = $i++,
+ 'element@attr' => $attr = $i++,
+ 'element@attr#post' => $attr_post = $i++,
+ 'element#child' => $child = $i++,
+ 'element#content_model_type' => $content_model_type = $i++,
+ '@attr' => $global_attr = $i++,
+ '@attr#post' => $global_attr_post = $i++
+ ));
+
+ $module2 = new HTMLPurifier_HTMLModule_Tidy();
+ $e = $module2->addBlankElement('element');
+ $e->attr_transform_pre['attr'] = $attr;
+ $e->attr_transform_post['attr'] = $attr_post;
+ $e->child = $child;
+ $e->content_model_type = $content_model_type;
+ $module2->info_tag_transform['element'] = $element;
+ $module2->info_attr_transform_pre['attr'] = $global_attr;
+ $module2->info_attr_transform_post['attr'] = $global_attr_post;
+
+ $this->assertEqual($module, $module2);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleHarness.php
new file mode 100644
index 000000000..7aadf468a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleHarness.php
@@ -0,0 +1,11 @@
+obj = new HTMLPurifier_Strategy_Core();
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleManagerTest.php b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleManagerTest.php
new file mode 100644
index 000000000..2750f8924
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleManagerTest.php
@@ -0,0 +1,120 @@
+config->set('HTML.CustomDoctype', 'Blank');
+ $manager->doctypes->register('Blank');
+
+ $attrdef_nmtokens = new HTMLPurifier_AttrDef_HTML_Nmtokens();
+
+ generate_mock_once('HTMLPurifier_AttrDef');
+ $attrdef = new HTMLPurifier_AttrDefMock();
+ $attrdef->setReturnValue('make', $attrdef_nmtokens);
+ $manager->attrTypes->set('NMTOKENS', $attrdef);
+ return $manager;
+ }
+
+ function test_addModule() {
+
+ $manager = $this->createManager();
+
+ // ...but we add user modules
+
+ $common_module = new HTMLPurifier_HTMLModule();
+ $common_module->name = 'Common';
+ $common_module->attr_collections['Common'] = array('class' => 'NMTOKENS');
+ $common_module->content_sets['Flow'] = 'Block | Inline';
+ $manager->addModule($common_module);
+
+ $structural_module = new HTMLPurifier_HTMLModule();
+ $structural_module->name = 'Structural';
+ $structural_module->addElement('p', 'Block', 'Inline', 'Common');
+ $manager->addModule($structural_module);
+
+ $formatting_module = new HTMLPurifier_HTMLModule();
+ $formatting_module->name = 'Formatting';
+ $formatting_module->addElement('em', 'Inline', 'Inline', 'Common');
+ $manager->addModule($formatting_module);
+
+ $unsafe_module = new HTMLPurifier_HTMLModule();
+ $unsafe_module->name = 'Unsafe';
+ $unsafe_module->safe = false;
+ $unsafe_module->addElement('div', 'Block', 'Flow');
+ $manager->addModule($unsafe_module);
+
+ $config = HTMLPurifier_Config::createDefault();
+ $config->set('HTML.Trusted', false);
+ $config->set('HTML.CustomDoctype', 'Blank');
+
+ $manager->setup($config);
+
+ $attrdef_nmtokens = new HTMLPurifier_AttrDef_HTML_Nmtokens();
+
+ $p = new HTMLPurifier_ElementDef();
+ $p->attr['class'] = $attrdef_nmtokens;
+ $p->child = new HTMLPurifier_ChildDef_Optional(array('em', '#PCDATA'));
+ $p->content_model = 'em | #PCDATA';
+ $p->content_model_type = 'optional';
+ $p->descendants_are_inline = true;
+
+ $em = new HTMLPurifier_ElementDef();
+ $em->attr['class'] = $attrdef_nmtokens;
+ $em->child = new HTMLPurifier_ChildDef_Optional(array('em', '#PCDATA'));
+ $em->content_model = 'em | #PCDATA';
+ $em->content_model_type = 'optional';
+ $em->descendants_are_inline = true;
+
+ $this->assertEqual(
+ array('p' => $p, 'em' => $em),
+ $manager->getElements()
+ );
+
+ // test trusted parameter override
+
+ $div = new HTMLPurifier_ElementDef();
+ $div->child = new HTMLPurifier_ChildDef_Optional(array('p', 'div', 'em', '#PCDATA'));
+ $div->content_model = 'p | div | em | #PCDATA';
+ $div->content_model_type = 'optional';
+ $div->descendants_are_inline = false;
+
+ $this->assertEqual($div, $manager->getElement('div', true));
+
+ }
+
+ function testAllowedModules() {
+
+ $manager = new HTMLPurifier_HTMLModuleManager();
+ $manager->doctypes->register(
+ 'Fantasy Inventory 1.0', true,
+ array('Weapons', 'Magic')
+ );
+
+ // register these modules so it doesn't blow up
+ $weapons_module = new HTMLPurifier_HTMLModule();
+ $weapons_module->name = 'Weapons';
+ $manager->registerModule($weapons_module);
+
+ $magic_module = new HTMLPurifier_HTMLModule();
+ $magic_module->name = 'Magic';
+ $manager->registerModule($magic_module);
+
+ $config = HTMLPurifier_Config::create(array(
+ 'HTML.CustomDoctype' => 'Fantasy Inventory 1.0',
+ 'HTML.AllowedModules' => 'Weapons'
+ ));
+ $manager->setup($config);
+
+ $this->assertTrue( isset($manager->modules['Weapons']));
+ $this->assertFalse(isset($manager->modules['Magic']));
+
+ }
+
+
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleTest.php b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleTest.php
new file mode 100644
index 000000000..65220f08b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLModuleTest.php
@@ -0,0 +1,146 @@
+addElementToContentSet('b', 'Inline');
+ $this->assertIdentical($module->content_sets, array('Inline' => 'b'));
+
+ $module->addElementToContentSet('i', 'Inline');
+ $this->assertIdentical($module->content_sets, array('Inline' => 'b | i'));
+
+ }
+
+ function test_addElement() {
+
+ $module = new HTMLPurifier_HTMLModule();
+ $def = $module->addElement(
+ 'a', 'Inline', 'Optional: #PCDATA', array('Common'),
+ array(
+ 'href' => 'URI'
+ )
+ );
+
+ $module2 = new HTMLPurifier_HTMLModule();
+ $def2 = new HTMLPurifier_ElementDef();
+ $def2->content_model = '#PCDATA';
+ $def2->content_model_type = 'optional';
+ $def2->attr = array(
+ 'href' => 'URI',
+ 0 => array('Common')
+ );
+ $module2->info['a'] = $def2;
+ $module2->elements = array('a');
+ $module2->content_sets['Inline'] = 'a';
+
+ $this->assertIdentical($module, $module2);
+ $this->assertIdentical($def, $def2);
+ $this->assertReference($def, $module->info['a']);
+
+ }
+
+ function test_parseContents() {
+
+ $module = new HTMLPurifier_HTMLModule();
+
+ // pre-defined templates
+ $this->assertIdentical(
+ $module->parseContents('Inline'),
+ array('optional', 'Inline | #PCDATA')
+ );
+ $this->assertIdentical(
+ $module->parseContents('Flow'),
+ array('optional', 'Flow | #PCDATA')
+ );
+ $this->assertIdentical(
+ $module->parseContents('Empty'),
+ array('empty', '')
+ );
+
+ // normalization procedures
+ $this->assertIdentical(
+ $module->parseContents('optional: a'),
+ array('optional', 'a')
+ );
+ $this->assertIdentical(
+ $module->parseContents('OPTIONAL :a'),
+ array('optional', 'a')
+ );
+ $this->assertIdentical(
+ $module->parseContents('Optional: a'),
+ array('optional', 'a')
+ );
+
+ // others
+ $this->assertIdentical(
+ $module->parseContents('Optional: a | b | c'),
+ array('optional', 'a | b | c')
+ );
+
+ // object pass-through
+ generate_mock_once('HTMLPurifier_AttrDef');
+ $this->assertIdentical(
+ $module->parseContents(new HTMLPurifier_AttrDefMock()),
+ array(null, null)
+ );
+
+ }
+
+ function test_mergeInAttrIncludes() {
+
+ $module = new HTMLPurifier_HTMLModule();
+
+ $attr = array();
+ $module->mergeInAttrIncludes($attr, 'Common');
+ $this->assertIdentical($attr, array(0 => array('Common')));
+
+ $attr = array('a' => 'b');
+ $module->mergeInAttrIncludes($attr, array('Common', 'Good'));
+ $this->assertIdentical($attr, array('a' => 'b', 0 => array('Common', 'Good')));
+
+ }
+
+ function test_addBlankElement() {
+
+ $module = new HTMLPurifier_HTMLModule();
+ $def = $module->addBlankElement('a');
+
+ $def2 = new HTMLPurifier_ElementDef();
+ $def2->standalone = false;
+
+ $this->assertReference($module->info['a'], $def);
+ $this->assertIdentical($def, $def2);
+
+ }
+
+ function test_makeLookup() {
+
+ $module = new HTMLPurifier_HTMLModule();
+
+ $this->assertIdentical(
+ $module->makeLookup('foo'),
+ array('foo' => true)
+ );
+ $this->assertIdentical(
+ $module->makeLookup(array('foo')),
+ array('foo' => true)
+ );
+
+ $this->assertIdentical(
+ $module->makeLookup('foo', 'two'),
+ array('foo' => true, 'two' => true)
+ );
+ $this->assertIdentical(
+ $module->makeLookup(array('foo', 'two')),
+ array('foo' => true, 'two' => true)
+ );
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT.php b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT.php
new file mode 100644
index 000000000..06e7958fb
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT.php
@@ -0,0 +1,33 @@
+path = $path;
+ parent::__construct($path);
+ }
+
+ public function testHtmlt() {
+ $parser = new HTMLPurifier_StringHashParser();
+ $hash = $parser->parseFile($this->path); // assume parser normalizes to "\n"
+ if (isset($hash['SKIPIF'])) {
+ if (eval($hash['SKIPIF'])) return;
+ }
+ $this->config->set('Output.Newline', "\n");
+ if (isset($hash['INI'])) {
+ // there should be a more efficient way than writing another
+ // ini file every time... probably means building a parser for
+ // ini (check out the yaml implementation we saw somewhere else)
+ $ini_file = $this->path . '.ini';
+ file_put_contents($ini_file, $hash['INI']);
+ $this->config->loadIni($ini_file);
+ }
+ $expect = isset($hash['EXPECT']) ? $hash['EXPECT'] : $hash['HTML'];
+ $this->assertPurification(rtrim($hash['HTML']), rtrim($expect));
+ if (isset($hash['INI'])) unlink($ini_file);
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/allowed-preserve.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/allowed-preserve.htmlt
new file mode 100644
index 000000000..650f00b6b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/allowed-preserve.htmlt
@@ -0,0 +1,8 @@
+--INI--
+HTML.AllowedElements = b,i,p,a
+HTML.AllowedAttributes = a.href,*.id
+--HTML--
+Par.
+Paragr aph
+TextBold
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/allowed-remove.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/allowed-remove.htmlt
new file mode 100644
index 000000000..2b6b8eea6
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/allowed-remove.htmlt
@@ -0,0 +1,8 @@
+--INI--
+HTML.AllowedElements = b,i,p,a
+HTML.AllowedAttributes = a.href,*.id
+--HTML--
+Not allowed Remove id too!
+--EXPECT--
+Not allowedRemove id too!
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/basic.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/basic.htmlt
new file mode 100644
index 000000000..4c1f42778
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/basic.htmlt
@@ -0,0 +1,5 @@
+--HTML--
+basic
+--EXPECT--
+basic
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/blacklist-preserve.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/blacklist-preserve.htmlt
new file mode 100644
index 000000000..d8882fe22
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/blacklist-preserve.htmlt
@@ -0,0 +1,6 @@
+--INI--
+HTML.ForbiddenElements = b
+HTML.ForbiddenAttributes = a@href
+--HTML--
+foo
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/blacklist-remove.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/blacklist-remove.htmlt
new file mode 100644
index 000000000..1b5985873
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/blacklist-remove.htmlt
@@ -0,0 +1,8 @@
+--INI--
+HTML.ForbiddenElements = b
+HTML.ForbiddenAttributes = a@href
+--HTML--
+Foobar
+--EXPECT--
+Foobar
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/css-allowed-preserve.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/css-allowed-preserve.htmlt
new file mode 100644
index 000000000..a5fe3f849
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/css-allowed-preserve.htmlt
@@ -0,0 +1,5 @@
+--INI--
+CSS.AllowedProperties = color,background-color
+--HTML--
+red
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/css-allowed-remove.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/css-allowed-remove.htmlt
new file mode 100644
index 000000000..644b7001a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/css-allowed-remove.htmlt
@@ -0,0 +1,7 @@
+--INI--
+CSS.AllowedProperties = color,background-color
+--HTML--
+red
+--EXPECT--
+red
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/disable-uri.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/disable-uri.htmlt
new file mode 100644
index 000000000..fa692e444
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/disable-uri.htmlt
@@ -0,0 +1,6 @@
+--INI--
+URI.Disable = true
+--HTML--
+
+--EXPECT--
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/double-youtube.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/double-youtube.htmlt
new file mode 100644
index 000000000..a46ce4736
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/double-youtube.htmlt
@@ -0,0 +1,6 @@
+--INI--
+HTML.SafeObject = true
+Output.FlashCompat = true
+--HTML--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/empty.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/empty.htmlt
new file mode 100644
index 000000000..9094c47b0
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/empty.htmlt
@@ -0,0 +1,6 @@
+--INI--
+
+--HTML--
+
+--EXPECT--
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/file-uri.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/file-uri.htmlt
new file mode 100644
index 000000000..5b9e34a8c
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/file-uri.htmlt
@@ -0,0 +1,5 @@
+--INI--
+URI.AllowedSchemes = file
+--HTML--
+foo
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-default.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-default.htmlt
new file mode 100644
index 000000000..1c1460f2c
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-default.htmlt
@@ -0,0 +1,5 @@
+--HTML--
+foobar
+--EXPECT--
+foobar
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-enabled.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-enabled.htmlt
new file mode 100644
index 000000000..70ddcf99f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-enabled.htmlt
@@ -0,0 +1,6 @@
+--INI--
+Attr.EnableID = true
+--HTML--
+foobar
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-img.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-img.htmlt
new file mode 100644
index 000000000..12755bea3
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-img.htmlt
@@ -0,0 +1,8 @@
+--INI--
+Attr.EnableID = true
+Core.LexerImpl = DirectLex
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-name-mix.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-name-mix.htmlt
new file mode 100644
index 000000000..a48da8e62
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/id-name-mix.htmlt
@@ -0,0 +1,11 @@
+--INI--
+Attr.EnableID = true
+--HTML--
+Test
+Test2
+Test3
+--EXPECT--
+Test
+Test2
+Test3
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/inline-list-loop.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/inline-list-loop.htmlt
new file mode 100644
index 000000000..0a63e8955
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/inline-list-loop.htmlt
@@ -0,0 +1,5 @@
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/inline-wraps-block.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/inline-wraps-block.htmlt
new file mode 100644
index 000000000..da6bae689
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/inline-wraps-block.htmlt
@@ -0,0 +1,5 @@
+--HTML--
+Foobar
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/list-nesting.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/list-nesting.htmlt
new file mode 100644
index 000000000..22ebf6058
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/list-nesting.htmlt
@@ -0,0 +1,5 @@
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/munge-extra.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/munge-extra.htmlt
new file mode 100644
index 000000000..4b1c70a9d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/munge-extra.htmlt
@@ -0,0 +1,11 @@
+--INI--
+URI.Munge = "/redirect?s=%s&t=%t&r=%r&n=%n&m=%m&p=%p"
+URI.MungeSecretKey = "foo"
+URI.MungeResources = true
+--HTML--
+Link
+
+--EXPECT--
+Link
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/munge.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/munge.htmlt
new file mode 100644
index 000000000..827c216e6
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/munge.htmlt
@@ -0,0 +1,52 @@
+--INI--
+URI.Munge = "/r/%s"
+URI.AllowedSchemes = http,ftp,file
+--HTML--
+foo
+foo
+foo
+foo
+foo
+
+foo
+foo
+foo
+foo
+foo
+
+foo
+foo
+foo
+foo
+foo
+
+foo
+foo
+foo
+foo
+foo
+--EXPECT--
+foo
+foo
+foo
+foo
+foo
+
+foo
+foo
+foo
+foo
+foo
+
+foo
+foo
+foo
+foo
+foo
+
+foo
+foo
+foo
+foo
+foo
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/name.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/name.htmlt
new file mode 100644
index 000000000..1713ed417
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/name.htmlt
@@ -0,0 +1,6 @@
+--INI--
+Attr.EnableID = true
+HTML.Doctype = "XHTML 1.0 Strict"
+--HTML--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-googlemaps.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-googlemaps.htmlt
new file mode 100644
index 000000000..40fac62d5
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-googlemaps.htmlt
@@ -0,0 +1,8 @@
+--INI--
+HTML.SafeIframe = true
+URI.SafeIframeRegexp = "%^http://maps.google.com/%"
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-invalid.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-invalid.htmlt
new file mode 100644
index 000000000..5b366da54
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-invalid.htmlt
@@ -0,0 +1,7 @@
+--INI--
+HTML.SafeIframe = true
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-youtube.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-youtube.htmlt
new file mode 100644
index 000000000..1abc2c827
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe-youtube.htmlt
@@ -0,0 +1,8 @@
+--INI--
+HTML.SafeIframe = true
+URI.SafeIframeRegexp = "%^http://www.youtube.com/embed/%"
+--HTML--
+VIDEO
+--EXPECT--
+VIDEO
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe.htmlt
new file mode 100644
index 000000000..7c0b60d2f
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-iframe.htmlt
@@ -0,0 +1,14 @@
+--INI--
+HTML.SafeIframe = true
+URI.SafeIframeRegexp = "%(^http://www.example.com/|^https?://dev.example.com/)%"
+--HTML--
+
+
+
+
+--EXPECT--
+
+
+
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-object-embed-munge.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-object-embed-munge.htmlt
new file mode 100644
index 000000000..77b32d3a1
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-object-embed-munge.htmlt
@@ -0,0 +1,10 @@
+--INI--
+HTML.SafeObject = true
+HTML.SafeEmbed = true
+URI.Munge = "/redirect.php?url=%s&check=%t"
+URI.MungeSecretKey = "foo"
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-object-embed.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-object-embed.htmlt
new file mode 100644
index 000000000..f4bb0ff09
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/safe-object-embed.htmlt
@@ -0,0 +1,8 @@
+--INI--
+HTML.SafeObject = true
+HTML.SafeEmbed = true
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-bare.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-bare.htmlt
new file mode 100644
index 000000000..f85c2fb5e
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-bare.htmlt
@@ -0,0 +1,9 @@
+--INI--
+HTML.Trusted = true
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-cdata.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-cdata.htmlt
new file mode 100644
index 000000000..e7d6d7f5b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-cdata.htmlt
@@ -0,0 +1,11 @@
+--INI--
+HTML.Trusted = true
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-comment.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-comment.htmlt
new file mode 100644
index 000000000..006901919
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-comment.htmlt
@@ -0,0 +1,11 @@
+--INI--
+HTML.Trusted = true
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-dbl-comment.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-dbl-comment.htmlt
new file mode 100644
index 000000000..ef899b597
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-dbl-comment.htmlt
@@ -0,0 +1,11 @@
+--INI--
+HTML.Trusted = true
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-ideal.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-ideal.htmlt
new file mode 100644
index 000000000..70510687c
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/script-ideal.htmlt
@@ -0,0 +1,11 @@
+--INI--
+HTML.Trusted = true
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/secure-munge.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/secure-munge.htmlt
new file mode 100644
index 000000000..114cb0000
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/secure-munge.htmlt
@@ -0,0 +1,10 @@
+--INI--
+URI.Munge = "/redirect.php?url=%s&check=%t"
+URI.MungeSecretKey = "foo"
+--HTML--
+foo
+
+--EXPECT--
+foo
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/shift-jis-preserve-yen.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/shift-jis-preserve-yen.htmlt
new file mode 100644
index 000000000..f22417c01
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/shift-jis-preserve-yen.htmlt
@@ -0,0 +1,8 @@
+--SKIPIF--
+if (!function_exists('iconv')) return true;
+--INI--
+Core.Encoding = "Shift_JIS"
+Core.EscapeNonASCIICharacters = true
+--HTML--
+111
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/shift-jis-remove-yen.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/shift-jis-remove-yen.htmlt
new file mode 100644
index 000000000..6c2d3bc4c
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/shift-jis-remove-yen.htmlt
@@ -0,0 +1,9 @@
+--SKIPIF--
+if (!function_exists('iconv')) return true;
+--INI--
+Core.Encoding = Shift_JIS
+--HTML--
+111
+--EXPECT--
+111
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-blockquote-with-inline.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-blockquote-with-inline.htmlt
new file mode 100644
index 000000000..a6eb0ec66
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-blockquote-with-inline.htmlt
@@ -0,0 +1,7 @@
+--INI--
+HTML.Doctype = "XHTML 1.0 Strict"
+--HTML--
+Illegal contents
+--EXPECT--
+Illegal contents
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-blockquote.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-blockquote.htmlt
new file mode 100644
index 000000000..b61e8dc07
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-blockquote.htmlt
@@ -0,0 +1,7 @@
+--INI--
+HTML.Strict = true
+--HTML--
+Illegal contents
+--EXPECT--
+Illegal contents
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-underline.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-underline.htmlt
new file mode 100644
index 000000000..a2e18b1c9
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/strict-underline.htmlt
@@ -0,0 +1,7 @@
+--INI--
+HTML.Strict = true
+--HTML--
+Illegal underline
+--EXPECT--
+Illegal underline
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/tidy-background.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/tidy-background.htmlt
new file mode 100644
index 000000000..08bda2678
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/tidy-background.htmlt
@@ -0,0 +1,5 @@
+--HTML--
+
+--EXPECT--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments-required.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments-required.htmlt
new file mode 100644
index 000000000..62dc159d0
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments-required.htmlt
@@ -0,0 +1,6 @@
+--INI--
+HTML.Trusted = true
+--HTML--
+
+--EXPECT--
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments-table.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments-table.htmlt
new file mode 100644
index 000000000..89d80febf
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments-table.htmlt
@@ -0,0 +1,5 @@
+--INI--
+HTML.Trusted = true
+--HTML--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments.htmlt
new file mode 100644
index 000000000..93b4a35a6
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/trusted-comments.htmlt
@@ -0,0 +1,5 @@
+--INI--
+HTML.Trusted = true
+--HTML--
+
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/whitespace-preserve.htmlt b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/whitespace-preserve.htmlt
new file mode 100644
index 000000000..861bddaf4
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/HTMLT/whitespace-preserve.htmlt
@@ -0,0 +1,3 @@
+--HTML--
+Foo bar
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Harness.php b/lib/htmlpurifier/tests/HTMLPurifier/Harness.php
new file mode 100644
index 000000000..d6490a117
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Harness.php
@@ -0,0 +1,90 @@
+config, $this->context) = $this->createCommon();
+ $this->config->set('Output.Newline', '
+');
+ $this->purifier = new HTMLPurifier();
+ }
+
+ /**
+ * Asserts a purification. Good for integration testing.
+ */
+ function assertPurification($input, $expect = null) {
+ if ($expect === null) $expect = $input;
+ $result = $this->purifier->purify($input, $this->config);
+ $this->assertIdentical($expect, $result);
+ }
+
+
+ /**
+ * Accepts config and context and prepares them into a valid state
+ * @param &$config Reference to config variable
+ * @param &$context Reference to context variable
+ */
+ protected function prepareCommon(&$config, &$context) {
+ $config = HTMLPurifier_Config::create($config);
+ if (!$context) $context = new HTMLPurifier_Context();
+ }
+
+ /**
+ * Generates default configuration and context objects
+ * @return Defaults in form of array($config, $context)
+ */
+ protected function createCommon() {
+ return array(HTMLPurifier_Config::createDefault(), new HTMLPurifier_Context);
+ }
+
+ /**
+ * Normalizes a string to Unix (\n) endings
+ */
+ protected function normalize(&$string) {
+ $string = str_replace(array("\r\n", "\r"), "\n", $string);
+ }
+
+ /**
+ * If $expect is false, ignore $result and check if status failed.
+ * Otherwise, check if $status if true and $result === $expect.
+ * @param $status Boolean status
+ * @param $result Mixed result from processing
+ * @param $expect Mixed expectation for result
+ */
+ protected function assertEitherFailOrIdentical($status, $result, $expect) {
+ if ($expect === false) {
+ $this->assertFalse($status, 'Expected false result, got true');
+ } else {
+ $this->assertTrue($status, 'Expected true result, got false');
+ $this->assertIdentical($result, $expect);
+ }
+ }
+
+ public function getTests() {
+ // __onlytest makes only one test get triggered
+ foreach (get_class_methods(get_class($this)) as $method) {
+ if (strtolower(substr($method, 0, 10)) == '__onlytest') {
+ $this->reporter->paintSkip('All test methods besides ' . $method);
+ return array($method);
+ }
+ }
+ return parent::getTests();
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/IDAccumulatorTest.php b/lib/htmlpurifier/tests/HTMLPurifier/IDAccumulatorTest.php
new file mode 100644
index 000000000..90bca0739
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/IDAccumulatorTest.php
@@ -0,0 +1,39 @@
+assertTrue( $accumulator->add('id1'));
+ $this->assertTrue( $accumulator->add('id2'));
+ $this->assertFalse($accumulator->add('id1')); // repeated id
+
+ // you can also access the properties (they're public)
+ $this->assertTrue( isset($accumulator->ids['id2']) );
+
+ }
+
+ function testLoad() {
+
+ $accumulator = new HTMLPurifier_IDAccumulator();
+
+ $accumulator->load(array('id1', 'id2', 'id3'));
+
+ $this->assertFalse($accumulator->add('id1')); // repeated id
+ $this->assertTrue($accumulator->add('id4'));
+
+ }
+
+ function testBuild() {
+ $this->config->set('Attr.IDBlacklist', array('foo'));
+ $accumulator = HTMLPurifier_IDAccumulator::build($this->config, $this->context);
+ $this->assertTrue( isset($accumulator->ids['foo']) );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Injector/AutoParagraphTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Injector/AutoParagraphTest.php
new file mode 100644
index 000000000..e6abbd1ff
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Injector/AutoParagraphTest.php
@@ -0,0 +1,515 @@
+config->set('AutoFormat.AutoParagraph', true);
+ }
+
+ function testSingleParagraph() {
+ $this->assertResult(
+ 'Foobar',
+ 'Foobar
'
+ );
+ }
+
+ function testSingleMultiLineParagraph() {
+ $this->assertResult(
+'Par 1
+Par 1 still',
+'Par 1
+Par 1 still
'
+ );
+ }
+
+ function testTwoParagraphs() {
+ $this->assertResult(
+'Par1
+
+Par2',
+"Par1
+
+Par2
"
+ );
+ }
+
+ function testTwoParagraphsWithLotsOfSpace() {
+ $this->assertResult(
+'Par1
+
+
+
+Par2',
+'Par1
+
+Par2
'
+ );
+ }
+
+ function testTwoParagraphsWithInlineElements() {
+ $this->assertResult(
+'Par1
+
+Par2 ',
+'Par1
+
+Par2
'
+ );
+ }
+
+ function testSingleParagraphThatLooksLikeTwo() {
+ $this->assertResult(
+'Par1
+
+Par2 ',
+'Par1
+
+Par2
'
+ );
+ }
+
+ function testAddParagraphAdjacentToParagraph() {
+ $this->assertResult(
+ 'Par1Par2
',
+'Par1
+
+Par2
'
+ );
+ }
+
+ function testParagraphUnclosedInlineElement() {
+ $this->assertResult(
+ 'Par1',
+ ' Par1
'
+ );
+ }
+
+ function testPreservePreTags() {
+ $this->assertResult(
+'Par1
+
+Par1 '
+ );
+ }
+
+ function testIgnoreTrailingWhitespace() {
+ $this->assertResult(
+'Par1
+
+ ',
+'Par1
+
+'
+ );
+ }
+
+ function testDoNotParagraphBlockElements() {
+ $this->assertResult(
+'Par1
+
+Par2
+
+Par3',
+'Par1
+
+Par2
+
+Par3
'
+ );
+ }
+
+ function testParagraphTextAndInlineNodes() {
+ $this->assertResult(
+'Par1 ',
+ 'Par1
'
+ );
+ }
+
+ function testPreserveLeadingWhitespace() {
+ $this->assertResult(
+'
+
+Par',
+'
+
+Par
'
+ );
+ }
+
+ function testPreserveSurroundingWhitespace() {
+ $this->assertResult(
+'
+
+Par
+
+',
+'
+
+Par
+
+'
+ );
+ }
+
+ function testParagraphInsideBlockNode() {
+ $this->assertResult(
+'Par1
+
+Par2
',
+''
+ );
+ }
+
+ function testParagraphInlineNodeInsideBlockNode() {
+ $this->assertResult(
+'Par1
+
+Par2
',
+''
+ );
+ }
+
+ function testNoParagraphWhenOnlyOneInsideBlockNode() {
+ $this->assertResult('Par1
');
+ }
+
+ function testParagraphTwoInlineNodesInsideBlockNode() {
+ $this->assertResult(
+'Par1
+
+Par2
',
+''
+ );
+ }
+
+ function testPreserveInlineNodesInPreTag() {
+ $this->assertResult(
+'Par1
+
+Par2 '
+ );
+ }
+
+ function testSplitUpInternalsOfPTagInBlockNode() {
+ $this->assertResult(
+'',
+''
+ );
+ }
+
+ function testSplitUpInlineNodesInPTagInBlockNode() {
+ $this->assertResult(
+'',
+''
+ );
+ }
+
+ function testNoParagraphSingleInlineNodeInBlockNode() {
+ $this->assertResult( 'Foo
' );
+ }
+
+ function testParagraphInBlockquote() {
+ $this->assertResult(
+'Par1
+
+Par2 ',
+'Par1
+
+Par2
'
+ );
+ }
+
+ function testNoParagraphBetweenListItem() {
+ $this->assertResult(
+''
+ );
+ }
+
+ function testParagraphSingleElementWithSurroundingSpace() {
+ $this->assertResult(
+'
+
+Bar
+
+
',
+ ''
+ );
+ }
+
+ function testIgnoreExtraSpaceWithLeadingInlineNode() {
+ $this->assertResult(
+'Par1 a
+
+
+
+Par2',
+'Par1 a
+
+Par2
'
+ );
+ }
+
+ function testAbsorbExtraEndingPTag() {
+ $this->assertResult(
+'Par1
+
+Par2
',
+'Par1
+
+Par2
'
+ );
+ }
+
+ function testAbsorbExtraEndingDivTag() {
+ $this->assertResult(
+'Par1
+
+Par2',
+'Par1
+
+Par2
'
+ );
+ }
+
+ function testDoNotParagraphSingleSurroundingSpaceInBlockNode() {
+ $this->assertResult(
+'
+Par1
+
'
+ );
+ }
+
+ function testBlockNodeTextDelimeterInBlockNode() {
+ $this->assertResult(
+'',
+''
+ );
+ }
+
+ function testBlockNodeTextDelimeterWithoutDoublespaceInBlockNode() {
+ $this->assertResult(
+''
+ );
+ }
+
+ function testBlockNodeTextDelimeterWithoutDoublespace() {
+ $this->assertResult(
+'Par1
+Par2
',
+'Par1
+
+
+Par2
'
+ );
+ }
+
+ function testTwoParagraphsOfTextAndInlineNode() {
+ $this->assertResult(
+'Par1
+
+Par2 ',
+'Par1
+
+Par2
'
+ );
+ }
+
+ function testLeadingInlineNodeParagraph() {
+ $this->assertResult(
+' Foo',
+' Foo
'
+ );
+ }
+
+ function testTrailingInlineNodeParagraph() {
+ $this->assertResult(
+'Foo bar '
+ );
+ }
+
+ function testTwoInlineNodeParagraph() {
+ $this->assertResult(
+'baz bar '
+ );
+ }
+
+ function testNoParagraphTrailingBlockNodeInBlockNode() {
+ $this->assertResult(
+''
+ );
+ }
+
+ function testParagraphTrailingBlockNodeWithDoublespaceInBlockNode() {
+ $this->assertResult(
+'',
+''
+ );
+ }
+
+ function testParagraphTwoInlineNodesAndWhitespaceNode() {
+ $this->assertResult(
+'One Two ',
+'One Two
'
+ );
+ }
+
+ function testNoParagraphWithInlineRootNode() {
+ $this->config->set('HTML.Parent', 'span');
+ $this->assertResult(
+'Par
+
+Par2'
+ );
+ }
+
+ function testInlineAndBlockTagInDivNoParagraph() {
+ $this->assertResult(
+ ''
+ );
+ }
+
+ function testInlineAndBlockTagInDivNeedingParagraph() {
+ $this->assertResult(
+'',
+''
+ );
+ }
+
+ function testTextInlineNodeTextThenDoubleNewlineNeedsParagraph() {
+ $this->assertResult(
+'',
+''
+ );
+ }
+
+ function testUpcomingTokenHasNewline() {
+ $this->assertResult(
+'Testfoo barbing bang
+
+boo
',
+'Testfoo barbing bang
+
+
boo
'
+);
+ }
+
+ function testEmptyTokenAtEndOfDiv() {
+ $this->assertResult(
+'',
+''
+);
+ }
+
+ function testEmptyDoubleLineTokenAtEndOfDiv() {
+ $this->assertResult(
+'',
+''
+);
+ }
+
+ function testTextState11Root() {
+ $this->assertResult('
');
+ }
+
+ function testTextState11Element() {
+ $this->assertResult(
+"");
+ }
+
+ function testTextStateLikeElementState111NoWhitespace() {
+ $this->assertResult('', '');
+ }
+
+ function testElementState111NoWhitespace() {
+ $this->assertResult('', '');
+ }
+
+ function testElementState133() {
+ $this->assertResult(
+"",
+""
+);
+ }
+
+ function testElementState22() {
+ $this->assertResult(
+ ''
+ );
+ }
+
+ function testElementState311() {
+ $this->assertResult(
+ 'Foo
Bar ',
+'Foo
+
+Bar
'
+ );
+ }
+
+ function testAutoClose() {
+ $this->assertResult(
+ '
+ '
+ );
+ }
+
+ function testErrorNeeded() {
+ $this->config->set('HTML.Allowed', 'b');
+ $this->expectError('Cannot enable AutoParagraph injector because p is not allowed');
+ $this->assertResult('foobar ');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Injector/DisplayLinkURITest.php b/lib/htmlpurifier/tests/HTMLPurifier/Injector/DisplayLinkURITest.php
new file mode 100644
index 000000000..1629d9bd1
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Injector/DisplayLinkURITest.php
@@ -0,0 +1,33 @@
+config->set('AutoFormat.DisplayLinkURI', true);
+ }
+
+ function testBasicLink() {
+ $this->assertResult(
+ 'Don\'t go here! ',
+ 'Don\'t go here! (http://malware.example.com)'
+ );
+ }
+
+ function testEmptyLink() {
+ $this->assertResult(
+ 'Don\'t go here! ',
+ 'Don\'t go here! '
+ );
+ }
+ function testEmptyText() {
+ $this->assertResult(
+ ' ',
+ ' (http://malware.example.com)'
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Injector/LinkifyTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Injector/LinkifyTest.php
new file mode 100644
index 000000000..1a1542d53
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Injector/LinkifyTest.php
@@ -0,0 +1,50 @@
+config->set('AutoFormat.Linkify', true);
+ }
+
+ function testLinkifyURLInRootNode() {
+ $this->assertResult(
+ 'http://example.com',
+ 'http://example.com '
+ );
+ }
+
+ function testLinkifyURLInInlineNode() {
+ $this->assertResult(
+ 'http://example.com ',
+ 'http://example.com '
+ );
+ }
+
+ function testBasicUsageCase() {
+ $this->assertResult(
+ 'This URL http://example.com is what you need',
+ 'This URL http://example.com is what you need'
+ );
+ }
+
+ function testIgnoreURLInATag() {
+ $this->assertResult(
+ 'http://example.com/ '
+ );
+ }
+
+ function testNeeded() {
+ $this->config->set('HTML.Allowed', 'b');
+ $this->expectError('Cannot enable Linkify injector because a is not allowed');
+ $this->assertResult('http://example.com/');
+ }
+
+ function testExcludes() {
+ $this->assertResult('http://example.com ');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Injector/PurifierLinkifyTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Injector/PurifierLinkifyTest.php
new file mode 100644
index 000000000..774b234ad
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Injector/PurifierLinkifyTest.php
@@ -0,0 +1,59 @@
+config->set('AutoFormat.PurifierLinkify', true);
+ $this->config->set('AutoFormat.PurifierLinkify.DocURL', '#%s');
+ }
+
+ function testNoTriggerCharacer() {
+ $this->assertResult('Foobar');
+ }
+
+ function testTriggerCharacterInIrrelevantContext() {
+ $this->assertResult('20% off!');
+ }
+
+ function testPreserveNamespace() {
+ $this->assertResult('%Core namespace (not recognized)');
+ }
+
+ function testLinkifyBasic() {
+ $this->assertResult(
+ '%Namespace.Directive',
+ '%Namespace.Directive '
+ );
+ }
+
+ function testLinkifyWithAdjacentTextNodes() {
+ $this->assertResult(
+ 'This %Namespace.Directive thing',
+ 'This %Namespace.Directive thing'
+ );
+ }
+
+ function testLinkifyInBlock() {
+ $this->assertResult(
+ 'This %Namespace.Directive thing
',
+ ''
+ );
+ }
+
+ function testPreserveInATag() {
+ $this->assertResult(
+ '%Namespace.Directive '
+ );
+ }
+
+ function testNeeded() {
+ $this->config->set('HTML.Allowed', 'b');
+ $this->expectError('Cannot enable PurifierLinkify injector because a is not allowed');
+ $this->assertResult('%Namespace.Directive');
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Injector/RemoveEmptyTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Injector/RemoveEmptyTest.php
new file mode 100644
index 000000000..34dbc9515
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Injector/RemoveEmptyTest.php
@@ -0,0 +1,80 @@
+config->set('AutoFormat.RemoveEmpty', true);
+ }
+
+ function testPreserve() {
+ $this->assertResult('asdf ');
+ }
+
+ function testRemove() {
+ $this->assertResult(' ', '');
+ }
+
+ function testRemoveWithSpace() {
+ $this->assertResult(' ', '');
+ }
+
+ function testRemoveWithAttr() {
+ $this->assertResult(' ', '');
+ }
+
+ function testRemoveIdAndName() {
+ $this->assertResult(' ', '');
+ }
+
+ function testPreserveColgroup() {
+ $this->assertResult(' ');
+ }
+
+ function testPreserveId() {
+ $this->config->set('Attr.EnableID', true);
+ $this->assertResult(' ');
+ }
+
+ function testPreserveName() {
+ $this->config->set('Attr.EnableID', true);
+ $this->assertResult(' ');
+ }
+
+ function testRemoveNested() {
+ $this->assertResult(' ', '');
+ }
+
+ function testRemoveNested2() {
+ $this->assertResult(' ', '');
+ }
+
+ function testRemoveNested3() {
+ $this->assertResult(' ', '');
+ }
+
+ function testRemoveNbsp() {
+ $this->config->set('AutoFormat.RemoveEmpty.RemoveNbsp', true);
+ $this->assertResult(' ', '');
+ }
+
+ function testRemoveNbspMix() {
+ $this->config->set('AutoFormat.RemoveEmpty.RemoveNbsp', true);
+ $this->assertResult(' ', '');
+ }
+
+ function testDontRemoveNbsp() {
+ $this->config->set('AutoFormat.RemoveEmpty.RemoveNbsp', true);
+ $this->assertResult(' ', " \xC2\xA0 ");
+ }
+
+ function testRemoveNbspExceptionsSpecial() {
+ $this->config->set('AutoFormat.RemoveEmpty.RemoveNbsp', true);
+ $this->config->set('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions', 'b');
+ $this->assertResult(' ', "\xC2\xA0 ");
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Injector/RemoveSpansWithoutAttributesTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Injector/RemoveSpansWithoutAttributesTest.php
new file mode 100755
index 000000000..704c1cd7b
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Injector/RemoveSpansWithoutAttributesTest.php
@@ -0,0 +1,99 @@
+config->set('HTML.Allowed', 'span[class],div,p,strong,em');
+ $this->config->set('AutoFormat.RemoveSpansWithoutAttributes', true);
+ }
+
+ function testSingleSpan() {
+ $this->assertResult(
+ 'foo ',
+ 'foo'
+ );
+ }
+
+ function testSingleSpanWithAttributes() {
+ $this->assertResult(
+ 'foo ',
+ 'foo '
+ );
+ }
+
+ function testSingleNestedSpan() {
+ $this->assertResult(
+ 'foo
',
+ 'foo
'
+ );
+ }
+
+ function testSingleNestedSpanWithAttributes() {
+ $this->assertResult(
+ 'foo
',
+ 'foo
'
+ );
+ }
+
+
+ function testSpanWithChildren() {
+ $this->assertResult(
+ 'foo bar baz ',
+ 'foo bar baz '
+ );
+ }
+
+ function testSpanWithSiblings() {
+ $this->assertResult(
+ 'before inside after
',
+ 'before inside after
'
+ );
+ }
+
+ function testNestedSpanWithSiblingsAndChildren() {
+ $this->assertResult(
+ 'a b c d e
',
+ 'a b c d e
'
+ );
+ }
+
+ function testNestedSpansWithoutAttributes() {
+ $this->assertResult(
+ 'onetwothree ',
+ 'onetwothree'
+ );
+ }
+
+ function testDeeplyNestedSpan() {
+ $this->assertResult(
+ '',
+ ''
+ );
+ }
+
+ function testSpanWithInvalidAttributes() {
+ $this->assertResult(
+ 'foo
',
+ 'foo
'
+ );
+ }
+
+ function testNestedAlternateSpans() {
+ $this->assertResult(
+'a b c d e f
+ ',
+'a b c d e f
+ '
+ );
+ }
+
+ function testSpanWithSomeInvalidAttributes() {
+ $this->assertResult(
+ 'foo
',
+ 'foo
'
+ );
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Injector/SafeObjectTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Injector/SafeObjectTest.php
new file mode 100644
index 000000000..59e0493c3
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Injector/SafeObjectTest.php
@@ -0,0 +1,88 @@
+config->set('AutoFormat.Custom', array(new HTMLPurifier_Injector_SafeObject()));
+ $this->config->set('HTML.Trusted', true);
+ }
+
+ function testPreserve() {
+ $this->assertResult(
+ 'asdf '
+ );
+ }
+
+ function testRemoveStrayParam() {
+ $this->assertResult(
+ ' ',
+ ''
+ );
+ }
+
+ function testEditObjectParam() {
+ $this->assertResult(
+ ' ',
+ ' '
+ );
+ }
+
+ function testIgnoreStrayParam() {
+ $this->assertResult(
+ ' ',
+ ' '
+ );
+ }
+
+ function testIgnoreDuplicates() {
+ $this->assertResult(
+ ' '
+ );
+ }
+
+ function testIgnoreBogusData() {
+ $this->assertResult(
+ ' ',
+ ' '
+ );
+ }
+
+ function testIgnoreInvalidData() {
+ $this->assertResult(
+ ' ',
+ ' '
+ );
+ }
+
+ function testKeepValidData() {
+ $this->assertResult(
+ ' ',
+ ' '
+ );
+ }
+
+ function testNested() {
+ $this->assertResult(
+ ' ',
+ ' '
+ );
+ }
+
+ function testNotActuallyNested() {
+ $this->assertResult(
+ '
',
+ '
'
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/InjectorHarness.php b/lib/htmlpurifier/tests/HTMLPurifier/InjectorHarness.php
new file mode 100644
index 000000000..e3815175a
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/InjectorHarness.php
@@ -0,0 +1,13 @@
+obj = new HTMLPurifier_Strategy_MakeWellFormed();
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/LanguageFactoryTest.php b/lib/htmlpurifier/tests/HTMLPurifier/LanguageFactoryTest.php
new file mode 100644
index 000000000..9fea24f42
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/LanguageFactoryTest.php
@@ -0,0 +1,70 @@
+factory = HTMLPurifier_LanguageFactory::instance();
+ parent::setUp();
+ }
+
+ function test() {
+
+ $this->config->set('Core.Language', 'en');
+ $language = $this->factory->create($this->config, $this->context);
+
+ $this->assertIsA($language, 'HTMLPurifier_Language');
+ $this->assertIdentical($language->code, 'en');
+
+ // lazy loading test
+ $this->assertIdentical(count($language->messages), 0);
+ $language->load();
+ $this->assertNotEqual(count($language->messages), 0);
+
+ }
+
+ function testFallback() {
+
+ $this->config->set('Core.Language', 'en-x-test');
+ $language = $this->factory->create($this->config, $this->context);
+
+ $this->assertIsA($language, 'HTMLPurifier_Language_en_x_test');
+ $this->assertIdentical($language->code, 'en-x-test');
+
+ $language->load();
+
+ // test overloaded message
+ $this->assertIdentical($language->getMessage('HTMLPurifier'), 'HTML Purifier X');
+
+ // test inherited message
+ $this->assertIdentical($language->getMessage('LanguageFactoryTest: Pizza'), 'Pizza');
+
+ }
+
+ function testFallbackWithNoClass() {
+ $this->config->set('Core.Language', 'en-x-testmini');
+ $language = $this->factory->create($this->config, $this->context);
+ $this->assertIsA($language, 'HTMLPurifier_Language');
+ $this->assertIdentical($language->code, 'en-x-testmini');
+ $language->load();
+ $this->assertIdentical($language->getMessage('HTMLPurifier'), 'HTML Purifier XNone');
+ $this->assertIdentical($language->getMessage('LanguageFactoryTest: Pizza'), 'Pizza');
+ $this->assertIdentical($language->error, false);
+ }
+
+ function testNoSuchLanguage() {
+ $this->config->set('Core.Language', 'en-x-testnone');
+ $language = $this->factory->create($this->config, $this->context);
+ $this->assertIsA($language, 'HTMLPurifier_Language');
+ $this->assertIdentical($language->code, 'en-x-testnone');
+ $this->assertIdentical($language->error, true);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/LanguageTest.php b/lib/htmlpurifier/tests/HTMLPurifier/LanguageTest.php
new file mode 100644
index 000000000..033b6aa71
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/LanguageTest.php
@@ -0,0 +1,79 @@
+_loaded using something else
+ */
+class HTMLPurifier_LanguageTest extends HTMLPurifier_Harness
+{
+
+ protected $lang;
+
+ protected function generateEnLanguage() {
+ $factory = HTMLPurifier_LanguageFactory::instance();
+ $config = HTMLPurifier_Config::create(array('Core.Language' => 'en'));
+ $context = new HTMLPurifier_Context();
+ return $factory->create($config, $context);
+ }
+
+ function test_getMessage() {
+ $config = HTMLPurifier_Config::createDefault();
+ $context = new HTMLPurifier_Context();
+ $lang = new HTMLPurifier_Language($config, $context);
+ $lang->_loaded = true;
+ $lang->messages['HTMLPurifier'] = 'HTML Purifier';
+ $this->assertIdentical($lang->getMessage('HTMLPurifier'), 'HTML Purifier');
+ $this->assertIdentical($lang->getMessage('LanguageTest: Totally non-existent key'), '[LanguageTest: Totally non-existent key]');
+ }
+
+ function test_formatMessage() {
+ $config = HTMLPurifier_Config::createDefault();
+ $context = new HTMLPurifier_Context();
+ $lang = new HTMLPurifier_Language($config, $context);
+ $lang->_loaded = true;
+ $lang->messages['LanguageTest: Error'] = 'Error is $1 on line $2';
+ $this->assertIdentical($lang->formatMessage('LanguageTest: Error', array(1=>'fatal', 32)), 'Error is fatal on line 32');
+ }
+
+ function test_formatMessage_tokenParameter() {
+ $config = HTMLPurifier_Config::createDefault();
+ $context = new HTMLPurifier_Context();
+ $generator = new HTMLPurifier_Generator($config, $context); // replace with mock if this gets icky
+ $context->register('Generator', $generator);
+ $lang = new HTMLPurifier_Language($config, $context);
+ $lang->_loaded = true;
+ $lang->messages['LanguageTest: Element info'] = 'Element Token: $1.Name, $1.Serialized, $1.Compact, $1.Line';
+ $lang->messages['LanguageTest: Data info'] = 'Data Token: $1.Data, $1.Serialized, $1.Compact, $1.Line';
+ $this->assertIdentical($lang->formatMessage('LanguageTest: Element info',
+ array(1=>new HTMLPurifier_Token_Start('a', array('href'=>'http://example.com'), 18))),
+ 'Element Token: a, , , 18');
+ $this->assertIdentical($lang->formatMessage('LanguageTest: Data info',
+ array(1=>new HTMLPurifier_Token_Text('data>', 23))),
+ 'Data Token: data>, data>, data>, 23');
+ }
+
+ function test_listify() {
+ $lang = $this->generateEnLanguage();
+ $this->assertEqual($lang->listify(array('Item')), 'Item');
+ $this->assertEqual($lang->listify(array('Item', 'Item2')), 'Item and Item2');
+ $this->assertEqual($lang->listify(array('Item', 'Item2', 'Item3')), 'Item, Item2 and Item3');
+ }
+
+ function test_formatMessage_arrayParameter() {
+ $lang = $this->generateEnLanguage();
+
+ $array = array('Item1', 'Item2', 'Item3');
+ $this->assertIdentical(
+ $lang->formatMessage('LanguageTest: List', array(1=>$array)),
+ 'Item1, Item2 and Item3'
+ );
+
+ $array = array('Key1' => 'Value1', 'Key2' => 'Value2');
+ $this->assertIdentical(
+ $lang->formatMessage('LanguageTest: Hash', array(1=>$array)),
+ 'Key1 and Key2; Value1 and Value2'
+ );
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/LengthTest.php b/lib/htmlpurifier/tests/HTMLPurifier/LengthTest.php
new file mode 100644
index 000000000..2968b6d33
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/LengthTest.php
@@ -0,0 +1,73 @@
+assertIdentical($l->getN(), '23');
+ $this->assertIdentical($l->getUnit(), 'in');
+ }
+
+ function testMake() {
+ $l = HTMLPurifier_Length::make('+23.4in');
+ $this->assertIdentical($l->getN(), '+23.4');
+ $this->assertIdentical($l->getUnit(), 'in');
+ }
+
+ function testToString() {
+ $l = new HTMLPurifier_Length('23', 'in');
+ $this->assertIdentical($l->toString(), '23in');
+ }
+
+ protected function assertValidate($string, $expect = true) {
+ if ($expect === true) $expect = $string;
+ $l = HTMLPurifier_Length::make($string);
+ $result = $l->isValid();
+ if ($result === false) $this->assertIdentical($expect, false);
+ else $this->assertIdentical($l->toString(), $expect);
+ }
+
+ function testValidate() {
+ $this->assertValidate('0');
+ $this->assertValidate('+0', '0');
+ $this->assertValidate('-0', '0');
+ $this->assertValidate('0px');
+ $this->assertValidate('4.5px');
+ $this->assertValidate('-4.5px');
+ $this->assertValidate('3ex');
+ $this->assertValidate('3em');
+ $this->assertValidate('3in');
+ $this->assertValidate('3cm');
+ $this->assertValidate('3mm');
+ $this->assertValidate('3pt');
+ $this->assertValidate('3pc');
+ $this->assertValidate('3PX', '3px');
+ $this->assertValidate('3', false);
+ $this->assertValidate('3miles', false);
+ }
+
+ /**
+ * @param $s1 First string to compare
+ * @param $s2 Second string to compare
+ * @param $expect 0 for $s1 == $s2, 1 for $s1 > $s2 and -1 for $s1 < $s2
+ */
+ protected function assertComparison($s1, $s2, $expect = 0) {
+ $l1 = HTMLPurifier_Length::make($s1);
+ $l2 = HTMLPurifier_Length::make($s2);
+ $r1 = $l1->compareTo($l2);
+ $r2 = $l2->compareTo($l1);
+ $this->assertIdentical($r1 == 0 ? 0 : ($r1 > 0 ? 1 : -1), $expect);
+ $this->assertIdentical($r2 == 0 ? 0 : ($r2 > 0 ? 1 : -1), - $expect);
+ }
+
+ function testCompareTo() {
+ $this->assertComparison('12in', '12in');
+ $this->assertComparison('12in', '12mm', 1);
+ $this->assertComparison('1px', '1mm', -1);
+ $this->assertComparison(str_repeat('2', 38) . 'in', '100px', 1);
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Lexer/DirectLexTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Lexer/DirectLexTest.php
new file mode 100644
index 000000000..095b5c952
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Lexer/DirectLexTest.php
@@ -0,0 +1,130 @@
+DirectLex = new HTMLPurifier_Lexer_DirectLex();
+ }
+
+ // internals testing
+ function test_parseAttributeString() {
+
+ $input[0] = 'href="about:blank" rel="nofollow"';
+ $expect[0] = array('href'=>'about:blank', 'rel'=>'nofollow');
+
+ $input[1] = "href='about:blank'";
+ $expect[1] = array('href'=>'about:blank');
+
+ // note that the single quotes aren't /really/ escaped
+ $input[2] = 'onclick="javascript:alert(\'asdf\');"';
+ $expect[2] = array('onclick' => "javascript:alert('asdf');");
+
+ $input[3] = 'selected';
+ $expect[3] = array('selected'=>'selected');
+
+ // [INVALID]
+ $input[4] = '="nokey"';
+ $expect[4] = array();
+
+ // [SIMPLE]
+ $input[5] = 'color=blue';
+ $expect[5] = array('color' => 'blue');
+
+ // [INVALID]
+ $input[6] = 'href="about:blank';
+ $expect[6] = array('href' => 'about:blank');
+
+ // [INVALID]
+ $input[7] = '"=';
+ $expect[7] = array('"' => '');
+ // we ought to get array()
+
+ $input[8] = 'href ="about:blank"rel ="nofollow"';
+ $expect[8] = array('href' => 'about:blank', 'rel' => 'nofollow');
+
+ $input[9] = 'two bool';
+ $expect[9] = array('two' => 'two', 'bool' => 'bool');
+
+ $input[10] = 'name="input" selected';
+ $expect[10] = array('name' => 'input', 'selected' => 'selected');
+
+ $input[11] = '=""';
+ $expect[11] = array();
+
+ $input[12] = '="" =""';
+ $expect[12] = array('"' => ''); // tough to say, just don't throw a loop
+
+ $input[13] = 'href="';
+ $expect[13] = array('href' => '');
+
+ $input[14] = 'href=" <';
+ $expect[14] = array('href' => ' <');
+
+ $config = HTMLPurifier_Config::createDefault();
+ $context = new HTMLPurifier_Context();
+ $size = count($input);
+ for($i = 0; $i < $size; $i++) {
+ $result = $this->DirectLex->parseAttributeString($input[$i], $config, $context);
+ $this->assertIdentical($expect[$i], $result, 'Test ' . $i . ': %s');
+ }
+
+ }
+
+ function testLineNumbers() {
+
+ // . . . . . . . . . .
+ // 01234567890123 01234567890123 0123456789012345 0123456789012 012345
+ $html = "Line 1 \nLine 2 \nStill Line 2 Now Line 4\n\n ";
+
+ $expect = array(
+ // line 1
+ 0 => new HTMLPurifier_Token_Start('b')
+ ,1 => new HTMLPurifier_Token_Text('Line 1')
+ ,2 => new HTMLPurifier_Token_End('b')
+ ,3 => new HTMLPurifier_Token_Text("\n")
+ // line 2
+ ,4 => new HTMLPurifier_Token_Start('i')
+ ,5 => new HTMLPurifier_Token_Text('Line 2')
+ ,6 => new HTMLPurifier_Token_End('i')
+ ,7 => new HTMLPurifier_Token_Text("\nStill Line 2")
+ // line 3
+ ,8 => new HTMLPurifier_Token_Empty('br')
+ // line 4
+ ,9 => new HTMLPurifier_Token_Text("Now Line 4\n\n")
+ // line SIX
+ ,10 => new HTMLPurifier_Token_Empty('br')
+ );
+
+ $context = new HTMLPurifier_Context();
+ $config = HTMLPurifier_Config::createDefault();
+ $output = $this->DirectLex->tokenizeHTML($html, $config, $context);
+
+ $this->assertIdentical($output, $expect);
+
+ $context = new HTMLPurifier_Context();
+ $config = HTMLPurifier_Config::create(array(
+ 'Core.MaintainLineNumbers' => true
+ ));
+ $expect[0]->position(1, 0);
+ $expect[1]->position(1, 3);
+ $expect[2]->position(1, 9);
+ $expect[3]->position(2, -1);
+ $expect[4]->position(2, 0);
+ $expect[5]->position(2, 3);
+ $expect[6]->position(2, 9);
+ $expect[7]->position(3, -1);
+ $expect[8]->position(3, 12);
+ $expect[9]->position(4, 2);
+ $expect[10]->position(6, 0);
+
+ $output = $this->DirectLex->tokenizeHTML($html, $config, $context);
+ $this->assertIdentical($output, $expect);
+
+ }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/tests/HTMLPurifier/Lexer/DirectLex_ErrorsTest.php b/lib/htmlpurifier/tests/HTMLPurifier/Lexer/DirectLex_ErrorsTest.php
new file mode 100644
index 000000000..69d3c628d
--- /dev/null
+++ b/lib/htmlpurifier/tests/HTMLPurifier/Lexer/DirectLex_ErrorsTest.php
@@ -0,0 +1,58 @@
+tokenizeHTML($input, $this->config, $this->context);
+ }
+
+ function invokeAttr($input) {
+ $lexer = new HTMLPurifier_Lexer_DirectLex();
+ $lexer->parseAttributeString($input, $this->config, $this->context);
+ }
+
+ function testExtractBody() {
+ $this->expectErrorCollection(E_WARNING, 'Lexer: Extracted body');
+ $this->invoke('foo');
+ }
+
+ function testUnclosedComment() {
+ $this->expectErrorCollection(E_WARNING, 'Lexer: Unclosed comment');
+ $this->expectContext('CurrentLine', 1);
+ $this->invoke('',
+ array( new HTMLPurifier_Token_Comment(' Comment ') )
+ );
+ }
+
+ function test_tokenizeHTML_malformedComment() {
+ $this->assertTokenization(
+ '',
+ array( new HTMLPurifier_Token_Comment(' not so well formed -') )
+ );
+ }
+
+ function test_tokenizeHTML_unterminatedTag() {
+ $this->assertTokenization(
+ ' array( new HTMLPurifier_Token_Empty('a', array('href'=>'')) ),
+ 'PH5P' => false, // total barfing, grabs scaffolding too
+ )
+ );
+ }
+
+ function test_tokenizeHTML_specialEntities() {
+ $this->assertTokenization(
+ '<b>',
+ array(
+ new HTMLPurifier_Token_Text('')
+ ),
+ array(
+ // some parsers will separate entities out
+ 'PH5P' => array(
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('b'),
+ new HTMLPurifier_Token_Text('>'),
+ ),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_earlyQuote() {
+ $this->assertTokenization(
+ '',
+ array( new HTMLPurifier_Token_Empty('a') ),
+ array(
+ // we barf on this input
+ 'DirectLex' => array(
+ new HTMLPurifier_Token_Start('a', array('"' => ''))
+ ),
+ 'PH5P' => false, // behavior varies; handle this personally
+ )
+ );
+ }
+
+ function test_tokenizeHTML_earlyQuote_PH5P() {
+ if (!class_exists('DOMDocument')) return;
+ $lexer = new HTMLPurifier_Lexer_PH5P();
+ $result = $lexer->tokenizeHTML(' ', $this->config, $this->context);
+ if ($this->context->get('PH5PError', true)) {
+ $this->assertIdentical(array(
+ new HTMLPurifier_Token_Start('a', array('"' => ''))
+ ), $result);
+ } else {
+ $this->assertIdentical(array(
+ new HTMLPurifier_Token_Empty('a', array('"' => ''))
+ ), $result);
+ }
+ }
+
+ function test_tokenizeHTML_unescapedQuote() {
+ $this->assertTokenization(
+ '"',
+ array( new HTMLPurifier_Token_Text('"') )
+ );
+ }
+
+ function test_tokenizeHTML_escapedQuote() {
+ $this->assertTokenization(
+ '"',
+ array( new HTMLPurifier_Token_Text('"') )
+ );
+ }
+
+ function test_tokenizeHTML_cdata() {
+ $this->assertTokenization(
+ 'can't get me!]]>',
+ array( new HTMLPurifier_Token_Text('You can't get me!') ),
+ array(
+ 'PH5P' => array(
+ new HTMLPurifier_Token_Text('You '),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('b'),
+ new HTMLPurifier_Token_Text('>'),
+ new HTMLPurifier_Token_Text('can'),
+ new HTMLPurifier_Token_Text('&'),
+ new HTMLPurifier_Token_Text('#39;t'),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('/b'),
+ new HTMLPurifier_Token_Text('>'),
+ new HTMLPurifier_Token_Text(' get me!'),
+ ),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_characterEntity() {
+ $this->assertTokenization(
+ 'θ',
+ array( new HTMLPurifier_Token_Text("\xCE\xB8") )
+ );
+ }
+
+ function test_tokenizeHTML_characterEntityInCDATA() {
+ $this->assertTokenization(
+ '',
+ array( new HTMLPurifier_Token_Text("→") ),
+ array(
+ 'PH5P' => array(
+ new HTMLPurifier_Token_Text('&'),
+ new HTMLPurifier_Token_Text('rarr;'),
+ ),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_entityInAttribute() {
+ $this->assertTokenization(
+ ' Link ',
+ array(
+ new HTMLPurifier_Token_Start('a',array('href' => 'index.php?title=foo&id=bar')),
+ new HTMLPurifier_Token_Text('Link'),
+ new HTMLPurifier_Token_End('a'),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_preserveUTF8() {
+ $this->assertTokenization(
+ "\xCE\xB8",
+ array( new HTMLPurifier_Token_Text("\xCE\xB8") )
+ );
+ }
+
+ function test_tokenizeHTML_specialEntityInAttribute() {
+ $this->assertTokenization(
+ ' ',
+ array( new HTMLPurifier_Token_Empty('br', array('test' => 'x < 6')) )
+ );
+ }
+
+ function test_tokenizeHTML_emoticonProtection() {
+ $this->assertTokenization(
+ 'Whoa! <3 That\'s not good >.> ',
+ array(
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('Whoa! '),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('3 That\'s not good >.>'),
+ new HTMLPurifier_Token_End('b')
+ ),
+ array(
+ // text is absorbed together
+ 'DOMLex' => array(
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('Whoa! <3 That\'s not good >.>'),
+ new HTMLPurifier_Token_End('b'),
+ ),
+ 'PH5P' => array( // interesting grouping
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('Whoa! '),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('3 That\'s not good >.>'),
+ new HTMLPurifier_Token_End('b'),
+ ),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_commentWithFunkyChars() {
+ $this->assertTokenization(
+ ' ',
+ array(
+ new HTMLPurifier_Token_Comment(' This >< comment '),
+ new HTMLPurifier_Token_Empty('br'),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_unterminatedComment() {
+ $this->assertTokenization(
+ '',
+ array( new HTMLPurifier_Token_Comment(' This comment < < & ') )
+ );
+ }
+
+ function test_tokenizeHTML_attributeWithSpecialCharacters() {
+ $this->assertTokenization(
+ '',
+ array( new HTMLPurifier_Token_Empty('a', array('href' => '><>')) ),
+ array(
+ 'DirectLex' => array(
+ new HTMLPurifier_Token_Start('a', array('href' => '')),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('">'),
+ )
+ )
+ );
+ }
+
+ function test_tokenizeHTML_emptyTagWithSlashInAttribute() {
+ $this->assertTokenization(
+ ' ',
+ array( new HTMLPurifier_Token_Empty('param', array('name' => 'src', 'value' => 'http://example.com/video.wmv')) )
+ );
+ }
+
+ function test_tokenizeHTML_style() {
+ $extra = array(
+ // PH5P doesn't seem to like style tags
+ 'PH5P' => false,
+ // DirectLex defers to RemoveForeignElements for textification
+ 'DirectLex' => array(
+ new HTMLPurifier_Token_Start('style', array('type' => 'text/css')),
+ new HTMLPurifier_Token_Comment("\ndiv {}\n"),
+ new HTMLPurifier_Token_End('style'),
+ ),
+ );
+ if (!defined('LIBXML_VERSION')) {
+ // LIBXML_VERSION is missing in early versions of PHP
+ // prior to 1.30 of php-src/ext/libxml/libxml.c (version-wise,
+ // this translates to 5.0.x. In such cases, punt the test entirely.
+ return;
+ } elseif (LIBXML_VERSION < 20628) {
+ // libxml's behavior is wrong prior to this version, so make
+ // appropriate accomodations
+ $extra['DOMLex'] = $extra['DirectLex'];
+ }
+ $this->assertTokenization(
+'',
+ array(
+ new HTMLPurifier_Token_Start('style', array('type' => 'text/css')),
+ new HTMLPurifier_Token_Text("\ndiv {}\n"),
+ new HTMLPurifier_Token_End('style'),
+ ),
+ $extra
+ );
+ }
+
+ function test_tokenizeHTML_tagWithAtSignAndExtraGt() {
+ $alt_expect = array(
+ // Technically this is invalid, but it won't be a
+ // problem with invalid element removal; also, this
+ // mimics Mozilla's parsing of the tag.
+ new HTMLPurifier_Token_Start('a@'),
+ new HTMLPurifier_Token_Text('>'),
+ );
+ $this->assertTokenization(
+ ' >',
+ array(
+ new HTMLPurifier_Token_Start('a'),
+ new HTMLPurifier_Token_Text('>'),
+ new HTMLPurifier_Token_End('a'),
+ ),
+ array(
+ 'DirectLex' => $alt_expect,
+ )
+ );
+ }
+
+ function test_tokenizeHTML_emoticonHeart() {
+ $this->assertTokenization(
+ ' <3 ',
+ array(
+ new HTMLPurifier_Token_Empty('br'),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('3'),
+ new HTMLPurifier_Token_Empty('br'),
+ ),
+ array(
+ 'DOMLex' => array(
+ new HTMLPurifier_Token_Empty('br'),
+ new HTMLPurifier_Token_Text('<3'),
+ new HTMLPurifier_Token_Empty('br'),
+ ),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_emoticonShiftyEyes() {
+ $this->assertTokenization(
+ '<< ',
+ array(
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_End('b'),
+ ),
+ array(
+ 'DOMLex' => array(
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('<<'),
+ new HTMLPurifier_Token_End('b'),
+ ),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_eon1996() {
+ $this->assertTokenization(
+ '< test ',
+ array(
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text(' '),
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('test'),
+ new HTMLPurifier_Token_End('b'),
+ ),
+ array(
+ 'DOMLex' => array(
+ new HTMLPurifier_Token_Text('< '),
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('test'),
+ new HTMLPurifier_Token_End('b'),
+ ),
+ )
+ );
+ }
+
+ function test_tokenizeHTML_bodyInCDATA() {
+ $alt_tokens = array(
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('body'),
+ new HTMLPurifier_Token_Text('>'),
+ new HTMLPurifier_Token_Text('Foo'),
+ new HTMLPurifier_Token_Text('<'),
+ new HTMLPurifier_Token_Text('/body'),
+ new HTMLPurifier_Token_Text('>'),
+ );
+ $this->assertTokenization(
+ 'Foo Foo