Merge branch '1.10.x' of github.com:chamilo/chamilo-lms into 1.10.x

1.10.x
Yannick Warnier 10 years ago
commit 27796b63aa
  1. 14
      .gitattributes
  2. 35
      composer.json
  3. 186
      composer.lock
  4. 65
      main/announcements/announcements.php
  5. 2
      main/course_notice/index.php
  6. 118
      main/cron/import_csv.php
  7. 3
      main/cron/user_import/client.php
  8. 10
      main/document/create_audio.php
  9. 36
      main/document/file.php
  10. 6
      main/exercice/export/aiken/aiken_import.inc.php
  11. 25
      main/gradebook/lib/be/studentpublicationlink.class.php
  12. 2
      main/inc/ajax/install.ajax.php
  13. 18
      main/inc/autoload.inc.php
  14. 4
      main/inc/global.inc.php
  15. 0
      main/inc/lib/AnnouncementEmail.php
  16. 2
      main/inc/lib/autoload.class.php
  17. 3
      main/inc/lib/certificate.lib.php
  18. 3072
      main/inc/lib/ezpdf/class.pdf.php
  19. 2
      main/inc/lib/formvalidator/Rule/allowed_tags.inc.php
  20. 1
      main/inc/lib/htmlpurifier/VERSION
  21. 6
      main/inc/lib/htmlpurifier/configdoc/index.html
  22. 6
      main/inc/lib/htmlpurifier/configdoc/styles/index.html
  23. 6
      main/inc/lib/htmlpurifier/extras/ConfigDoc/index.html
  24. 6
      main/inc/lib/htmlpurifier/extras/FSTools/index.html
  25. 6
      main/inc/lib/htmlpurifier/extras/index.html
  26. 6
      main/inc/lib/htmlpurifier/index.html
  27. 21
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
  28. 28
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
  29. 72
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
  30. 47
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php
  31. 78
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
  32. 40
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php
  33. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/index.html
  34. 28
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php
  35. 32
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php
  36. 21
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
  37. 70
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php
  38. 41
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php
  39. 41
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
  40. 48
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php
  41. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/index.html
  42. 15
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php
  43. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/index.html
  44. 68
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php
  45. 99
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php
  46. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/URI/index.html
  47. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrDef/index.html
  48. 36
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php
  49. 58
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php
  50. 27
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php
  51. 21
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php
  52. 27
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php
  53. 16
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php
  54. 18
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php
  55. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/AttrTransform/index.html
  56. 104
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Bootstrap.php
  57. 301
      main/inc/lib/htmlpurifier/library/HTMLPurifier/CSSDefinition.php
  58. 26
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php
  59. 117
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php
  60. 88
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php
  61. 142
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php
  62. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ChildDef/index.html
  63. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/index.html
  64. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/index.html
  65. 66
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php
  66. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ConfigSchema/index.html
  67. BIN
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser
  68. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/index.html
  69. 82
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Context.php
  70. 62
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php
  71. 43
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php
  72. 46
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php
  73. 47
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in
  74. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/index.html
  75. 39
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php
  76. 172
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php
  77. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/index.html
  78. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/DefinitionCache/index.html
  79. 1
      main/inc/lib/htmlpurifier/library/HTMLPurifier/EntityLookup/entities.ser
  80. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/EntityLookup/index.html
  81. 0
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Filter/AllowIframes.php
  82. 135
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php
  83. 39
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php
  84. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Filter/index.html
  85. 118
      main/inc/lib/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php
  86. 21
      main/inc/lib/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php
  87. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/index.html
  88. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/HTMLModule/index.html
  89. 51
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php
  90. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Injector/index.html
  91. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Language/classes/index.html
  92. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Language/index.html
  93. 63
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Language/messages/en.php
  94. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Language/messages/index.html
  95. 139
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Lexer/PEARSax3.php
  96. 3904
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php
  97. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Lexer/index.html
  98. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Printer/index.html
  99. 328
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php
  100. 6
      main/inc/lib/htmlpurifier/library/HTMLPurifier/Strategy/index.html
  101. Some files were not shown because too many files have changed in this diff Show More

14
.gitattributes vendored

@ -2,3 +2,17 @@
.gitignore export-ignore
.travis.yml export-ignore
/tests export-ignore
/vendor/ezyang/htmlpurifier/docs export-ignore
/vendor/ezyang/htmlpurifier/benchmarks export-ignore
/vendor/ezyang/htmlpurifier/tests export-ignore
/vendor/ezyang/htmlpurifier/smoketests export-ignore
/vendor/ezyang/htmlpurifier/package.php export-ignore
/vendor/ezyang/htmlpurifier/release1-update.php export-ignore
/vendor/ezyang/htmlpurifier/release2-tag.php export-ignore
/vendor/ezyang/htmlpurifier/test-settings.sample.php export-ignore
/vendor/twig/twig/test export-ignore
/vendor/monolog/monolog/tests/ export-ignore
/vendor/neutron/temporary-filesystem/tests export-ignore
/vendor/sabre/vobject/tests export-ignore
/vendor/twig/twig/test export-ignore

@ -1,11 +1,44 @@
{
"name": "chamilo/chamilo-lms",
"description": "E-learning and collaboration software",
"type": "project",
"homepage": "http://www.chamilo.org",
"license": "GPL-3.0",
"support": {
"forum": "http://www.chamilo.org/forum",
"irc": "irc://irc.freenode.org/chamilo"
},
"autoload": {
"classmap": [
"main/auth",
"main/admin",
"main/cron/lang",
"main/coursecopy",
"main/exercice",
"main/gradebook/lib",
"main/newscorm",
"main/inc/lib",
"plugin",
"main/install",
"main/inc/lib/getid3",
"main/survey"
]
},
"require": {
"php": ">=5.3.3",
"php-ffmpeg/php-ffmpeg": "0.3.x-dev@dev",
"sabre/vobject": "~3.1",
"toin0u/digitalocean": "~1.4",
"twig/twig": "1.*",
"michelf/php-markdown": "1.4.1",
"emojione/emojione": "1.3.0",
"zendframework/zend-config": "2.3.3"
"zendframework/zend-config": "2.3.3",
"ezyang/htmlpurifier": "4.6.0",
"aferrandini/phpqrcode": "1.0.1"
},
"extra": {
"branch-alias": {
"dev-master": "1.10.x-dev"
}
}
}

186
composer.lock generated

@ -4,8 +4,52 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "1abe77cf0b8752805b4ac0e3cde352b0",
"hash": "a422c2e4eb5cfff2fa4784fd9036ed9c",
"packages": [
{
"name": "aferrandini/phpqrcode",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/aferrandini/PHPQRCode.git",
"reference": "3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aferrandini/PHPQRCode/zipball/3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46",
"reference": "3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"psr-0": {
"PHPQRCode": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ariel Ferrandini",
"email": "arielferrandini@gmail.com",
"homepage": "http://www.ferrandini.com/",
"role": "Developer"
}
],
"description": "PHPQRCode porting and changed for PHP 5.3 compatibility",
"homepage": "https://github.com/aferrandini/PHPQRCode",
"keywords": [
"barcode",
"php",
"qrcode"
],
"time": "2013-07-08 09:39:08"
},
{
"name": "alchemy/binary-driver",
"version": "1.5.0",
@ -65,16 +109,16 @@
},
{
"name": "doctrine/cache",
"version": "v1.3.1",
"version": "v1.4.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
"reference": "cf483685798a72c93bf4206e3dd6358ea07d64e7"
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/cf483685798a72c93bf4206e3dd6358ea07d64e7",
"reference": "cf483685798a72c93bf4206e3dd6358ea07d64e7",
"url": "https://api.github.com/repos/doctrine/cache/zipball/2346085d2b027b233ae1d5de59b07440b9f288c8",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8",
"shasum": ""
},
"require": {
@ -85,6 +129,7 @@
},
"require-dev": {
"phpunit/phpunit": ">=3.7",
"predis/predis": "~0.8",
"satooshi/php-coveralls": "~0.6"
},
"type": "library",
@ -130,7 +175,7 @@
"cache",
"caching"
],
"time": "2014-09-17 14:24:04"
"time": "2015-01-15 20:38:55"
},
{
"name": "emojione/emojione",
@ -210,6 +255,50 @@
],
"time": "2012-05-30 15:01:08"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.6.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "6f389f0f25b90d0b495308efcfa073981177f0fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/6f389f0f25b90d0b495308efcfa073981177f0fd",
"reference": "6f389f0f25b90d0b495308efcfa073981177f0fd",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"type": "library",
"autoload": {
"psr-0": {
"HTMLPurifier": "library/"
},
"files": [
"library/HTMLPurifier.composer.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"time": "2013-11-30 08:25:19"
},
{
"name": "michelf/php-markdown",
"version": "1.4.1",
@ -263,16 +352,16 @@
},
{
"name": "monolog/monolog",
"version": "1.11.0",
"version": "1.12.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa"
"reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/ec3961874c43840e96da3a8a1ed20d8c73d7e5aa",
"reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/1fbe8c2641f2b163addf49cc5e18f144bec6b19f",
"reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f",
"shasum": ""
},
"require": {
@ -286,7 +375,7 @@
"aws/aws-sdk-php": "~2.4, >2.4.8",
"doctrine/couchdb": "~1.0@dev",
"graylog2/gelf-php": "~1.0",
"phpunit/phpunit": "~3.7.0",
"phpunit/phpunit": "~4.0",
"raven/raven": "~0.5",
"ruflin/elastica": "0.90.*",
"videlalvaro/php-amqplib": "~2.4"
@ -305,7 +394,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.11.x-dev"
"dev-master": "1.12.x-dev"
}
},
"autoload": {
@ -331,7 +420,7 @@
"logging",
"psr-3"
],
"time": "2014-09-30 13:30:58"
"time": "2014-12-29 21:29:35"
},
{
"name": "neutron/temporary-filesystem",
@ -482,16 +571,16 @@
},
{
"name": "sabre/vobject",
"version": "3.3.4",
"version": "3.3.5",
"source": {
"type": "git",
"url": "https://github.com/fruux/sabre-vobject.git",
"reference": "e7cbc59a7a77325dfa32924865e1802c9216a3e0"
"reference": "77cb636a5bde4c19d7522c2c548b258859ddd1ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/e7cbc59a7a77325dfa32924865e1802c9216a3e0",
"reference": "e7cbc59a7a77325dfa32924865e1802c9216a3e0",
"url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/77cb636a5bde4c19d7522c2c548b258859ddd1ef",
"reference": "77cb636a5bde4c19d7522c2c548b258859ddd1ef",
"shasum": ""
},
"require": {
@ -544,21 +633,21 @@
"jCard",
"vCard"
],
"time": "2014-11-19 22:15:24"
"time": "2015-01-10 00:54:52"
},
{
"name": "symfony/console",
"version": "v2.6.1",
"version": "v2.6.4",
"target-dir": "Symfony/Component/Console",
"source": {
"type": "git",
"url": "https://github.com/symfony/Console.git",
"reference": "ef825fd9f809d275926547c9e57cbf14968793e8"
"reference": "e44154bfe3e41e8267d7a3794cd9da9a51cfac34"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Console/zipball/ef825fd9f809d275926547c9e57cbf14968793e8",
"reference": "ef825fd9f809d275926547c9e57cbf14968793e8",
"url": "https://api.github.com/repos/symfony/Console/zipball/e44154bfe3e41e8267d7a3794cd9da9a51cfac34",
"reference": "e44154bfe3e41e8267d7a3794cd9da9a51cfac34",
"shasum": ""
},
"require": {
@ -601,21 +690,21 @@
],
"description": "Symfony Console Component",
"homepage": "http://symfony.com",
"time": "2014-12-02 20:19:20"
"time": "2015-01-25 04:39:26"
},
{
"name": "symfony/filesystem",
"version": "v2.6.1",
"version": "v2.6.4",
"target-dir": "Symfony/Component/Filesystem",
"source": {
"type": "git",
"url": "https://github.com/symfony/Filesystem.git",
"reference": "ff6efc95256cb33031933729e68b01d720b5436b"
"reference": "a1f566d1f92e142fa1593f4555d6d89e3044a9b7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Filesystem/zipball/ff6efc95256cb33031933729e68b01d720b5436b",
"reference": "ff6efc95256cb33031933729e68b01d720b5436b",
"url": "https://api.github.com/repos/symfony/Filesystem/zipball/a1f566d1f92e142fa1593f4555d6d89e3044a9b7",
"reference": "a1f566d1f92e142fa1593f4555d6d89e3044a9b7",
"shasum": ""
},
"require": {
@ -648,21 +737,21 @@
],
"description": "Symfony Filesystem Component",
"homepage": "http://symfony.com",
"time": "2014-12-02 20:19:20"
"time": "2015-01-03 21:13:09"
},
{
"name": "symfony/process",
"version": "v2.6.1",
"version": "v2.6.4",
"target-dir": "Symfony/Component/Process",
"source": {
"type": "git",
"url": "https://github.com/symfony/Process.git",
"reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a"
"reference": "ecfc23e89d9967999fa5f60a1e9af7384396e9ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Process/zipball/bf0c9bd625f13b0b0bbe39919225cf145dfb935a",
"reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a",
"url": "https://api.github.com/repos/symfony/Process/zipball/ecfc23e89d9967999fa5f60a1e9af7384396e9ae",
"reference": "ecfc23e89d9967999fa5f60a1e9af7384396e9ae",
"shasum": ""
},
"require": {
@ -695,21 +784,21 @@
],
"description": "Symfony Process Component",
"homepage": "http://symfony.com",
"time": "2014-12-02 20:19:20"
"time": "2015-01-25 04:39:26"
},
{
"name": "symfony/yaml",
"version": "v2.6.1",
"version": "v2.6.4",
"target-dir": "Symfony/Component/Yaml",
"source": {
"type": "git",
"url": "https://github.com/symfony/Yaml.git",
"reference": "3346fc090a3eb6b53d408db2903b241af51dcb20"
"reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/3346fc090a3eb6b53d408db2903b241af51dcb20",
"reference": "3346fc090a3eb6b53d408db2903b241af51dcb20",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/60ed7751671113cf1ee7d7778e691642c2e9acd8",
"reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8",
"shasum": ""
},
"require": {
@ -742,7 +831,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "http://symfony.com",
"time": "2014-12-02 20:19:20"
"time": "2015-01-25 04:39:26"
},
{
"name": "toin0u/digitalocean",
@ -866,16 +955,16 @@
},
{
"name": "twig/twig",
"version": "v1.16.2",
"version": "v1.18.0",
"source": {
"type": "git",
"url": "https://github.com/fabpot/Twig.git",
"reference": "42f758d9fe2146d1f0470604fc05ee43580873fc"
"url": "https://github.com/twigphp/Twig.git",
"reference": "4cf7464348e7f9893a93f7096a90b73722be99cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fabpot/Twig/zipball/42f758d9fe2146d1f0470604fc05ee43580873fc",
"reference": "42f758d9fe2146d1f0470604fc05ee43580873fc",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/4cf7464348e7f9893a93f7096a90b73722be99cf",
"reference": "4cf7464348e7f9893a93f7096a90b73722be99cf",
"shasum": ""
},
"require": {
@ -884,7 +973,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.16-dev"
"dev-master": "1.18-dev"
}
},
"autoload": {
@ -910,7 +999,7 @@
},
{
"name": "Twig Team",
"homepage": "https://github.com/fabpot/Twig/graphs/contributors",
"homepage": "http://twig.sensiolabs.org/contributors",
"role": "Contributors"
}
],
@ -919,7 +1008,7 @@
"keywords": [
"templating"
],
"time": "2014-10-17 12:53:44"
"time": "2015-01-25 17:32:08"
},
{
"name": "zendframework/zend-config",
@ -1035,6 +1124,9 @@
"php-ffmpeg/php-ffmpeg": 20
},
"prefer-stable": false,
"platform": [],
"prefer-lowest": false,
"platform": {
"php": ">=5.3.3"
},
"platform-dev": []
}

@ -220,7 +220,6 @@ if (api_is_allowed_to_edit(false,true) OR
// tooledit : visibility = 2 : only visible for platform administrator
if ($ctok == $_GET['sec_token']) {
AnnouncementManager::delete_announcement($_course, $id);
//delete_added_resource("Ad_Valvas", $delete);
$id = null;
$emailTitle = null;
@ -263,7 +262,7 @@ if (api_is_allowed_to_edit(false,true) OR
$id = intval($_GET['id']);
if (!api_is_course_coach() || api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $id)) {
$sql="SELECT * FROM $tbl_announcement WHERE c_id = $course_id AND id = '$id'";
$sql = "SELECT * FROM $tbl_announcement WHERE c_id = $course_id AND id = '$id'";
$rs = Database::query($sql);
$myrow = Database::fetch_array($rs);
$last_id = $id;
@ -326,7 +325,6 @@ if (api_is_allowed_to_edit(false,true) OR
while (list ($announcementId, $announcementOrder) = Database::fetch_row($result)) {
// STEP 2 : FOUND THE NEXT ANNOUNCEMENT ID AND ORDER.
// COMMIT ORDER SWAP ON THE DB
if ($thisAnnouncementOrderFound) {
$nextAnnouncementId = $announcementId;
$nextAnnouncementOrder = $announcementOrder;
@ -471,7 +469,7 @@ if (api_is_allowed_to_edit(false,true)) {
} else {
// students only get to see the visible announcements
if (empty($_GET['origin']) or $_GET['origin'] !== 'learnpath') {
$group_memberships=GroupManager::get_group_ids($_course['real_id'], $_user['user_id']);
$group_memberships = GroupManager::get_group_ids($_course['real_id'], $_user['user_id']);
if ((api_get_course_setting('allow_user_edit_announcement') && !api_is_anonymous())) {
@ -494,19 +492,19 @@ if (api_is_allowed_to_edit(false,true)) {
// the user is member of several groups => display personal announcements AND his group announcements AND the general announcements
if (is_array($group_memberships) && count($group_memberships)>0) {
$sql="SELECT announcement.*, ip.visibility, ip.to_group_id, ip.insert_user_id
FROM $tbl_announcement announcement, $tbl_item_property ip
WHERE
announcement.c_id = $course_id AND
ip.c_id = $course_id AND
announcement.id = ip.ref AND
ip.tool='announcement'
AND ip.visibility='1'
$cond_user_id
$condition_session
GROUP BY ip.ref
ORDER BY display_order DESC
LIMIT 0,$maximum";
$sql = "SELECT announcement.*, ip.visibility, ip.to_group_id, ip.insert_user_id
FROM $tbl_announcement announcement, $tbl_item_property ip
WHERE
announcement.c_id = $course_id AND
ip.c_id = $course_id AND
announcement.id = ip.ref AND
ip.tool='announcement'
AND ip.visibility='1'
$cond_user_id
$condition_session
GROUP BY ip.ref
ORDER BY display_order DESC
LIMIT 0, $maximum";
} else {
// the user is not member of any group
// this is an identified user => show the general announcements AND his personal announcements
@ -520,16 +518,16 @@ if (api_is_allowed_to_edit(false,true)) {
$sql="SELECT announcement.*, ip.visibility, ip.to_group_id, ip.insert_user_id
FROM $tbl_announcement announcement, $tbl_item_property ip
WHERE
announcement.c_id = $course_id AND
ip.c_id = $course_id AND
announcement.id = ip.ref
AND ip.tool='announcement'
AND ip.visibility='1'
$cond_user_id
$condition_session
announcement.c_id = $course_id AND
ip.c_id = $course_id AND
announcement.id = ip.ref
AND ip.tool='announcement'
AND ip.visibility='1'
$cond_user_id
$condition_session
GROUP BY ip.ref
ORDER BY display_order DESC
LIMIT 0,$maximum";
LIMIT 0, $maximum";
} else {
if (api_get_course_setting('allow_user_edit_announcement')) {
@ -542,13 +540,13 @@ if (api_is_allowed_to_edit(false,true)) {
$sql="SELECT announcement.*, ip.visibility, ip.to_group_id, ip.insert_user_id
FROM $tbl_announcement announcement, $tbl_item_property ip
WHERE
announcement.c_id = $course_id AND
ip.c_id = $course_id AND
announcement.id = ip.ref
AND ip.tool='announcement'
AND ip.visibility='1'
AND ip.to_group_id='0'
$condition_session
announcement.c_id = $course_id AND
ip.c_id = $course_id AND
announcement.id = ip.ref
AND ip.tool='announcement'
AND ip.visibility='1'
AND ip.to_group_id='0'
$condition_session
GROUP BY ip.ref
ORDER BY display_order DESC
LIMIT 0,$maximum";
@ -619,7 +617,6 @@ if ($display_form) {
$title_to_modify = stripslashes($title_to_modify);
// DISPLAY ADD ANNOUNCEMENT COMMAND
//echo '<form method="post" name="f1" enctype = "multipart/form-data" action="'.api_get_self().'?publish_survey='.Security::remove_XSS($surveyid).'&id='.Security::remove_XSS($_GET['id']).'&db_name='.$db_name.'&cidReq='.Security::remove_XSS($_GET['cidReq']).'" style="margin:0px;">';
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
echo '<form class="form-horizontal" method="post" name="f1" enctype = "multipart/form-data" action="'.api_get_self().'?id='.$id.'&'.api_get_cidreq().'" style="margin:0px;">';
if (empty($_GET['id'])) {
@ -668,8 +665,6 @@ if ($display_form) {
$title_to_modify = sprintf(get_lang('RemindInactiveLearnersMailSubject'), api_get_setting('siteName'));
$content_to_modify = get_lang('YourAccountIsActiveYouCanLoginAndCheckYourCourses');
}
} else {
//echo '<span id="recipient_overview">' . get_lang('Everybody') . '</span>';
}
AnnouncementManager::show_to_form($to);
echo ' </div>

@ -6,7 +6,7 @@
* @license see /license.txt
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva
*/
require_once dirname(__FILE__) . '/../inc/autoload.inc.php';
require_once dirname(__FILE__) . '/../../vendor/autoload.php';
$controller = CourseNoticeController::instance();
KeyAuth::enable_services($controller);

@ -109,7 +109,10 @@ class ImportCsv
$isStatic = strpos($method, 'Static');
if (method_exists($this, $method)) {
if ($method == 'importUnsubscribeStatic' || empty($isStatic)) {
if (($method == 'importUnsubscribeStatic' ||
$method == 'importSubscribeStatic') ||
empty($isStatic)
) {
$fileToProcess[$parts[1]][] = array(
'method' => $method,
'file' => $path.$fileInfo['basename']
@ -144,8 +147,10 @@ class ImportCsv
'teachers',
'courses',
'sessions',
'subscribe-static',
'unsubscribe-static'
);
foreach ($sections as $section) {
$this->logger->addInfo("-- Import $section --");
@ -169,6 +174,7 @@ class ImportCsv
'sessions-static',
'calendar-static',
);
foreach ($sections as $section) {
$this->logger->addInfo("-- Import static files $section --");
@ -1010,7 +1016,6 @@ class ImportCsv
// 2014-06-30
$dateStart = explode('/', $session['DateStart']);
$dateEnd = explode('/', $session['DateEnd']);
//$visibility = $session['visibility'];
$visibility = $this->defaultSessionVisibility;
$coachId = null;
@ -1028,12 +1033,13 @@ class ImportCsv
$dateEnd[0],
$dateEnd[1],
$dateEnd[2],
null, //$session['nb_days_access_before_beginning'],
null, //$session['nb_days_access_after_end'],
$this->daysCoachAccessBeforeBeginning,
$this->daysCoachAccessAfterBeginning,
null,
$coachUserName,
$categoryId,
$visibility
$visibility,
1
);
if (is_numeric($result)) {
@ -1045,6 +1051,28 @@ class ImportCsv
);
}
} else {
$sessionInfo = api_get_session_info($sessionId);
$accessBefore = null;
$accessAfter = null;
if (empty($sessionInfo['nb_days_access_before_beginning']) ||
(!empty($sessionInfo['nb_days_access_before_beginning']) &&
$sessionInfo['nb_days_access_before_beginning'] < $this->daysCoachAccessBeforeBeginning)
) {
$accessBefore = intval($this->daysCoachAccessBeforeBeginning);
}
$accessAfter = null;
if (empty($sessionInfo['nb_days_access_after_end']) ||
(!empty($sessionInfo['nb_days_access_after_end']) &&
$sessionInfo['nb_days_access_after_end'] < $this->daysCoachAccessAfterBeginning)
) {
$accessAfter = intval($this->daysCoachAccessAfterBeginning);
}
$showDescription = isset($sessionInfo['show_description']) ? $sessionInfo['show_description'] : 1;
$result = SessionManager::edit_session(
$sessionId,
$session['SessionName'],
@ -1054,12 +1082,16 @@ class ImportCsv
$dateEnd[0],
$dateEnd[1],
$dateEnd[2],
null,//$session['nb_days_access_before_beginning'],
null,//$session['nb_days_access_after_end'],
$accessBefore,
$accessAfter,
null,
$coachId,
$categoryId,
$visibility
$visibility,
true, //$start_limit =
true, //$end_limit =
null, //$description
$showDescription // $showDescription = null,
);
if (is_numeric($result)) {
@ -1183,7 +1215,10 @@ class ImportCsv
$avoid,
false, // deleteUsersNotInList
false, // updateCourseCoaches
true // sessionWithCoursesModifier
true, // sessionWithCoursesModifier
true, //$addOriginalCourseTeachersAsCourseSessionCoaches
true, //$removeAllTeachersFromCourse
1 // $showDescription
);
if (!empty($result['error_message'])) {
@ -1196,6 +1231,67 @@ class ImportCsv
}
}
/**
* @param string $file
*/
private function importSubscribeStatic($file)
{
$data = Import::csv_reader($file);
if (!empty($data)) {
$this->logger->addInfo(count($data) . " records found.");
foreach ($data as $row) {
$chamiloUserName = $row['UserName'];
$chamiloCourseCode = $row['CourseCode'];
$chamiloSessionId = $row['SessionID'];
$type = $row['Type'];
$sessionInfo = api_get_session_info($chamiloSessionId);
if (empty($sessionInfo)) {
$this->logger->addError('Session does not exists: '.$chamiloSessionId);
continue;
}
$courseInfo = api_get_course_info($chamiloCourseCode);
if (empty($courseInfo)) {
$this->logger->addError('Course does not exists: '.$courseInfo);
continue;
}
$userId = Usermanager::get_user_id_from_username($chamiloUserName);
if (empty($userId)) {
$this->logger->addError('User does not exists: '.$chamiloUserName);
continue;
}
$status = null;
switch ($type) {
case 'student':
SessionManager::subscribe_users_to_session_course(
array($userId),
$chamiloSessionId,
$courseInfo['code'],
null,
false
);
break;
case 'teacher':
SessionManager::set_coach_to_course_session(
$userId,
$chamiloSessionId,
$courseInfo['code']
);
break;
}
$this->logger->addError(
"User '$chamiloUserName' with status $type was added to session: #$chamiloSessionId - Course: " . $courseInfo['code']
);
}
}
}
/**
* @param string $file
*/
@ -1231,7 +1327,9 @@ class ImportCsv
}
CourseManager::unsubscribe_user($userId, $courseInfo['code'], $chamiloSessionId);
$this->logger->addError("User '$chamiloUserName' was removed from session: #$chamiloSessionId, Course: ".$courseInfo['code']);
$this->logger->addError(
"User '$chamiloUserName' was removed from session: #$chamiloSessionId, Course: ".$courseInfo['code']
);
}
}
}

@ -19,9 +19,6 @@ if (php_sapi_name()!='cli') {
die();
}
// include nusoap library
require_once(api_get_path(LIBRARY_PATH).'nusoap/nusoap.php');
// create client
$client = new nusoap_client(api_get_path(WEB_CODE_PATH).'cron/user_import/service.php');

@ -28,7 +28,7 @@ if (api_get_setting('enabled_text2audio') == 'false'){
api_not_allowed(true);
}
$document_data = DocumentManager::get_document_data_by_id($_GET['id'], api_get_course_id());
$document_data = DocumentManager::get_document_data_by_id($_REQUEST['id'], api_get_course_id());
if (empty($document_data)) {
if (api_is_in_group()) {
$group_properties = GroupManager::get_group_properties(api_get_group_id());
@ -212,7 +212,7 @@ $(document).ready(function(){
echo '<div>';
$form = new FormValidator('form1', 'post', null, '', array('id' => 'form1'));
$form->addElement('hidden', 'text2voice_mode', 'google');
$form->addElement('hidden', 'document_id', $document_id);
$form->addElement('hidden', 'id', $document_id);
$form->addElement('text', 'title', get_lang('Title'));
$form->addElement('select', 'lang', get_lang('Language'), $options);
$form->addElement('textarea', 'text', get_lang('InsertText2Audio'), array('id' => 'textarea_google', 'class' =>'span6' ));
@ -235,7 +235,7 @@ $(document).ready(function(){
$form = new FormValidator('form2', 'post', null, '', array('id' => 'form2'));
$form->addElement('hidden', 'text2voice_mode','pediaphon');
$form->addElement('hidden', 'document_id', $document_id);
$form->addElement('hidden', 'id', $document_id);
$form->addElement('text', 'title', get_lang('Title'));
$form->addElement('select', 'lang', get_lang('Language'), $options_pedia, array('onclick' => 'update_voices(this.selectedIndex);'));
$form->addElement('select', 'voices', get_lang('Voice'), array(get_lang('FirstSelectALanguage')), array());
@ -345,7 +345,7 @@ Display :: display_footer();
*/
function downloadMP3_google($filepath, $dir)
{
$location='create_audio.php?'.api_get_cidreq().'&id='.Security::remove_XSS($_POST['document_id']).'&dt2a=google';
$location='create_audio.php?'.api_get_cidreq().'&id='.intval($_POST['id']).'&dt2a=google';
//security
if (!isset($_POST['lang']) && !isset($_POST['text']) && !isset($_POST['title']) && !isset($filepath) && !isset($dir)) {
@ -420,7 +420,7 @@ function downloadMP3_google($filepath, $dir)
* @version january 2011, chamilo 1.8.8
*/
function downloadMP3_pediaphon($filepath, $dir){
$location='create_audio.php?'.api_get_cidreq().'&id='.Security::remove_XSS($_POST['document_id']).'&dt2a=pediaphon';
$location='create_audio.php?'.api_get_cidreq().'&id='.intval($_POST['id']).'&dt2a=pediaphon';
//security
if(!isset($_POST['lang']) && !isset($_POST['text']) && !isset($_POST['title']) && !isset($filepath) && !isset($dir)) {
echo '<script>window.location.href="'.$location.'"</script>';

@ -11,25 +11,25 @@ Use Model\Document;
Use Model\Course;
/**
* Return either
*
* Return either
*
* - one document
* - several documents (file and/or folders) zipped together
*
*
* Used to transfer files to another application through http.
*
*
* Script parameters:
*
* - id id(s) of the document id=1 or id=1,2,4
*
* - id id(s) of the document id=1 or id=1,2,4
* - cidReq course code
*
*
* Note this script enables key authentication so access with a key token is possible.
*
*
* @package chamilo.document
* @license see /license.txt
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva
*/
require_once __DIR__ . '/../inc/autoload.inc.php';
require_once __DIR__ . '/../../vendor/autoload.php';
KeyAuth::enable();
require_once __DIR__ . '/../inc/global.inc.php';
@ -48,14 +48,14 @@ $course = Course::current();
/**
* No files requested. We make sure we return 404 error to tell the client
* that the call failed.
* that the call failed.
*/
if (count($ids) == 0 || empty($course)) {
Response::not_found();
}
/**
* One file requested. In this case we return the file itself.
* One file requested. In this case we return the file itself.
*/
if (count($ids) == 1) {
$id = reset($ids);
@ -77,7 +77,7 @@ if (count($ids) == 1) {
}
/**
* Several files requested. In this case we zip them together.
* Several files requested. In this case we zip them together.
*/
$files = array();
$folders = array();
@ -97,9 +97,9 @@ foreach ($ids as $id) {
$requested_folders = $folders;
/**
* Note that if a parent folder is hidden children should not be accesible
* even if they are visible. It is therefore not sufficient to check document
* visibility.
* Note that if a parent folder is hidden children should not be accesible
* even if they are visible. It is therefore not sufficient to check document
* visibility.
*/
while ($folders) {
$items = $folders;
@ -123,7 +123,7 @@ while ($folders) {
$folders = $requested_folders;
/**
* Requested files may not be accessible.
* Requested files may not be accessible.
*/
if (count($files) == 0) {
Response::not_found();
@ -142,7 +142,7 @@ foreach ($items as $item) {
}
/**
* Zip files together.
* Zip files together.
*/
$temp_zip_path = Chamilo::temp_file('zip');
$zip_folder = new PclZip($temp_zip_path);
@ -155,7 +155,7 @@ foreach ($files as $file) {
}
/**
* Send file for download
* Send file for download
*/
event_download(Uri::here());
DocumentManager::file_send_for_download($temp_zip_path, false, get_lang('Documents') . '.zip');

@ -289,11 +289,11 @@ function aiken_parse_file(&$exercise_info, $exercisePath, $file, $questionFile)
$new_question = true;
} else {
if (empty($exercise_info['question'][$question_index]['title'])) {
if (strlen($info) < 40) {
if (strlen($info) < 100) {
$exercise_info['question'][$question_index]['title'] = $info;
} else {
//Question itself (use a 40-chars long title and a larger description)
$exercise_info['question'][$question_index]['title'] = trim(substr($info,0,40)).'...';
//Question itself (use a 100-chars long title and a larger description)
$exercise_info['question'][$question_index]['title'] = trim(substr($info, 0, 100)) . '...';
$exercise_info['question'][$question_index]['description'] = $info;
}
} else {

@ -158,27 +158,32 @@ class StudentPublicationLink extends AbstractLink
public function calc_score($stud_id = null)
{
$stud_id = intval($stud_id);
$tbl_stats = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
$sql = 'SELECT * FROM '.$tbl_stats."
$table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
$sql = 'SELECT * FROM '.$table."
WHERE
c_id = {$this->course_id} AND
id = '".intval($this->get_ref_id())."' AND
session_id = ".api_get_session_id()."";
session_id = ".api_get_session_id()."
"
;
$query = Database::query($sql);
$assignment = Database::fetch_array($query);
if (count($assignment)==0) {
$v_assigment_id ='0';
if (count($assignment) == 0) {
$parentId = '0';
} else {
$v_assigment_id = $assignment['id'];
$parentId = $assignment['id'];
}
$sql = 'SELECT * FROM '.$tbl_stats.'
$sql = 'SELECT * FROM '.$table.'
WHERE
c_id = '.$this->course_id.' AND
active = 1 AND
parent_id ="'.$v_assigment_id.'" AND
session_id='.api_get_session_id().'';
parent_id = "'.$parentId.'" AND
session_id = '.api_get_session_id() .' AND
qualificator_id <> 0
';
if (!empty($stud_id)) {
$sql .= " AND user_id = $stud_id ";
}

@ -37,8 +37,6 @@ switch ($action) {
} else {
// save contact information with web service
require_once '../lib/nusoap/nusoap.php';
// create a client
$client = new nusoap_client('http://version.chamilo.org/contact.php?wsdl', true);

@ -1,18 +0,0 @@
<?php
/**
* Set up the Chamilo autoload stack. Can be called several time if needed also
* better to avoid it.
*/
require_once dirname(__FILE__) . '/lib/autoload.class.php';
Autoload::register();
/**
use Symfony\Component\ClassLoader\UniversalClassLoader;
$loader = new UniversalClassLoader();
$loader->registerNamespaces(array(
'Symfony\\Component\\HttpFoundation', __DIR__.'/vendor/symfony/http-foundation',
));
$loader->register();
*/

@ -84,7 +84,7 @@ if (api_get_setting('login_is_email') == 'true') {
define('USERNAME_MAX_LENGTH', $default_username_length);
// Do not over-use this variable. It is only for this script's local use.
$lib_path = api_get_path(LIBRARY_PATH);
$lib_path = dirname(__FILE__).'/../../main/inc/lib/';
// Fix bug in IIS that doesn't fill the $_SERVER['REQUEST_URI'].
api_request_uri();
@ -96,7 +96,7 @@ ini_set('include_path', api_create_include_path_setting());
ini_set('auto_detect_line_endings', '1');
// Include the libraries that are necessary everywhere
require_once dirname(__FILE__).'/autoload.inc.php';
require_once dirname(__FILE__).'/../../vendor/autoload.php';
require_once $lib_path.'database.lib.php';
require_once $lib_path.'text.lib.php';

@ -2,7 +2,7 @@
/**
* Autoload Chamilo classes
*
* @deprecated
* @license see /license.txt
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva
*/

@ -261,9 +261,8 @@ class Certificate extends Model
{
//Make sure HTML certificate is generated
if (!empty($text) && !empty($path)) {
require_once api_get_path(LIBRARY_PATH).'phpqrcode/qrlib.php';
//L low, M - Medium, L large error correction
return QRcode::png($text, $path, 'M', 2, 2);
return PHPQRCode\QRcode::png($text, $path, 'M', 2, 2);
}
return false;
}

File diff suppressed because it is too large Load Diff

@ -921,10 +921,8 @@ $allowed_tags_teacher['body']['link'] = array();
$allowed_tags_teacher['body']['text'] = array();
$allowed_tags_teacher['body']['vlink'] = array();
$allowed_tags_teacher_full_page = $allowed_tags_student_full_page;
// ALLOWED HTML FOR ANONYMOUS USERS
$allowed_tags_anonymous = $allowed_tags_student;

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,21 +0,0 @@
<?php
class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number
{
public function __construct() {
parent::__construct(false); // opacity is non-negative, but we will clamp it
}
public function validate($number, $config, $context) {
$result = parent::validate($number, $config, $context);
if ($result === false) return $result;
$float = (float) $result;
if ($float < 0.0) $result = '0';
if ($float > 1.0) $result = '1';
return $result;
}
}
// vim: et sw=4 sts=4

@ -1,28 +0,0 @@
<?php
/**
* Decorator which enables CSS properties to be disabled for specific elements.
*/
class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
{
public $def, $element;
/**
* @param $def Definition to wrap
* @param $element Element to deny
*/
public function __construct($def, $element) {
$this->def = $def;
$this->element = $element;
}
/**
* Checks if CurrentToken is set and equal to $this->element
*/
public function validate($string, $config, $context) {
$token = $context->get('CurrentToken', true);
if ($token && $token->name == $this->element) return false;
return $this->def->validate($string, $config, $context);
}
}
// vim: et sw=4 sts=4

@ -1,72 +0,0 @@
<?php
/**
* Validates a font family list according to CSS spec
* @todo whitelisting allowed fonts would be nice
*/
class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
{
public function validate($string, $config, $context) {
static $generic_names = array(
'serif' => true,
'sans-serif' => true,
'monospace' => true,
'fantasy' => true,
'cursive' => true
);
// assume that no font names contain commas in them
$fonts = explode(',', $string);
$final = '';
foreach($fonts as $font) {
$font = trim($font);
if ($font === '') continue;
// match a generic name
if (isset($generic_names[$font])) {
$final .= $font . ', ';
continue;
}
// match a quoted name
if ($font[0] === '"' || $font[0] === "'") {
$length = strlen($font);
if ($length <= 2) continue;
$quote = $font[0];
if ($font[$length - 1] !== $quote) continue;
$font = substr($font, 1, $length - 2);
}
$font = $this->expandCSSEscape($font);
// $font is a pure representation of the font name
if (ctype_alnum($font) && $font !== '') {
// very simple font, allow it in unharmed
$final .= $font . ', ';
continue;
}
// bugger out on whitespace. form feed (0C) really
// shouldn't show up regardless
$font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
// These ugly transforms don't pose a security
// risk (as \\ and \" might). We could try to be clever and
// use single-quote wrapping when there is a double quote
// present, but I have choosen not to implement that.
// (warning: this code relies on the selection of quotation
// mark below)
$font = str_replace('\\', '\\5C ', $font);
$font = str_replace('"', '\\22 ', $font);
// complicated font, requires quoting
$final .= "\"$font\", "; // note that this will later get turned into &quot;
}
$final = rtrim($final, ', ');
if ($final === '') return false;
return $final;
}
}
// vim: et sw=4 sts=4

@ -1,47 +0,0 @@
<?php
/**
* Represents a Length as defined by CSS.
*/
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
{
protected $min, $max;
/**
* @param HTMLPurifier_Length $max Minimum length, or null for no bound. String is also acceptable.
* @param HTMLPurifier_Length $max Maximum length, or null for no bound. String is also acceptable.
*/
public function __construct($min = null, $max = null) {
$this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
$this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
}
public function validate($string, $config, $context) {
$string = $this->parseCDATA($string);
// Optimizations
if ($string === '') return false;
if ($string === '0') return '0';
if (strlen($string) === 1) return false;
$length = HTMLPurifier_Length::make($string);
if (!$length->isValid()) return false;
if ($this->min) {
$c = $length->compareTo($this->min);
if ($c === false) return false;
if ($c < 0) return false;
}
if ($this->max) {
$c = $length->compareTo($this->max);
if ($c === false) return false;
if ($c > 0) return false;
}
return $length->toString();
}
}
// vim: et sw=4 sts=4

@ -1,78 +0,0 @@
<?php
/**
* Validates shorthand CSS property list-style.
* @warning Does not support url tokens that have internal spaces.
*/
class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
{
/**
* Local copy of component validators.
* @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
*/
protected $info;
public function __construct($config) {
$def = $config->getCSSDefinition();
$this->info['list-style-type'] = $def->info['list-style-type'];
$this->info['list-style-position'] = $def->info['list-style-position'];
$this->info['list-style-image'] = $def->info['list-style-image'];
}
public function validate($string, $config, $context) {
// regular pre-processing
$string = $this->parseCDATA($string);
if ($string === '') return false;
// assumes URI doesn't have spaces in it
$bits = explode(' ', strtolower($string)); // bits to process
$caught = array();
$caught['type'] = false;
$caught['position'] = false;
$caught['image'] = false;
$i = 0; // number of catches
$none = false;
foreach ($bits as $bit) {
if ($i >= 3) return; // optimization bit
if ($bit === '') continue;
foreach ($caught as $key => $status) {
if ($status !== false) continue;
$r = $this->info['list-style-' . $key]->validate($bit, $config, $context);
if ($r === false) continue;
if ($r === 'none') {
if ($none) continue;
else $none = true;
if ($key == 'image') continue;
}
$caught[$key] = $r;
$i++;
break;
}
}
if (!$i) return false;
$ret = array();
// construct type
if ($caught['type']) $ret[] = $caught['type'];
// construct image
if ($caught['image']) $ret[] = $caught['image'];
// construct position
if ($caught['position']) $ret[] = $caught['position'];
if (empty($ret)) return false;
return implode(' ', $ret);
}
}
// vim: et sw=4 sts=4

@ -1,40 +0,0 @@
<?php
/**
* Validates a Percentage as defined by the CSS spec.
*/
class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
{
/**
* Instance of HTMLPurifier_AttrDef_CSS_Number to defer number validation
*/
protected $number_def;
/**
* @param Bool indicating whether to forbid negative values
*/
public function __construct($non_negative = false) {
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
}
public function validate($string, $config, $context) {
$string = $this->parseCDATA($string);
if ($string === '') return false;
$length = strlen($string);
if ($length === 1) return false;
if ($string[$length - 1] !== '%') return false;
$number = substr($string, 0, $length - 1);
$number = $this->number_def->validate($number, $config, $context);
if ($number === false) return false;
return "$number%";
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,28 +0,0 @@
<?php
/**
* Validates a boolean attribute
*/
class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
{
protected $name;
public $minimized = true;
public function __construct($name = false) {$this->name = $name;}
public function validate($string, $config, $context) {
if (empty($string)) return false;
return $this->name;
}
/**
* @param $string Name of attribute
*/
public function make($string) {
return new HTMLPurifier_AttrDef_HTML_Bool($string);
}
}
// vim: et sw=4 sts=4

@ -1,32 +0,0 @@
<?php
/**
* Validates a color according to the HTML spec.
*/
class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
{
public function validate($string, $config, $context) {
static $colors = null;
if ($colors === null) $colors = $config->get('Core.ColorKeywords');
$string = trim($string);
if (empty($string)) return false;
if (isset($colors[$string])) return $colors[$string];
if ($string[0] === '#') $hex = substr($string, 1);
else $hex = $string;
$length = strlen($hex);
if ($length !== 3 && $length !== 6) return false;
if (!ctype_xdigit($hex)) return false;
if ($length === 3) $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
return "#$hex";
}
}
// vim: et sw=4 sts=4

@ -1,21 +0,0 @@
<?php
/**
* Special-case enum attribute definition that lazy loads allowed frame targets
*/
class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
{
public $valid_values = false; // uninitialized value
protected $case_sensitive = false;
public function __construct() {}
public function validate($string, $config, $context) {
if ($this->valid_values === false) $this->valid_values = $config->get('Attr.AllowedFrameTargets');
return parent::validate($string, $config, $context);
}
}
// vim: et sw=4 sts=4

@ -1,70 +0,0 @@
<?php
/**
* Validates the HTML attribute ID.
* @warning Even though this is the id processor, it
* will ignore the directive Attr:IDBlacklist, since it will only
* go according to the ID accumulator. Since the accumulator is
* automatically generated, it will have already absorbed the
* blacklist. If you're hacking around, make sure you use load()!
*/
class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
{
// ref functionality disabled, since we also have to verify
// whether or not the ID it refers to exists
public function validate($id, $config, $context) {
if (!$config->get('Attr.EnableID')) return false;
$id = trim($id); // trim it first
if ($id === '') return false;
$prefix = $config->get('Attr.IDPrefix');
if ($prefix !== '') {
$prefix .= $config->get('Attr.IDPrefixLocal');
// prevent re-appending the prefix
if (strpos($id, $prefix) !== 0) $id = $prefix . $id;
} elseif ($config->get('Attr.IDPrefixLocal') !== '') {
trigger_error('%Attr.IDPrefixLocal cannot be used unless '.
'%Attr.IDPrefix is set', E_USER_WARNING);
}
//if (!$this->ref) {
$id_accumulator =& $context->get('IDAccumulator');
if (isset($id_accumulator->ids[$id])) return false;
//}
// we purposely avoid using regex, hopefully this is faster
if (ctype_alpha($id)) {
$result = true;
} else {
if (!ctype_alpha(@$id[0])) return false;
$trim = trim( // primitive style of regexps, I suppose
$id,
'A..Za..z0..9:-._'
);
$result = ($trim === '');
}
$regexp = $config->get('Attr.IDBlacklistRegexp');
if ($regexp && preg_match($regexp, $id)) {
return false;
}
if (/*!$this->ref && */$result) $id_accumulator->add($id);
// if no change was made to the ID, return the result
// else, return the new id if stripping whitespace made it
// valid, or return false.
return $result ? $id : false;
}
}
// vim: et sw=4 sts=4

@ -1,41 +0,0 @@
<?php
/**
* Validates the HTML type length (not to be confused with CSS's length).
*
* This accepts integer pixels or percentages as lengths for certain
* HTML attributes.
*/
class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels
{
public function validate($string, $config, $context) {
$string = trim($string);
if ($string === '') return false;
$parent_result = parent::validate($string, $config, $context);
if ($parent_result !== false) return $parent_result;
$length = strlen($string);
$last_char = $string[$length - 1];
if ($last_char !== '%') return false;
$points = substr($string, 0, $length - 1);
if (!is_numeric($points)) return false;
$points = (int) $points;
if ($points < 0) return '0%';
if ($points > 100) return '100%';
return ((string) $points) . '%';
}
}
// vim: et sw=4 sts=4

@ -1,41 +0,0 @@
<?php
/**
* Validates a MultiLength as defined by the HTML spec.
*
* A multilength is either a integer (pixel count), a percentage, or
* a relative number.
*/
class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length
{
public function validate($string, $config, $context) {
$string = trim($string);
if ($string === '') return false;
$parent_result = parent::validate($string, $config, $context);
if ($parent_result !== false) return $parent_result;
$length = strlen($string);
$last_char = $string[$length - 1];
if ($last_char !== '*') return false;
$int = substr($string, 0, $length - 1);
if ($int == '') return '*';
if (!is_numeric($int)) return false;
$int = (int) $int;
if ($int < 0) return false;
if ($int == 0) return '0';
if ($int == 1) return '*';
return ((string) $int) . '*';
}
}
// vim: et sw=4 sts=4

@ -1,48 +0,0 @@
<?php
/**
* Validates an integer representation of pixels according to the HTML spec.
*/
class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
{
protected $max;
public function __construct($max = null) {
$this->max = $max;
}
public function validate($string, $config, $context) {
$string = trim($string);
if ($string === '0') return $string;
if ($string === '') return false;
$length = strlen($string);
if (substr($string, $length - 2) == 'px') {
$string = substr($string, 0, $length - 2);
}
if (!is_numeric($string)) return false;
$int = (int) $string;
if ($int < 0) return '0';
// upper-bound value, extremely high values can
// crash operating systems, see <http://ha.ckers.org/imagecrash.html>
// WARNING, above link WILL crash you if you're using Windows
if ($this->max !== null && $int > $this->max) return (string) $this->max;
return (string) $int;
}
public function make($string) {
if ($string === '') $max = null;
else $max = (int) $string;
$class = get_class($this);
return new $class($max);
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,15 +0,0 @@
<?php
/**
* Validates arbitrary text according to the HTML spec.
*/
class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef
{
public function validate($string, $config, $context) {
return $this->parseCDATA($string);
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,68 +0,0 @@
<?php
/**
* Validates a host according to the IPv4, IPv6 and DNS (future) specifications.
*/
class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
{
/**
* Instance of HTMLPurifier_AttrDef_URI_IPv4 sub-validator
*/
protected $ipv4;
/**
* Instance of HTMLPurifier_AttrDef_URI_IPv6 sub-validator
*/
protected $ipv6;
public function __construct() {
$this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
$this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
}
public function validate($string, $config, $context) {
$length = strlen($string);
// empty hostname is OK; it's usually semantically equivalent:
// the default host as defined by a URI scheme is used:
//
// If the URI scheme defines a default for host, then that
// default applies when the host subcomponent is undefined
// or when the registered name is empty (zero length).
if ($string === '') return '';
if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') {
//IPv6
$ip = substr($string, 1, $length - 2);
$valid = $this->ipv6->validate($ip, $config, $context);
if ($valid === false) return false;
return '['. $valid . ']';
}
// need to do checks on unusual encodings too
$ipv4 = $this->ipv4->validate($string, $config, $context);
if ($ipv4 !== false) return $ipv4;
// A regular domain name.
// This breaks I18N domain names, but we don't have proper IRI support,
// so force users to insert Punycode. If there's complaining we'll
// try to fix things into an international friendly form.
// The productions describing this are:
$a = '[a-z]'; // alpha
$an = '[a-z0-9]'; // alphanum
$and = '[a-z0-9-]'; // alphanum | "-"
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
$domainlabel = "$an($and*$an)?";
// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
$toplabel = "$a($and*$an)?";
// hostname = *( domainlabel "." ) toplabel [ "." ]
$match = preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string);
if (!$match) return false;
return $string;
}
}
// vim: et sw=4 sts=4

@ -1,99 +0,0 @@
<?php
/**
* Validates an IPv6 address.
* @author Feyd @ forums.devnetwork.net (public domain)
* @note This function requires brackets to have been removed from address
* in URI.
*/
class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4
{
public function validate($aIP, $config, $context) {
if (!$this->ip4) $this->_loadRegex();
$original = $aIP;
$hex = '[0-9a-fA-F]';
$blk = '(?:' . $hex . '{1,4})';
$pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128
// prefix check
if (strpos($aIP, '/') !== false)
{
if (preg_match('#' . $pre . '$#s', $aIP, $find))
{
$aIP = substr($aIP, 0, 0-strlen($find[0]));
unset($find);
}
else
{
return false;
}
}
// IPv4-compatiblity check
if (preg_match('#(?<=:'.')' . $this->ip4 . '$#s', $aIP, $find))
{
$aIP = substr($aIP, 0, 0-strlen($find[0]));
$ip = explode('.', $find[0]);
$ip = array_map('dechex', $ip);
$aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
unset($find, $ip);
}
// compression check
$aIP = explode('::', $aIP);
$c = count($aIP);
if ($c > 2)
{
return false;
}
elseif ($c == 2)
{
list($first, $second) = $aIP;
$first = explode(':', $first);
$second = explode(':', $second);
if (count($first) + count($second) > 8)
{
return false;
}
while(count($first) < 8)
{
array_push($first, '0');
}
array_splice($first, 8 - count($second), 8, $second);
$aIP = $first;
unset($first,$second);
}
else
{
$aIP = explode(':', $aIP[0]);
}
$c = count($aIP);
if ($c != 8)
{
return false;
}
// All the pieces should be 16-bit hex strings. Are they?
foreach ($aIP as $piece)
{
if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece)))
{
return false;
}
}
return $original;
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,36 +0,0 @@
<?php
/**
* Pre-transform that changes converts a boolean attribute to fixed CSS
*/
class HTMLPurifier_AttrTransform_BoolToCSS extends HTMLPurifier_AttrTransform {
/**
* Name of boolean attribute that is trigger
*/
protected $attr;
/**
* CSS declarations to add to style, needs trailing semicolon
*/
protected $css;
/**
* @param $attr string attribute name to convert from
* @param $css string CSS declarations to add to style (needs semicolon)
*/
public function __construct($attr, $css) {
$this->attr = $attr;
$this->css = $css;
}
public function transform($attr, $config, $context) {
if (!isset($attr[$this->attr])) return $attr;
unset($attr[$this->attr]);
$this->prependCSS($attr, $this->css);
return $attr;
}
}
// vim: et sw=4 sts=4

@ -1,58 +0,0 @@
<?php
/**
* Generic pre-transform that converts an attribute with a fixed number of
* values (enumerated) to CSS.
*/
class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform {
/**
* Name of attribute to transform from
*/
protected $attr;
/**
* Lookup array of attribute values to CSS
*/
protected $enumToCSS = array();
/**
* Case sensitivity of the matching
* @warning Currently can only be guaranteed to work with ASCII
* values.
*/
protected $caseSensitive = false;
/**
* @param $attr String attribute name to transform from
* @param $enumToCSS Lookup array of attribute values to CSS
* @param $case_sensitive Boolean case sensitivity indicator, default false
*/
public function __construct($attr, $enum_to_css, $case_sensitive = false) {
$this->attr = $attr;
$this->enumToCSS = $enum_to_css;
$this->caseSensitive = (bool) $case_sensitive;
}
public function transform($attr, $config, $context) {
if (!isset($attr[$this->attr])) return $attr;
$value = trim($attr[$this->attr]);
unset($attr[$this->attr]);
if (!$this->caseSensitive) $value = strtolower($value);
if (!isset($this->enumToCSS[$value])) {
return $attr;
}
$this->prependCSS($attr, $this->enumToCSS[$value]);
return $attr;
}
}
// vim: et sw=4 sts=4

@ -1,27 +0,0 @@
<?php
/**
* Class for handling width/height length attribute transformations to CSS
*/
class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform
{
protected $name;
protected $cssName;
public function __construct($name, $css_name = null) {
$this->name = $name;
$this->cssName = $css_name ? $css_name : $name;
}
public function transform($attr, $config, $context) {
if (!isset($attr[$this->name])) return $attr;
$length = $this->confiscateAttr($attr, $this->name);
if(ctype_digit($length)) $length .= 'px';
$this->prependCSS($attr, $this->cssName . ":$length;");
return $attr;
}
}
// vim: et sw=4 sts=4

@ -1,21 +0,0 @@
<?php
/**
* Pre-transform that changes deprecated name attribute to ID if necessary
*/
class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform
{
public function transform($attr, $config, $context) {
// Abort early if we're using relaxed definition of name
if ($config->get('HTML.Attr.Name.UseCDATA')) return $attr;
if (!isset($attr['name'])) return $attr;
$id = $this->confiscateAttr($attr, 'name');
if ( isset($attr['id'])) return $attr;
$attr['id'] = $id;
return $attr;
}
}
// vim: et sw=4 sts=4

@ -1,27 +0,0 @@
<?php
/**
* Post-transform that performs validation to the name attribute; if
* it is present with an equivalent id attribute, it is passed through;
* otherwise validation is performed.
*/
class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform
{
public function __construct() {
$this->idDef = new HTMLPurifier_AttrDef_HTML_ID();
}
public function transform($attr, $config, $context) {
if (!isset($attr['name'])) return $attr;
$name = $attr['name'];
if (isset($attr['id']) && $attr['id'] === $name) return $attr;
$result = $this->idDef->validate($name, $config, $context);
if ($result === false) unset($attr['name']);
else $attr['name'] = $result;
return $attr;
}
}
// vim: et sw=4 sts=4

@ -1,16 +0,0 @@
<?php
/**
* Writes default type for all objects. Currently only supports flash.
*/
class HTMLPurifier_AttrTransform_SafeObject extends HTMLPurifier_AttrTransform
{
public $name = "SafeObject";
function transform($attr, $config, $context) {
if (!isset($attr['type'])) $attr['type'] = 'application/x-shockwave-flash';
return $attr;
}
}
// vim: et sw=4 sts=4

@ -1,18 +0,0 @@
<?php
/**
* Sets height/width defaults for <textarea>
*/
class HTMLPurifier_AttrTransform_Textarea extends HTMLPurifier_AttrTransform
{
public function transform($attr, $config, $context) {
// Calculated from Firefox
if (!isset($attr['cols'])) $attr['cols'] = '22';
if (!isset($attr['rows'])) $attr['rows'] = '3';
return $attr;
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,104 +0,0 @@
<?php
// constants are slow, so we use as few as possible
if (!defined('HTMLPURIFIER_PREFIX')) {
define('HTMLPURIFIER_PREFIX', realpath(dirname(__FILE__) . '/..'));
}
// accomodations for versions earlier than 5.0.2
// borrowed from PHP_Compat, LGPL licensed, by Aidan Lister <aidan@php.net>
if (!defined('PHP_EOL')) {
switch (strtoupper(substr(PHP_OS, 0, 3))) {
case 'WIN':
define('PHP_EOL', "\r\n");
break;
case 'DAR':
define('PHP_EOL', "\r");
break;
default:
define('PHP_EOL', "\n");
}
}
/**
* Bootstrap class that contains meta-functionality for HTML Purifier such as
* the autoload function.
*
* @note
* This class may be used without any other files from HTML Purifier.
*/
class HTMLPurifier_Bootstrap
{
/**
* Autoload function for HTML Purifier
* @param $class Class to load
*/
public static function autoload($class) {
$file = HTMLPurifier_Bootstrap::getPath($class);
if (!$file) return false;
// Technically speaking, it should be ok and more efficient to
// just do 'require', but Antonio Parraga reports that with
// Zend extensions such as Zend debugger and APC, this invariant
// may be broken. Since we have efficient alternatives, pay
// the cost here and avoid the bug.
require_once HTMLPURIFIER_PREFIX . '/' . $file;
return true;
}
/**
* Returns the path for a specific class.
*/
public static function getPath($class) {
if (strncmp('HTMLPurifier', $class, 12) !== 0) return false;
// Custom implementations
if (strncmp('HTMLPurifier_Language_', $class, 22) === 0) {
$code = str_replace('_', '-', substr($class, 22));
$file = 'HTMLPurifier/Language/classes/' . $code . '.php';
} else {
$file = str_replace('_', '/', $class) . '.php';
}
if (!file_exists(HTMLPURIFIER_PREFIX . '/' . $file)) return false;
return $file;
}
/**
* "Pre-registers" our autoloader on the SPL stack.
*/
public static function registerAutoload() {
$autoload = array('HTMLPurifier_Bootstrap', 'autoload');
if ( ($funcs = spl_autoload_functions()) === false ) {
spl_autoload_register($autoload);
} elseif (function_exists('spl_autoload_unregister')) {
$buggy = version_compare(PHP_VERSION, '5.2.11', '<');
$compat = version_compare(PHP_VERSION, '5.1.2', '<=') &&
version_compare(PHP_VERSION, '5.1.0', '>=');
foreach ($funcs as $func) {
if ($buggy && is_array($func)) {
// :TRICKY: There are some compatibility issues and some
// places where we need to error out
$reflector = new ReflectionMethod($func[0], $func[1]);
if (!$reflector->isStatic()) {
throw new Exception('
HTML Purifier autoloader registrar is not compatible
with non-static object methods due to PHP Bug #44144;
Please do not use HTMLPurifier.autoload.php (or any
file that includes this file); instead, place the code:
spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\'))
after your own autoloaders.
');
}
// Suprisingly, spl_autoload_register supports the
// Class::staticMethod callback format, although call_user_func doesn't
if ($compat) $func = implode('::', $func);
}
spl_autoload_unregister($func);
}
spl_autoload_register($autoload);
foreach ($funcs as $func) spl_autoload_register($func);
}
}
}
// vim: et sw=4 sts=4

@ -1,301 +0,0 @@
<?php
/**
* Defines allowed CSS attributes and what their values are.
* @see HTMLPurifier_HTMLDefinition
*/
class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
{
public $type = 'CSS';
/**
* Assoc array of attribute name to definition object.
*/
public $info = array();
/**
* Constructs the info array. The meat of this class.
*/
protected function doSetup($config) {
$this->info['text-align'] = new HTMLPurifier_AttrDef_Enum(
array('left', 'right', 'center', 'justify'), false);
$border_style =
$this->info['border-bottom-style'] =
$this->info['border-right-style'] =
$this->info['border-left-style'] =
$this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum(
array('none', 'hidden', 'dotted', 'dashed', 'solid', 'double',
'groove', 'ridge', 'inset', 'outset'), false);
$this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style);
$this->info['clear'] = new HTMLPurifier_AttrDef_Enum(
array('none', 'left', 'right', 'both'), false);
$this->info['float'] = new HTMLPurifier_AttrDef_Enum(
array('none', 'left', 'right'), false);
$this->info['font-style'] = new HTMLPurifier_AttrDef_Enum(
array('normal', 'italic', 'oblique'), false);
$this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum(
array('normal', 'small-caps'), false);
$uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite(
array(
new HTMLPurifier_AttrDef_Enum(array('none')),
new HTMLPurifier_AttrDef_CSS_URI()
)
);
$this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum(
array('inside', 'outside'), false);
$this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum(
array('disc', 'circle', 'square', 'decimal', 'lower-roman',
'upper-roman', 'lower-alpha', 'upper-alpha', 'none'), false);
$this->info['list-style-image'] = $uri_or_none;
$this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config);
$this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum(
array('capitalize', 'uppercase', 'lowercase', 'none'), false);
$this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color();
$this->info['background-image'] = $uri_or_none;
$this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum(
array('repeat', 'repeat-x', 'repeat-y', 'no-repeat')
);
$this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum(
array('scroll', 'fixed')
);
$this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition();
$border_color =
$this->info['border-top-color'] =
$this->info['border-bottom-color'] =
$this->info['border-left-color'] =
$this->info['border-right-color'] =
$this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('transparent')),
new HTMLPurifier_AttrDef_CSS_Color()
));
$this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config);
$this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_color);
$border_width =
$this->info['border-top-width'] =
$this->info['border-bottom-width'] =
$this->info['border-left-width'] =
$this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')),
new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
));
$this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width);
$this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('normal')),
new HTMLPurifier_AttrDef_CSS_Length()
));
$this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('normal')),
new HTMLPurifier_AttrDef_CSS_Length()
));
$this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('xx-small', 'x-small',
'small', 'medium', 'large', 'x-large', 'xx-large',
'larger', 'smaller')),
new HTMLPurifier_AttrDef_CSS_Percentage(),
new HTMLPurifier_AttrDef_CSS_Length()
));
$this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('normal')),
new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives
new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Percentage(true)
));
$margin =
$this->info['margin-top'] =
$this->info['margin-bottom'] =
$this->info['margin-left'] =
$this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length(),
new HTMLPurifier_AttrDef_CSS_Percentage(),
new HTMLPurifier_AttrDef_Enum(array('auto'))
));
$this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin);
// non-negative
$padding =
$this->info['padding-top'] =
$this->info['padding-bottom'] =
$this->info['padding-left'] =
$this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Percentage(true)
));
$this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding);
$this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length(),
new HTMLPurifier_AttrDef_CSS_Percentage()
));
$trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Percentage(true),
new HTMLPurifier_AttrDef_Enum(array('auto'))
));
$max = $config->get('CSS.MaxImgLength');
$this->info['width'] =
$this->info['height'] =
$max === null ?
$trusted_wh :
new HTMLPurifier_AttrDef_Switch('img',
// For img tags:
new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length('0', $max),
new HTMLPurifier_AttrDef_Enum(array('auto'))
)),
// For everyone else:
$trusted_wh
);
$this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();
$this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily();
// this could use specialized code
$this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum(
array('normal', 'bold', 'bolder', 'lighter', '100', '200', '300',
'400', '500', '600', '700', '800', '900'), false);
// MUST be called after other font properties, as it references
// a CSSDefinition object
$this->info['font'] = new HTMLPurifier_AttrDef_CSS_Font($config);
// same here
$this->info['border'] =
$this->info['border-bottom'] =
$this->info['border-top'] =
$this->info['border-left'] =
$this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config);
$this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum(array(
'collapse', 'separate'));
$this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum(array(
'top', 'bottom'));
$this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum(array(
'auto', 'fixed'));
$this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('baseline', 'sub', 'super',
'top', 'text-top', 'middle', 'bottom', 'text-bottom')),
new HTMLPurifier_AttrDef_CSS_Length(),
new HTMLPurifier_AttrDef_CSS_Percentage()
));
$this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2);
// partial support
$this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap'));
if ($config->get('CSS.Proprietary')) {
$this->doSetupProprietary($config);
}
if ($config->get('CSS.AllowTricky')) {
$this->doSetupTricky($config);
}
$allow_important = $config->get('CSS.AllowImportant');
// wrap all attr-defs with decorator that handles !important
foreach ($this->info as $k => $v) {
$this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important);
}
$this->setupConfigStuff($config);
}
protected function doSetupProprietary($config) {
// Internet Explorer only scrollbar colors
$this->info['scrollbar-arrow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
$this->info['scrollbar-base-color'] = new HTMLPurifier_AttrDef_CSS_Color();
$this->info['scrollbar-darkshadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
$this->info['scrollbar-face-color'] = new HTMLPurifier_AttrDef_CSS_Color();
$this->info['scrollbar-highlight-color'] = new HTMLPurifier_AttrDef_CSS_Color();
$this->info['scrollbar-shadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
// technically not proprietary, but CSS3, and no one supports it
$this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
$this->info['-moz-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
$this->info['-khtml-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
// only opacity, for now
$this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter();
}
protected function doSetupTricky($config) {
$this->info['display'] = new HTMLPurifier_AttrDef_Enum(array(
'inline', 'block', 'list-item', 'run-in', 'compact',
'marker', 'table', 'inline-table', 'table-row-group',
'table-header-group', 'table-footer-group', 'table-row',
'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none'
));
$this->info['visibility'] = new HTMLPurifier_AttrDef_Enum(array(
'visible', 'hidden', 'collapse'
));
$this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll'));
}
/**
* Performs extra config-based processing. Based off of
* HTMLPurifier_HTMLDefinition.
* @todo Refactor duplicate elements into common class (probably using
* composition, not inheritance).
*/
protected function setupConfigStuff($config) {
// setup allowed elements
$support = "(for information on implementing this, see the ".
"support forums) ";
$allowed_properties = $config->get('CSS.AllowedProperties');
if ($allowed_properties !== null) {
foreach ($this->info as $name => $d) {
if(!isset($allowed_properties[$name])) unset($this->info[$name]);
unset($allowed_properties[$name]);
}
// emit errors
foreach ($allowed_properties as $name => $d) {
// :TODO: Is this htmlspecialchars() call really necessary?
$name = htmlspecialchars($name);
trigger_error("Style attribute '$name' is not supported $support", E_USER_WARNING);
}
}
$forbidden_properties = $config->get('CSS.ForbiddenProperties');
if ($forbidden_properties !== null) {
foreach ($this->info as $name => $d) {
if (isset($forbidden_properties[$name])) {
unset($this->info[$name]);
}
}
}
}
}
// vim: et sw=4 sts=4

@ -1,26 +0,0 @@
<?php
/**
* Definition that allows a set of elements, and allows no children.
* @note This is a hack to reuse code from HTMLPurifier_ChildDef_Required,
* really, one shouldn't inherit from the other. Only altered behavior
* is to overload a returned false with an array. Thus, it will never
* return false.
*/
class HTMLPurifier_ChildDef_Optional extends HTMLPurifier_ChildDef_Required
{
public $allow_empty = true;
public $type = 'optional';
public function validateChildren($tokens_of_children, $config, $context) {
$result = parent::validateChildren($tokens_of_children, $config, $context);
// we assume that $tokens_of_children is not modified
if ($result === false) {
if (empty($tokens_of_children)) return true;
elseif ($this->whitespace) return $tokens_of_children;
else return array();
}
return $result;
}
}
// vim: et sw=4 sts=4

@ -1,117 +0,0 @@
<?php
/**
* Definition that allows a set of elements, but disallows empty children.
*/
class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
{
/**
* Lookup table of allowed elements.
* @public
*/
public $elements = array();
/**
* Whether or not the last passed node was all whitespace.
*/
protected $whitespace = false;
/**
* @param $elements List of allowed element names (lowercase).
*/
public function __construct($elements) {
if (is_string($elements)) {
$elements = str_replace(' ', '', $elements);
$elements = explode('|', $elements);
}
$keys = array_keys($elements);
if ($keys == array_keys($keys)) {
$elements = array_flip($elements);
foreach ($elements as $i => $x) {
$elements[$i] = true;
if (empty($i)) unset($elements[$i]); // remove blank
}
}
$this->elements = $elements;
}
public $allow_empty = false;
public $type = 'required';
public function validateChildren($tokens_of_children, $config, $context) {
// Flag for subclasses
$this->whitespace = false;
// if there are no tokens, delete parent node
if (empty($tokens_of_children)) return false;
// the new set of children
$result = array();
// current depth into the nest
$nesting = 0;
// whether or not we're deleting a node
$is_deleting = false;
// whether or not parsed character data is allowed
// this controls whether or not we silently drop a tag
// or generate escaped HTML from it
$pcdata_allowed = isset($this->elements['#PCDATA']);
// a little sanity check to make sure it's not ALL whitespace
$all_whitespace = true;
// some configuration
$escape_invalid_children = $config->get('Core.EscapeInvalidChildren');
// generator
$gen = new HTMLPurifier_Generator($config, $context);
foreach ($tokens_of_children as $token) {
if (!empty($token->is_whitespace)) {
$result[] = $token;
continue;
}
$all_whitespace = false; // phew, we're not talking about whitespace
$is_child = ($nesting == 0);
if ($token instanceof HTMLPurifier_Token_Start) {
$nesting++;
} elseif ($token instanceof HTMLPurifier_Token_End) {
$nesting--;
}
if ($is_child) {
$is_deleting = false;
if (!isset($this->elements[$token->name])) {
$is_deleting = true;
if ($pcdata_allowed && $token instanceof HTMLPurifier_Token_Text) {
$result[] = $token;
} elseif ($pcdata_allowed && $escape_invalid_children) {
$result[] = new HTMLPurifier_Token_Text(
$gen->generateFromToken($token)
);
}
continue;
}
}
if (!$is_deleting || ($pcdata_allowed && $token instanceof HTMLPurifier_Token_Text)) {
$result[] = $token;
} elseif ($pcdata_allowed && $escape_invalid_children) {
$result[] =
new HTMLPurifier_Token_Text(
$gen->generateFromToken($token)
);
} else {
// drop silently
}
}
if (empty($result)) return false;
if ($all_whitespace) {
$this->whitespace = true;
return false;
}
if ($tokens_of_children == $result) return true;
return $result;
}
}
// vim: et sw=4 sts=4

@ -1,88 +0,0 @@
<?php
/**
* Takes the contents of blockquote when in strict and reformats for validation.
*/
class HTMLPurifier_ChildDef_StrictBlockquote extends HTMLPurifier_ChildDef_Required
{
protected $real_elements;
protected $fake_elements;
public $allow_empty = true;
public $type = 'strictblockquote';
protected $init = false;
/**
* @note We don't want MakeWellFormed to auto-close inline elements since
* they might be allowed.
*/
public function getAllowedElements($config) {
$this->init($config);
return $this->fake_elements;
}
public function validateChildren($tokens_of_children, $config, $context) {
$this->init($config);
// trick the parent class into thinking it allows more
$this->elements = $this->fake_elements;
$result = parent::validateChildren($tokens_of_children, $config, $context);
$this->elements = $this->real_elements;
if ($result === false) return array();
if ($result === true) $result = $tokens_of_children;
$def = $config->getHTMLDefinition();
$block_wrap_start = new HTMLPurifier_Token_Start($def->info_block_wrapper);
$block_wrap_end = new HTMLPurifier_Token_End( $def->info_block_wrapper);
$is_inline = false;
$depth = 0;
$ret = array();
// assuming that there are no comment tokens
foreach ($result as $i => $token) {
$token = $result[$i];
// ifs are nested for readability
if (!$is_inline) {
if (!$depth) {
if (
($token instanceof HTMLPurifier_Token_Text && !$token->is_whitespace) ||
(!$token instanceof HTMLPurifier_Token_Text && !isset($this->elements[$token->name]))
) {
$is_inline = true;
$ret[] = $block_wrap_start;
}
}
} else {
if (!$depth) {
// starting tokens have been inline text / empty
if ($token instanceof HTMLPurifier_Token_Start || $token instanceof HTMLPurifier_Token_Empty) {
if (isset($this->elements[$token->name])) {
// ended
$ret[] = $block_wrap_end;
$is_inline = false;
}
}
}
}
$ret[] = $token;
if ($token instanceof HTMLPurifier_Token_Start) $depth++;
if ($token instanceof HTMLPurifier_Token_End) $depth--;
}
if ($is_inline) $ret[] = $block_wrap_end;
return $ret;
}
private function init($config) {
if (!$this->init) {
$def = $config->getHTMLDefinition();
// allow all inline elements
$this->real_elements = $this->elements;
$this->fake_elements = $def->info_content_sets['Flow'];
$this->fake_elements['#PCDATA'] = true;
$this->init = true;
}
}
}
// vim: et sw=4 sts=4

@ -1,142 +0,0 @@
<?php
/**
* Definition for tables
*/
class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef
{
public $allow_empty = false;
public $type = 'table';
public $elements = array('tr' => true, 'tbody' => true, 'thead' => true,
'tfoot' => true, 'caption' => true, 'colgroup' => true, 'col' => true);
public function __construct() {}
public function validateChildren($tokens_of_children, $config, $context) {
if (empty($tokens_of_children)) return false;
// this ensures that the loop gets run one last time before closing
// up. It's a little bit of a hack, but it works! Just make sure you
// get rid of the token later.
$tokens_of_children[] = false;
// only one of these elements is allowed in a table
$caption = false;
$thead = false;
$tfoot = false;
// as many of these as you want
$cols = array();
$content = array();
$nesting = 0; // current depth so we can determine nodes
$is_collecting = false; // are we globbing together tokens to package
// into one of the collectors?
$collection = array(); // collected nodes
$tag_index = 0; // the first node might be whitespace,
// so this tells us where the start tag is
foreach ($tokens_of_children as $token) {
$is_child = ($nesting == 0);
if ($token === false) {
// terminating sequence started
} elseif ($token instanceof HTMLPurifier_Token_Start) {
$nesting++;
} elseif ($token instanceof HTMLPurifier_Token_End) {
$nesting--;
}
// handle node collection
if ($is_collecting) {
if ($is_child) {
// okay, let's stash the tokens away
// first token tells us the type of the collection
switch ($collection[$tag_index]->name) {
case 'tr':
case 'tbody':
$content[] = $collection;
break;
case 'caption':
if ($caption !== false) break;
$caption = $collection;
break;
case 'thead':
case 'tfoot':
// access the appropriate variable, $thead or $tfoot
$var = $collection[$tag_index]->name;
if ($$var === false) {
$$var = $collection;
} else {
// transmutate the first and less entries into
// tbody tags, and then put into content
$collection[$tag_index]->name = 'tbody';
$collection[count($collection)-1]->name = 'tbody';
$content[] = $collection;
}
break;
case 'colgroup':
$cols[] = $collection;
break;
}
$collection = array();
$is_collecting = false;
$tag_index = 0;
} else {
// add the node to the collection
$collection[] = $token;
}
}
// terminate
if ($token === false) break;
if ($is_child) {
// determine what we're dealing with
if ($token->name == 'col') {
// the only empty tag in the possie, we can handle it
// immediately
$cols[] = array_merge($collection, array($token));
$collection = array();
$tag_index = 0;
continue;
}
switch($token->name) {
case 'caption':
case 'colgroup':
case 'thead':
case 'tfoot':
case 'tbody':
case 'tr':
$is_collecting = true;
$collection[] = $token;
continue;
default:
if (!empty($token->is_whitespace)) {
$collection[] = $token;
$tag_index++;
}
continue;
}
}
}
if (empty($content)) return false;
$ret = array();
if ($caption !== false) $ret = array_merge($ret, $caption);
if ($cols !== false) foreach ($cols as $token_array) $ret = array_merge($ret, $token_array);
if ($thead !== false) $ret = array_merge($ret, $thead);
if ($tfoot !== false) $ret = array_merge($ret, $tfoot);
foreach ($content as $token_array) $ret = array_merge($ret, $token_array);
if (!empty($collection) && $is_collecting == false){
// grab the trailing space
$ret = array_merge($ret, $collection);
}
array_pop($tokens_of_children); // remove phantom token
return ($ret === $tokens_of_children) ? true : $ret;
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,66 +0,0 @@
<?php
/**
* Fluent interface for validating the contents of member variables.
* This should be immutable. See HTMLPurifier_ConfigSchema_Validator for
* use-cases. We name this an 'atom' because it's ONLY for validations that
* are independent and usually scalar.
*/
class HTMLPurifier_ConfigSchema_ValidatorAtom
{
protected $context, $obj, $member, $contents;
public function __construct($context, $obj, $member) {
$this->context = $context;
$this->obj = $obj;
$this->member = $member;
$this->contents =& $obj->$member;
}
public function assertIsString() {
if (!is_string($this->contents)) $this->error('must be a string');
return $this;
}
public function assertIsBool() {
if (!is_bool($this->contents)) $this->error('must be a boolean');
return $this;
}
public function assertIsArray() {
if (!is_array($this->contents)) $this->error('must be an array');
return $this;
}
public function assertNotNull() {
if ($this->contents === null) $this->error('must not be null');
return $this;
}
public function assertAlnum() {
$this->assertIsString();
if (!ctype_alnum($this->contents)) $this->error('must be alphanumeric');
return $this;
}
public function assertNotEmpty() {
if (empty($this->contents)) $this->error('must not be empty');
return $this;
}
public function assertIsLookup() {
$this->assertIsArray();
foreach ($this->contents as $v) {
if ($v !== true) $this->error('must be a lookup array');
}
return $this;
}
protected function error($msg) {
throw new HTMLPurifier_ConfigSchema_Exception(ucfirst($this->member) . ' in ' . $this->context . ' ' . $msg);
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,82 +0,0 @@
<?php
/**
* Registry object that contains information about the current context.
* @warning Is a bit buggy when variables are set to null: it thinks
* they don't exist! So use false instead, please.
* @note Since the variables Context deals with may not be objects,
* references are very important here! Do not remove!
*/
class HTMLPurifier_Context
{
/**
* Private array that stores the references.
*/
private $_storage = array();
/**
* Registers a variable into the context.
* @param $name String name
* @param $ref Reference to variable to be registered
*/
public function register($name, &$ref) {
if (isset($this->_storage[$name])) {
trigger_error("Name $name produces collision, cannot re-register",
E_USER_ERROR);
return;
}
$this->_storage[$name] =& $ref;
}
/**
* Retrieves a variable reference from the context.
* @param $name String name
* @param $ignore_error Boolean whether or not to ignore error
*/
public function &get($name, $ignore_error = false) {
if (!isset($this->_storage[$name])) {
if (!$ignore_error) {
trigger_error("Attempted to retrieve non-existent variable $name",
E_USER_ERROR);
}
$var = null; // so we can return by reference
return $var;
}
return $this->_storage[$name];
}
/**
* Destorys a variable in the context.
* @param $name String name
*/
public function destroy($name) {
if (!isset($this->_storage[$name])) {
trigger_error("Attempted to destroy non-existent variable $name",
E_USER_ERROR);
return;
}
unset($this->_storage[$name]);
}
/**
* Checks whether or not the variable exists.
* @param $name String name
*/
public function exists($name) {
return isset($this->_storage[$name]);
}
/**
* Loads a series of variables from an associative array
* @param $context_array Assoc array of variables to load
*/
public function loadArray($context_array) {
foreach ($context_array as $key => $discard) {
$this->register($key, $context_array[$key]);
}
}
}
// vim: et sw=4 sts=4

@ -1,62 +0,0 @@
<?php
class HTMLPurifier_DefinitionCache_Decorator extends HTMLPurifier_DefinitionCache
{
/**
* Cache object we are decorating
*/
public $cache;
public function __construct() {}
/**
* Lazy decorator function
* @param $cache Reference to cache object to decorate
*/
public function decorate(&$cache) {
$decorator = $this->copy();
// reference is necessary for mocks in PHP 4
$decorator->cache =& $cache;
$decorator->type = $cache->type;
return $decorator;
}
/**
* Cross-compatible clone substitute
*/
public function copy() {
return new HTMLPurifier_DefinitionCache_Decorator();
}
public function add($def, $config) {
return $this->cache->add($def, $config);
}
public function set($def, $config) {
return $this->cache->set($def, $config);
}
public function replace($def, $config) {
return $this->cache->replace($def, $config);
}
public function get($config) {
return $this->cache->get($config);
}
public function remove($config) {
return $this->cache->remove($config);
}
public function flush($config) {
return $this->cache->flush($config);
}
public function cleanup($config) {
return $this->cache->cleanup($config);
}
}
// vim: et sw=4 sts=4

@ -1,43 +0,0 @@
<?php
/**
* Definition cache decorator class that cleans up the cache
* whenever there is a cache miss.
*/
class HTMLPurifier_DefinitionCache_Decorator_Cleanup extends
HTMLPurifier_DefinitionCache_Decorator
{
public $name = 'Cleanup';
public function copy() {
return new HTMLPurifier_DefinitionCache_Decorator_Cleanup();
}
public function add($def, $config) {
$status = parent::add($def, $config);
if (!$status) parent::cleanup($config);
return $status;
}
public function set($def, $config) {
$status = parent::set($def, $config);
if (!$status) parent::cleanup($config);
return $status;
}
public function replace($def, $config) {
$status = parent::replace($def, $config);
if (!$status) parent::cleanup($config);
return $status;
}
public function get($config) {
$ret = parent::get($config);
if (!$ret) parent::cleanup($config);
return $ret;
}
}
// vim: et sw=4 sts=4

@ -1,46 +0,0 @@
<?php
/**
* Definition cache decorator class that saves all cache retrievals
* to PHP's memory; good for unit tests or circumstances where
* there are lots of configuration objects floating around.
*/
class HTMLPurifier_DefinitionCache_Decorator_Memory extends
HTMLPurifier_DefinitionCache_Decorator
{
protected $definitions;
public $name = 'Memory';
public function copy() {
return new HTMLPurifier_DefinitionCache_Decorator_Memory();
}
public function add($def, $config) {
$status = parent::add($def, $config);
if ($status) $this->definitions[$this->generateKey($config)] = $def;
return $status;
}
public function set($def, $config) {
$status = parent::set($def, $config);
if ($status) $this->definitions[$this->generateKey($config)] = $def;
return $status;
}
public function replace($def, $config) {
$status = parent::replace($def, $config);
if ($status) $this->definitions[$this->generateKey($config)] = $def;
return $status;
}
public function get($config) {
$key = $this->generateKey($config);
if (isset($this->definitions[$key])) return $this->definitions[$key];
$this->definitions[$key] = parent::get($config);
return $this->definitions[$key];
}
}
// vim: et sw=4 sts=4

@ -1,47 +0,0 @@
<?php
require_once 'HTMLPurifier/DefinitionCache/Decorator.php';
/**
* Definition cache decorator template.
*/
class HTMLPurifier_DefinitionCache_Decorator_Template extends
HTMLPurifier_DefinitionCache_Decorator
{
var $name = 'Template'; // replace this
function copy() {
// replace class name with yours
return new HTMLPurifier_DefinitionCache_Decorator_Template();
}
// remove methods you don't need
function add($def, $config) {
return parent::add($def, $config);
}
function set($def, $config) {
return parent::set($def, $config);
}
function replace($def, $config) {
return parent::replace($def, $config);
}
function get($config) {
return parent::get($config);
}
function flush() {
return parent::flush();
}
function cleanup($config) {
return parent::cleanup($config);
}
}
// vim: et sw=4 sts=4

@ -1,39 +0,0 @@
<?php
/**
* Null cache object to use when no caching is on.
*/
class HTMLPurifier_DefinitionCache_Null extends HTMLPurifier_DefinitionCache
{
public function add($def, $config) {
return false;
}
public function set($def, $config) {
return false;
}
public function replace($def, $config) {
return false;
}
public function remove($config) {
return false;
}
public function get($config) {
return false;
}
public function flush($config) {
return false;
}
public function cleanup($config) {
return false;
}
}
// vim: et sw=4 sts=4

@ -1,172 +0,0 @@
<?php
class HTMLPurifier_DefinitionCache_Serializer extends
HTMLPurifier_DefinitionCache
{
public function add($def, $config) {
if (!$this->checkDefType($def)) return;
$file = $this->generateFilePath($config);
if (file_exists($file)) return false;
if (!$this->_prepareDir($config)) return false;
return $this->_write($file, serialize($def));
}
public function set($def, $config) {
if (!$this->checkDefType($def)) return;
$file = $this->generateFilePath($config);
if (!$this->_prepareDir($config)) return false;
return $this->_write($file, serialize($def));
}
public function replace($def, $config) {
if (!$this->checkDefType($def)) return;
$file = $this->generateFilePath($config);
if (!file_exists($file)) return false;
if (!$this->_prepareDir($config)) return false;
return $this->_write($file, serialize($def));
}
public function get($config) {
$file = $this->generateFilePath($config);
if (!file_exists($file)) return false;
return unserialize(file_get_contents($file));
}
public function remove($config) {
$file = $this->generateFilePath($config);
if (!file_exists($file)) return false;
return unlink($file);
}
public function flush($config) {
if (!$this->_prepareDir($config)) return false;
$dir = $this->generateDirectoryPath($config);
$dh = opendir($dir);
while (false !== ($filename = readdir($dh))) {
if (empty($filename)) continue;
if ($filename[0] === '.') continue;
unlink($dir . '/' . $filename);
}
}
public function cleanup($config) {
if (!$this->_prepareDir($config)) return false;
$dir = $this->generateDirectoryPath($config);
$dh = opendir($dir);
while (false !== ($filename = readdir($dh))) {
if (empty($filename)) continue;
if ($filename[0] === '.') continue;
$key = substr($filename, 0, strlen($filename) - 4);
if ($this->isOld($key, $config)) unlink($dir . '/' . $filename);
}
}
/**
* Generates the file path to the serial file corresponding to
* the configuration and definition name
* @todo Make protected
*/
public function generateFilePath($config) {
$key = $this->generateKey($config);
return $this->generateDirectoryPath($config) . '/' . $key . '.ser';
}
/**
* Generates the path to the directory contain this cache's serial files
* @note No trailing slash
* @todo Make protected
*/
public function generateDirectoryPath($config) {
$base = $this->generateBaseDirectoryPath($config);
return $base . '/' . $this->type;
}
/**
* Generates path to base directory that contains all definition type
* serials
* @todo Make protected
*/
public function generateBaseDirectoryPath($config) {
$base = $config->get('Cache.SerializerPath');
$base = is_null($base) ? HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer' : $base;
return $base;
}
/**
* Convenience wrapper function for file_put_contents
* @param $file File name to write to
* @param $data Data to write into file
* @return Number of bytes written if success, or false if failure.
*/
private function _write($file, $data) {
return file_put_contents($file, $data);
}
/**
* Prepares the directory that this type stores the serials in
* @return True if successful
*/
private function _prepareDir($config) {
$directory = $this->generateDirectoryPath($config);
if (!is_dir($directory)) {
$base = $this->generateBaseDirectoryPath($config);
if (!is_dir($base)) {
trigger_error('Base directory '.$base.' does not exist,
please create or change using %Cache.SerializerPath',
E_USER_WARNING);
return false;
} elseif (!$this->_testPermissions($base)) {
return false;
}
$old = umask(0022); // disable group and world writes
mkdir($directory);
umask($old);
} elseif (!$this->_testPermissions($directory)) {
return false;
}
return true;
}
/**
* Tests permissions on a directory and throws out friendly
* error messages and attempts to chmod it itself if possible
*/
private function _testPermissions($dir) {
// early abort, if it is writable, everything is hunky-dory
if (is_writable($dir)) return true;
if (!is_dir($dir)) {
// generally, you'll want to handle this beforehand
// so a more specific error message can be given
trigger_error('Directory '.$dir.' does not exist',
E_USER_WARNING);
return false;
}
if (function_exists('posix_getuid')) {
// POSIX system, we can give more specific advice
if (fileowner($dir) === posix_getuid()) {
// we can chmod it ourselves
chmod($dir, 0755);
return true;
} elseif (filegroup($dir) === posix_getgid()) {
$chmod = '775';
} else {
// PHP's probably running as nobody, so we'll
// need to give global permissions
$chmod = '777';
}
trigger_error('Directory '.$dir.' not writable, '.
'please chmod to ' . $chmod,
E_USER_WARNING);
} else {
// generic error message
trigger_error('Directory '.$dir.' not writable, '.
'please alter file permissions',
E_USER_WARNING);
}
return false;
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

File diff suppressed because one or more lines are too long

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,135 +0,0 @@
<?php
/**
* This filter extracts <style> blocks from input HTML, cleans them up
* using CSSTidy, and then places them in $purifier->context->get('StyleBlocks')
* so they can be used elsewhere in the document.
*
* @note
* See tests/HTMLPurifier/Filter/ExtractStyleBlocksTest.php for
* sample usage.
*
* @note
* This filter can also be used on stylesheets not included in the
* document--something purists would probably prefer. Just directly
* call HTMLPurifier_Filter_ExtractStyleBlocks->cleanCSS()
*/
class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
{
public $name = 'ExtractStyleBlocks';
private $_styleMatches = array();
private $_tidy;
public function __construct() {
$this->_tidy = new csstidy();
}
/**
* Save the contents of CSS blocks to style matches
* @param $matches preg_replace style $matches array
*/
protected function styleCallback($matches) {
$this->_styleMatches[] = $matches[1];
}
/**
* Removes inline <style> tags from HTML, saves them for later use
* @todo Extend to indicate non-text/css style blocks
*/
public function preFilter($html, $config, $context) {
$tidy = $config->get('Filter.ExtractStyleBlocks.TidyImpl');
if ($tidy !== null) $this->_tidy = $tidy;
$html = preg_replace_callback('#<style(?:\s.*)?>(.+)</style>#isU', array($this, 'styleCallback'), $html);
$style_blocks = $this->_styleMatches;
$this->_styleMatches = array(); // reset
$context->register('StyleBlocks', $style_blocks); // $context must not be reused
if ($this->_tidy) {
foreach ($style_blocks as &$style) {
$style = $this->cleanCSS($style, $config, $context);
}
}
return $html;
}
/**
* Takes CSS (the stuff found in <style>) and cleans it.
* @warning Requires CSSTidy <http://csstidy.sourceforge.net/>
* @param $css CSS styling to clean
* @param $config Instance of HTMLPurifier_Config
* @param $context Instance of HTMLPurifier_Context
* @return Cleaned CSS
*/
public function cleanCSS($css, $config, $context) {
// prepare scope
$scope = $config->get('Filter.ExtractStyleBlocks.Scope');
if ($scope !== null) {
$scopes = array_map('trim', explode(',', $scope));
} else {
$scopes = array();
}
// remove comments from CSS
$css = trim($css);
if (strncmp('<!--', $css, 4) === 0) {
$css = substr($css, 4);
}
if (strlen($css) > 3 && substr($css, -3) == '-->') {
$css = substr($css, 0, -3);
}
$css = trim($css);
$this->_tidy->parse($css);
$css_definition = $config->getDefinition('CSS');
foreach ($this->_tidy->css as $k => $decls) {
// $decls are all CSS declarations inside an @ selector
$new_decls = array();
foreach ($decls as $selector => $style) {
$selector = trim($selector);
if ($selector === '') continue; // should not happen
if ($selector[0] === '+') {
if ($selector !== '' && $selector[0] === '+') continue;
}
if (!empty($scopes)) {
$new_selector = array(); // because multiple ones are possible
$selectors = array_map('trim', explode(',', $selector));
foreach ($scopes as $s1) {
foreach ($selectors as $s2) {
$new_selector[] = "$s1 $s2";
}
}
$selector = implode(', ', $new_selector); // now it's a string
}
foreach ($style as $name => $value) {
if (!isset($css_definition->info[$name])) {
unset($style[$name]);
continue;
}
$def = $css_definition->info[$name];
$ret = $def->validate($value, $config, $context);
if ($ret === false) unset($style[$name]);
else $style[$name] = $ret;
}
$new_decls[$selector] = $style;
}
$this->_tidy->css[$k] = $new_decls;
}
// remove stuff that shouldn't be used, could be reenabled
// after security risks are analyzed
$this->_tidy->import = array();
$this->_tidy->charset = null;
$this->_tidy->namespace = null;
$css = $this->_tidy->print->plain();
// we are going to escape any special characters <>& to ensure
// that no funny business occurs (i.e. </style> in a font-family prop).
if ($config->get('Filter.ExtractStyleBlocks.Escaping')) {
$css = str_replace(
array('<', '>', '&'),
array('\3C ', '\3E ', '\26 '),
$css
);
}
return $css;
}
}
// vim: et sw=4 sts=4

@ -1,39 +0,0 @@
<?php
class HTMLPurifier_Filter_YouTube extends HTMLPurifier_Filter
{
public $name = 'YouTube';
public function preFilter($html, $config, $context) {
$pre_regex = '#<object[^>]+>.+?'.
'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s';
$pre_replace = '<span class="youtube-embed">\1</span>';
return preg_replace($pre_regex, $pre_replace, $html);
}
public function postFilter($html, $config, $context) {
$post_regex = '#<span class="youtube-embed">((?:v|cp)/[A-Za-z0-9\-_=]+)</span>#';
return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html);
}
protected function armorUrl($url) {
return str_replace('--', '-&#45;', $url);
}
protected function postFilterCallback($matches) {
$url = $this->armorUrl($matches[1]);
return '<object width="425" height="350" type="application/x-shockwave-flash" '.
'data="http://www.youtube.com/'.$url.'">'.
'<param name="movie" value="http://www.youtube.com/'.$url.'"></param>'.
'<!--[if IE]>'.
'<embed src="http://www.youtube.com/'.$url.'"'.
'type="application/x-shockwave-flash"'.
'wmode="transparent" width="425" height="350" />'.
'<![endif]-->'.
'</object>';
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,118 +0,0 @@
<?php
/**
* XHTML 1.1 Forms module, defines all form-related elements found in HTML 4.
*/
class HTMLPurifier_HTMLModule_Forms extends HTMLPurifier_HTMLModule
{
public $name = 'Forms';
public $safe = false;
public $content_sets = array(
'Block' => 'Form',
'Inline' => 'Formctrl',
);
public function setup($config) {
$form = $this->addElement('form', 'Form',
'Required: Heading | List | Block | fieldset', 'Common', array(
'accept' => 'ContentTypes',
'accept-charset' => 'Charsets',
'action*' => 'URI',
'method' => 'Enum#get,post',
// really ContentType, but these two are the only ones used today
'enctype' => 'Enum#application/x-www-form-urlencoded,multipart/form-data',
));
$form->excludes = array('form' => true);
$input = $this->addElement('input', 'Formctrl', 'Empty', 'Common', array(
'accept' => 'ContentTypes',
'accesskey' => 'Character',
'alt' => 'Text',
'checked' => 'Bool#checked',
'disabled' => 'Bool#disabled',
'maxlength' => 'Number',
'name' => 'CDATA',
'readonly' => 'Bool#readonly',
'size' => 'Number',
'src' => 'URI#embeds',
'tabindex' => 'Number',
'type' => 'Enum#text,password,checkbox,button,radio,submit,reset,file,hidden,image',
'value' => 'CDATA',
));
$input->attr_transform_post[] = new HTMLPurifier_AttrTransform_Input();
$this->addElement('select', 'Formctrl', 'Required: optgroup | option', 'Common', array(
'disabled' => 'Bool#disabled',
'multiple' => 'Bool#multiple',
'name' => 'CDATA',
'size' => 'Number',
'tabindex' => 'Number',
));
$this->addElement('option', false, 'Optional: #PCDATA', 'Common', array(
'disabled' => 'Bool#disabled',
'label' => 'Text',
'selected' => 'Bool#selected',
'value' => 'CDATA',
));
// It's illegal for there to be more than one selected, but not
// be multiple. Also, no selected means undefined behavior. This might
// be difficult to implement; perhaps an injector, or a context variable.
$textarea = $this->addElement('textarea', 'Formctrl', 'Optional: #PCDATA', 'Common', array(
'accesskey' => 'Character',
'cols*' => 'Number',
'disabled' => 'Bool#disabled',
'name' => 'CDATA',
'readonly' => 'Bool#readonly',
'rows*' => 'Number',
'tabindex' => 'Number',
));
$textarea->attr_transform_pre[] = new HTMLPurifier_AttrTransform_Textarea();
$button = $this->addElement('button', 'Formctrl', 'Optional: #PCDATA | Heading | List | Block | Inline', 'Common', array(
'accesskey' => 'Character',
'disabled' => 'Bool#disabled',
'name' => 'CDATA',
'tabindex' => 'Number',
'type' => 'Enum#button,submit,reset',
'value' => 'CDATA',
));
// For exclusions, ideally we'd specify content sets, not literal elements
$button->excludes = $this->makeLookup(
'form', 'fieldset', // Form
'input', 'select', 'textarea', 'label', 'button', // Formctrl
'a' // as per HTML 4.01 spec, this is omitted by modularization
);
// Extra exclusion: img usemap="" is not permitted within this element.
// We'll omit this for now, since we don't have any good way of
// indicating it yet.
// This is HIGHLY user-unfriendly; we need a custom child-def for this
$this->addElement('fieldset', 'Form', 'Custom: (#WS?,legend,(Flow|#PCDATA)*)', 'Common');
$label = $this->addElement('label', 'Formctrl', 'Optional: #PCDATA | Inline', 'Common', array(
'accesskey' => 'Character',
// 'for' => 'IDREF', // IDREF not implemented, cannot allow
));
$label->excludes = array('label' => true);
$this->addElement('legend', false, 'Optional: #PCDATA | Inline', 'Common', array(
'accesskey' => 'Character',
));
$this->addElement('optgroup', false, 'Required: option', 'Common', array(
'disabled' => 'Bool#disabled',
'label*' => 'Text',
));
// Don't forget an injector for <isindex>. This one's a little complex
// because it maps to multiple elements.
}
}
// vim: et sw=4 sts=4

@ -1,21 +0,0 @@
<?php
class HTMLPurifier_HTMLModule_Tidy_Strict extends HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4
{
public $name = 'Tidy_Strict';
public $defaultLevel = 'light';
public function makeFixes() {
$r = parent::makeFixes();
$r['blockquote#content_model_type'] = 'strictblockquote';
return $r;
}
public $defines_child_def = true;
public function getChildDef($def) {
if ($def->content_model_type != 'strictblockquote') return parent::getChildDef($def);
return new HTMLPurifier_ChildDef_StrictBlockquote($def->content_model);
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,51 +0,0 @@
<?php
class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
{
private $context, $config, $attrValidator, $removeNbsp, $removeNbspExceptions;
public function prepare($config, $context) {
parent::prepare($config, $context);
$this->config = $config;
$this->context = $context;
$this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp');
$this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions');
$this->attrValidator = new HTMLPurifier_AttrValidator();
}
public function handleElement(&$token) {
if (!$token instanceof HTMLPurifier_Token_Start) return;
$next = false;
for ($i = $this->inputIndex + 1, $c = count($this->inputTokens); $i < $c; $i++) {
$next = $this->inputTokens[$i];
if ($next instanceof HTMLPurifier_Token_Text) {
if ($next->is_whitespace) continue;
if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) {
$plain = str_replace("\xC2\xA0", "", $next->data);
$isWsOrNbsp = $plain === '' || ctype_space($plain);
if ($isWsOrNbsp) continue;
}
}
break;
}
if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) {
if ($token->name == 'colgroup') return;
$this->attrValidator->validateToken($token, $this->config, $this->context);
$token->armor['ValidateAttributes'] = true;
if (isset($token->attr['id']) || isset($token->attr['name'])) return;
$token = $i - $this->inputIndex + 1;
for ($b = $this->inputIndex - 1; $b > 0; $b--) {
$prev = $this->inputTokens[$b];
if ($prev instanceof HTMLPurifier_Token_Text && $prev->is_whitespace) continue;
break;
}
// This is safe because we removed the token that triggered this.
$this->rewind($b - 1);
return;
}
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,63 +0,0 @@
<?php
$fallback = false;
$messages = array(
'HTMLPurifier' => 'HTML Purifier',
// for unit testing purposes
'LanguageFactoryTest: Pizza' => 'Pizza',
'LanguageTest: List' => '$1',
'LanguageTest: Hash' => '$1.Keys; $1.Values',
'Item separator' => ', ',
'Item separator last' => ' and ', // non-Harvard style
'ErrorCollector: No errors' => 'No errors detected. However, because error reporting is still incomplete, there may have been errors that the error collector was not notified of; please inspect the output HTML carefully.',
'ErrorCollector: At line' => ' at line $line',
'ErrorCollector: Incidental errors' => 'Incidental errors',
'Lexer: Unclosed comment' => 'Unclosed comment',
'Lexer: Unescaped lt' => 'Unescaped less-than sign (<) should be &lt;',
'Lexer: Missing gt' => 'Missing greater-than sign (>), previous less-than sign (<) should be escaped',
'Lexer: Missing attribute key' => 'Attribute declaration has no key',
'Lexer: Missing end quote' => 'Attribute declaration has no end quote',
'Lexer: Extracted body' => 'Removed document metadata tags',
'Strategy_RemoveForeignElements: Tag transform' => '<$1> element transformed into $CurrentToken.Serialized',
'Strategy_RemoveForeignElements: Missing required attribute' => '$CurrentToken.Compact element missing required attribute $1',
'Strategy_RemoveForeignElements: Foreign element to text' => 'Unrecognized $CurrentToken.Serialized tag converted to text',
'Strategy_RemoveForeignElements: Foreign element removed' => 'Unrecognized $CurrentToken.Serialized tag removed',
'Strategy_RemoveForeignElements: Comment removed' => 'Comment containing "$CurrentToken.Data" removed',
'Strategy_RemoveForeignElements: Foreign meta element removed' => 'Unrecognized $CurrentToken.Serialized meta tag and all descendants removed',
'Strategy_RemoveForeignElements: Token removed to end' => 'Tags and text starting from $1 element where removed to end',
'Strategy_RemoveForeignElements: Trailing hyphen in comment removed' => 'Trailing hyphen(s) in comment removed',
'Strategy_RemoveForeignElements: Hyphens in comment collapsed' => 'Double hyphens in comments are not allowed, and were collapsed into single hyphens',
'Strategy_MakeWellFormed: Unnecessary end tag removed' => 'Unnecessary $CurrentToken.Serialized tag removed',
'Strategy_MakeWellFormed: Unnecessary end tag to text' => 'Unnecessary $CurrentToken.Serialized tag converted to text',
'Strategy_MakeWellFormed: Tag auto closed' => '$1.Compact started on line $1.Line auto-closed by $CurrentToken.Compact',
'Strategy_MakeWellFormed: Tag carryover' => '$1.Compact started on line $1.Line auto-continued into $CurrentToken.Compact',
'Strategy_MakeWellFormed: Stray end tag removed' => 'Stray $CurrentToken.Serialized tag removed',
'Strategy_MakeWellFormed: Stray end tag to text' => 'Stray $CurrentToken.Serialized tag converted to text',
'Strategy_MakeWellFormed: Tag closed by element end' => '$1.Compact tag started on line $1.Line closed by end of $CurrentToken.Serialized',
'Strategy_MakeWellFormed: Tag closed by document end' => '$1.Compact tag started on line $1.Line closed by end of document',
'Strategy_FixNesting: Node removed' => '$CurrentToken.Compact node removed',
'Strategy_FixNesting: Node excluded' => '$CurrentToken.Compact node removed due to descendant exclusion by ancestor element',
'Strategy_FixNesting: Node reorganized' => 'Contents of $CurrentToken.Compact node reorganized to enforce its content model',
'Strategy_FixNesting: Node contents removed' => 'Contents of $CurrentToken.Compact node removed',
'AttrValidator: Attributes transformed' => 'Attributes on $CurrentToken.Compact transformed from $1.Keys to $2.Keys',
'AttrValidator: Attribute removed' => '$CurrentAttr.Name attribute on $CurrentToken.Compact removed',
);
$errorNames = array(
E_ERROR => 'Error',
E_WARNING => 'Warning',
E_NOTICE => 'Notice'
);
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,139 +0,0 @@
<?php
/**
* Proof-of-concept lexer that uses the PEAR package XML_HTMLSax3 to parse HTML.
*
* PEAR, not suprisingly, also has a SAX parser for HTML. I don't know
* very much about implementation, but it's fairly well written. However, that
* abstraction comes at a price: performance. You need to have it installed,
* and if the API changes, it might break our adapter. Not sure whether or not
* it's UTF-8 aware, but it has some entity parsing trouble (in all areas,
* text and attributes).
*
* Quite personally, I don't recommend using the PEAR class, and the defaults
* don't use it. The unit tests do perform the tests on the SAX parser too, but
* whatever it does for poorly formed HTML is up to it.
*
* @todo Generalize so that XML_HTMLSax is also supported.
*
* @warning Entity-resolution inside attributes is broken.
*/
class HTMLPurifier_Lexer_PEARSax3 extends HTMLPurifier_Lexer
{
/**
* Internal accumulator array for SAX parsers.
*/
protected $tokens = array();
protected $last_token_was_empty;
private $parent_handler;
private $stack = array();
public function tokenizeHTML($string, $config, $context) {
$this->tokens = array();
$this->last_token_was_empty = false;
$string = $this->normalize($string, $config, $context);
$this->parent_handler = set_error_handler(array($this, 'muteStrictErrorHandler'));
$parser = new XML_HTMLSax3();
$parser->set_object($this);
$parser->set_element_handler('openHandler','closeHandler');
$parser->set_data_handler('dataHandler');
$parser->set_escape_handler('escapeHandler');
// doesn't seem to work correctly for attributes
$parser->set_option('XML_OPTION_ENTITIES_PARSED', 1);
$parser->parse($string);
restore_error_handler();
return $this->tokens;
}
/**
* Open tag event handler, interface is defined by PEAR package.
*/
public function openHandler(&$parser, $name, $attrs, $closed) {
// entities are not resolved in attrs
foreach ($attrs as $key => $attr) {
$attrs[$key] = $this->parseData($attr);
}
if ($closed) {
$this->tokens[] = new HTMLPurifier_Token_Empty($name, $attrs);
$this->last_token_was_empty = true;
} else {
$this->tokens[] = new HTMLPurifier_Token_Start($name, $attrs);
}
$this->stack[] = $name;
return true;
}
/**
* Close tag event handler, interface is defined by PEAR package.
*/
public function closeHandler(&$parser, $name) {
// HTMLSax3 seems to always send empty tags an extra close tag
// check and ignore if you see it:
// [TESTME] to make sure it doesn't overreach
if ($this->last_token_was_empty) {
$this->last_token_was_empty = false;
return true;
}
$this->tokens[] = new HTMLPurifier_Token_End($name);
if (!empty($this->stack)) array_pop($this->stack);
return true;
}
/**
* Data event handler, interface is defined by PEAR package.
*/
public function dataHandler(&$parser, $data) {
$this->last_token_was_empty = false;
$this->tokens[] = new HTMLPurifier_Token_Text($data);
return true;
}
/**
* Escaped text handler, interface is defined by PEAR package.
*/
public function escapeHandler(&$parser, $data) {
if (strpos($data, '--') === 0) {
// remove trailing and leading double-dashes
$data = substr($data, 2);
if (strlen($data) >= 2 && substr($data, -2) == "--") {
$data = substr($data, 0, -2);
}
if (isset($this->stack[sizeof($this->stack) - 1]) &&
$this->stack[sizeof($this->stack) - 1] == "style") {
$this->tokens[] = new HTMLPurifier_Token_Text($data);
} else {
$this->tokens[] = new HTMLPurifier_Token_Comment($data);
}
$this->last_token_was_empty = false;
}
// CDATA is handled elsewhere, but if it was handled here:
//if (strpos($data, '[CDATA[') === 0) {
// $this->tokens[] = new HTMLPurifier_Token_Text(
// substr($data, 7, strlen($data) - 9) );
//}
return true;
}
/**
* An error handler that mutes strict errors
*/
public function muteStrictErrorHandler($errno, $errstr, $errfile=null, $errline=null, $errcontext=null) {
if ($errno == E_STRICT) return;
return call_user_func($this->parent_handler, $errno, $errstr, $errfile, $errline, $errcontext);
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

@ -1,328 +0,0 @@
<?php
/**
* Takes a well formed list of tokens and fixes their nesting.
*
* HTML elements dictate which elements are allowed to be their children,
* for example, you can't have a p tag in a span tag. Other elements have
* much more rigorous definitions: tables, for instance, require a specific
* order for their elements. There are also constraints not expressible by
* document type definitions, such as the chameleon nature of ins/del
* tags and global child exclusions.
*
* The first major objective of this strategy is to iterate through all the
* nodes (not tokens) of the list of tokens and determine whether or not
* their children conform to the element's definition. If they do not, the
* child definition may optionally supply an amended list of elements that
* is valid or require that the entire node be deleted (and the previous
* node rescanned).
*
* The second objective is to ensure that explicitly excluded elements of
* an element do not appear in its children. Code that accomplishes this
* task is pervasive through the strategy, though the two are distinct tasks
* and could, theoretically, be seperated (although it's not recommended).
*
* @note Whether or not unrecognized children are silently dropped or
* translated into text depends on the child definitions.
*
* @todo Enable nodes to be bubbled out of the structure.
*/
class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
{
public function execute($tokens, $config, $context) {
//####################################################################//
// Pre-processing
// get a copy of the HTML definition
$definition = $config->getHTMLDefinition();
// insert implicit "parent" node, will be removed at end.
// DEFINITION CALL
$parent_name = $definition->info_parent;
array_unshift($tokens, new HTMLPurifier_Token_Start($parent_name));
$tokens[] = new HTMLPurifier_Token_End($parent_name);
// setup the context variable 'IsInline', for chameleon processing
// is 'false' when we are not inline, 'true' when it must always
// be inline, and an integer when it is inline for a certain
// branch of the document tree
$is_inline = $definition->info_parent_def->descendants_are_inline;
$context->register('IsInline', $is_inline);
// setup error collector
$e =& $context->get('ErrorCollector', true);
//####################################################################//
// Loop initialization
// stack that contains the indexes of all parents,
// $stack[count($stack)-1] being the current parent
$stack = array();
// stack that contains all elements that are excluded
// it is organized by parent elements, similar to $stack,
// but it is only populated when an element with exclusions is
// processed, i.e. there won't be empty exclusions.
$exclude_stack = array();
// variable that contains the start token while we are processing
// nodes. This enables error reporting to do its job
$start_token = false;
$context->register('CurrentToken', $start_token);
//####################################################################//
// Loop
// iterate through all start nodes. Determining the start node
// is complicated so it has been omitted from the loop construct
for ($i = 0, $size = count($tokens) ; $i < $size; ) {
//################################################################//
// Gather information on children
// child token accumulator
$child_tokens = array();
// scroll to the end of this node, report number, and collect
// all children
for ($j = $i, $depth = 0; ; $j++) {
if ($tokens[$j] instanceof HTMLPurifier_Token_Start) {
$depth++;
// skip token assignment on first iteration, this is the
// token we currently are on
if ($depth == 1) continue;
} elseif ($tokens[$j] instanceof HTMLPurifier_Token_End) {
$depth--;
// skip token assignment on last iteration, this is the
// end token of the token we're currently on
if ($depth == 0) break;
}
$child_tokens[] = $tokens[$j];
}
// $i is index of start token
// $j is index of end token
$start_token = $tokens[$i]; // to make token available via CurrentToken
//################################################################//
// Gather information on parent
// calculate parent information
if ($count = count($stack)) {
$parent_index = $stack[$count-1];
$parent_name = $tokens[$parent_index]->name;
if ($parent_index == 0) {
$parent_def = $definition->info_parent_def;
} else {
$parent_def = $definition->info[$parent_name];
}
} else {
// processing as if the parent were the "root" node
// unknown info, it won't be used anyway, in the future,
// we may want to enforce one element only (this is
// necessary for HTML Purifier to clean entire documents
$parent_index = $parent_name = $parent_def = null;
}
// calculate context
if ($is_inline === false) {
// check if conditions make it inline
if (!empty($parent_def) && $parent_def->descendants_are_inline) {
$is_inline = $count - 1;
}
} else {
// check if we're out of inline
if ($count === $is_inline) {
$is_inline = false;
}
}
//################################################################//
// Determine whether element is explicitly excluded SGML-style
// determine whether or not element is excluded by checking all
// parent exclusions. The array should not be very large, two
// elements at most.
$excluded = false;
if (!empty($exclude_stack)) {
foreach ($exclude_stack as $lookup) {
if (isset($lookup[$tokens[$i]->name])) {
$excluded = true;
// no need to continue processing
break;
}
}
}
//################################################################//
// Perform child validation
if ($excluded) {
// there is an exclusion, remove the entire node
$result = false;
$excludes = array(); // not used, but good to initialize anyway
} else {
// DEFINITION CALL
if ($i === 0) {
// special processing for the first node
$def = $definition->info_parent_def;
} else {
$def = $definition->info[$tokens[$i]->name];
}
if (!empty($def->child)) {
// have DTD child def validate children
$result = $def->child->validateChildren(
$child_tokens, $config, $context);
} else {
// weird, no child definition, get rid of everything
$result = false;
}
// determine whether or not this element has any exclusions
$excludes = $def->excludes;
}
// $result is now a bool or array
//################################################################//
// Process result by interpreting $result
if ($result === true || $child_tokens === $result) {
// leave the node as is
// register start token as a parental node start
$stack[] = $i;
// register exclusions if there are any
if (!empty($excludes)) $exclude_stack[] = $excludes;
// move cursor to next possible start node
$i++;
} elseif($result === false) {
// remove entire node
if ($e) {
if ($excluded) {
$e->send(E_ERROR, 'Strategy_FixNesting: Node excluded');
} else {
$e->send(E_ERROR, 'Strategy_FixNesting: Node removed');
}
}
// calculate length of inner tokens and current tokens
$length = $j - $i + 1;
// perform removal
array_splice($tokens, $i, $length);
// update size
$size -= $length;
// there is no start token to register,
// current node is now the next possible start node
// unless it turns out that we need to do a double-check
// this is a rought heuristic that covers 100% of HTML's
// cases and 99% of all other cases. A child definition
// that would be tricked by this would be something like:
// ( | a b c) where it's all or nothing. Fortunately,
// our current implementation claims that that case would
// not allow empty, even if it did
if (!$parent_def->child->allow_empty) {
// we need to do a double-check
$i = $parent_index;
array_pop($stack);
}
// PROJECTED OPTIMIZATION: Process all children elements before
// reprocessing parent node.
} else {
// replace node with $result
// calculate length of inner tokens
$length = $j - $i - 1;
if ($e) {
if (empty($result) && $length) {
$e->send(E_ERROR, 'Strategy_FixNesting: Node contents removed');
} else {
$e->send(E_WARNING, 'Strategy_FixNesting: Node reorganized');
}
}
// perform replacement
array_splice($tokens, $i + 1, $length, $result);
// update size
$size -= $length;
$size += count($result);
// register start token as a parental node start
$stack[] = $i;
// register exclusions if there are any
if (!empty($excludes)) $exclude_stack[] = $excludes;
// move cursor to next possible start node
$i++;
}
//################################################################//
// Scroll to next start node
// We assume, at this point, that $i is the index of the token
// that is the first possible new start point for a node.
// Test if the token indeed is a start tag, if not, move forward
// and test again.
$size = count($tokens);
while ($i < $size and !$tokens[$i] instanceof HTMLPurifier_Token_Start) {
if ($tokens[$i] instanceof HTMLPurifier_Token_End) {
// pop a token index off the stack if we ended a node
array_pop($stack);
// pop an exclusion lookup off exclusion stack if
// we ended node and that node had exclusions
if ($i == 0 || $i == $size - 1) {
// use specialized var if it's the super-parent
$s_excludes = $definition->info_parent_def->excludes;
} else {
$s_excludes = $definition->info[$tokens[$i]->name]->excludes;
}
if ($s_excludes) {
array_pop($exclude_stack);
}
}
$i++;
}
}
//####################################################################//
// Post-processing
// remove implicit parent tokens at the beginning and end
array_shift($tokens);
array_pop($tokens);
// remove context variables
$context->destroy('IsInline');
$context->destroy('CurrentToken');
//####################################################################//
// Return
return $tokens;
}
}
// vim: et sw=4 sts=4

@ -1,6 +0,0 @@
<html>
<head>
</head>
<body>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save