1
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-08-12 09:04:31 +02:00

Compare commits

...

11 Commits

Author SHA1 Message Date
Edward Z. Yang
200ead9e4c Support PHP 8.4
Signed-off-by: Edward Z. Yang <ezyang@meta.com>
2024-02-21 23:44:14 -05:00
Edward Z. Yang
0f0fd36896 ci: upgrade semantic-release-action
Signed-off-by: Edward Z. Yang <ezyang@meta.com>
2023-11-17 10:00:42 -05:00
danbrellis
ec92490139 feat: Allows commas to be included in tel URI (#389)
* Allows commas in tel URI scheme validator (addresses #388)

* Adds comment explaining 8429f7b
2023-11-10 10:25:42 -05:00
Tim Düsterhus
ab21ea735a chore: Add support for PHP 8.3 (#382)
* Add PHP 8.3 to CI

* Allow PHP 8.3 in composer.json
2023-08-24 11:15:30 -04:00
Edward Z. Yang
6eb6123036 Don't suggest chmod to 777 (#373)
Signed-off-by: Edward Z. Yang <ezyang@meta.com>
2023-04-30 13:55:11 -04:00
cracksalad
43f49ac9a5 fix: Support for locales using decimal separators other than . (dot) (#372)
* Bugfix UnitConverter expects float got string (strict types enabled)

* Bugfix for latest bugfix with huge numbers

* Bugfix for german locale

* Use number_format instead of str_replace(sprintf())
2023-04-30 09:30:23 -04:00
George Peter Banyard
c05639e0c9 [refactor] Use range() function instead of string increment (#367)
This was found during the analysis for https://wiki.php.net/rfc/saner-inc-dec-operators

I don't know what is the minimal version targeted, so the line which defines ``$c`` may need to be changes to use ``array_merge()``
2023-02-23 13:11:13 -05:00
Steve Bauman
b4136da73c Remove unnecessary disablement of autoload (#364) 2023-02-05 21:40:57 -05:00
Jeff Standen
0176ef4bb6 fix: Invalid scheme check in Attr.TargetBlank (#363) 2023-01-26 19:06:28 -05:00
Francis Lévesque
78a9b4d0da fix: CSSTidy ImportantComments not handled properly (#359)
* fix: CSSTidy ImportantComments not handled properly

Signed-off-by: Francis Lévesque <wolfrank2164@gmail.com>

* fix: CSSTidy ImportantComments not handled properly -> remove comments

Signed-off-by: Francis Lévesque <wolfrank2164@gmail.com>
Co-authored-by: Edward Z. Yang <ezyang@meta.com>
2023-01-21 22:44:44 -05:00
Edward Z. Yang
9ec687c904 fix: fix CI (#361)
Signed-off-by: Edward Z. Yang <ezyang@meta.com>

Signed-off-by: Edward Z. Yang <ezyang@meta.com>
2023-01-21 22:42:38 -05:00
14 changed files with 222 additions and 194 deletions

View File

@@ -10,7 +10,7 @@ jobs:
strategy: strategy:
fail-fast: true fail-fast: true
matrix: matrix:
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
name: PHP ${{ matrix.php }} name: PHP ${{ matrix.php }}

View File

@@ -16,10 +16,10 @@ jobs:
- name: Setup PHP - name: Setup PHP
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
with: with:
php-version: 5.5 php-version: 8.2
- name: Run automated release process with semantic-release - name: Run automated release process with semantic-release
uses: cycjimmy/semantic-release-action@v2 uses: cycjimmy/semantic-release-action@v4
with: with:
extra_plugins: | extra_plugins: |
@semantic-release/changelog @semantic-release/changelog

View File

@@ -13,7 +13,7 @@
} }
], ],
"require": { "require": {
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0" "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
}, },
"require-dev": { "require-dev": {
"cerdic/css-tidy": "^1.7 || ^2.0", "cerdic/css-tidy": "^1.7 || ^2.0",
@@ -38,7 +38,8 @@
"repositories": [ "repositories": [
{ {
"type": "vcs", "type": "vcs",
"url": "https://github.com/ezyang/simpletest.git" "url": "https://github.com/ezyang/simpletest.git",
"no-api": true
} }
] ]
} }

View File

@@ -10,23 +10,21 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
public function __construct() public function __construct()
{ {
$this->mask = '_- '; // Lowercase letters
for ($c = 'a'; $c <= 'z'; $c++) { $l = range('a', 'z');
$this->mask .= $c; // Uppercase letters
} $u = range('A', 'Z');
for ($c = 'A'; $c <= 'Z'; $c++) { // Digits
$this->mask .= $c; $d = range('0', '9');
} // Special bytes used by UTF-8
for ($c = '0'; $c <= '9'; $c++) { $b = array_map('chr', range(0x80, 0xFF));
$this->mask .= $c; // All valid characters for the mask
} // cast-y, but should be fine $c = array_merge($l, $u, $d, $b);
// special bytes used by UTF-8 // Concatenate all valid characters into a string
for ($i = 0x80; $i <= 0xFF; $i++) { // Use '_- ' as an initial value
// We don't bother excluding invalid bytes in this range, $this->mask = array_reduce($c, function ($carry, $value) {
// because the our restriction of well-formed UTF-8 will return $carry . $value;
// prevent these from ever occurring. }, '_- ');
$this->mask .= chr($i);
}
/* /*
PHP's internal strcspn implementation is PHP's internal strcspn implementation is

View File

@@ -33,7 +33,11 @@ class HTMLPurifier_AttrTransform_TargetBlank extends HTMLPurifier_AttrTransform
// XXX Kind of inefficient // XXX Kind of inefficient
$url = $this->parser->parse($attr['href']); $url = $this->parser->parse($attr['href']);
$scheme = $url->getSchemeObj($config, $context);
// Ignore invalid schemes (e.g. `javascript:`)
if (!($scheme = $url->getSchemeObj($config, $context))) {
return $attr;
}
if ($scheme->browsable && !$url->isBenign($config, $context)) { if ($scheme->browsable && !$url->isBenign($config, $context)) {
$attr['target'] = '_blank'; $attr['target'] = '_blank';

View File

@@ -287,13 +287,14 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac
} elseif (filegroup($dir) === posix_getgid()) { } elseif (filegroup($dir) === posix_getgid()) {
$chmod = $chmod | 0070; $chmod = $chmod | 0070;
} else { } else {
// PHP's probably running as nobody, so we'll // PHP's probably running as nobody, it is
// need to give global permissions // not obvious how to fix this (777 is probably
$chmod = $chmod | 0777; // bad if you are multi-user), let the user figure it out
$chmod = null;
} }
trigger_error( trigger_error(
'Directory ' . $dir . ' not writable, ' . 'Directory ' . $dir . ' not writable. ' .
'please chmod to ' . decoct($chmod), ($chmod === null ? '' : 'Please chmod to ' . decoct($chmod)),
E_USER_WARNING E_USER_WARNING
); );
} else { } else {

View File

@@ -71,7 +71,7 @@ class HTMLPurifier_DefinitionCacheFactory
return $this->caches[$method][$type]; return $this->caches[$method][$type];
} }
if (isset($this->implementations[$method]) && if (isset($this->implementations[$method]) &&
class_exists($class = $this->implementations[$method], false)) { class_exists($class = $this->implementations[$method])) {
$cache = new $class($type); $cache = new $class($type);
} else { } else {
if ($method != 'Serializer') { if ($method != 'Serializer') {

View File

@@ -146,6 +146,7 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
foreach ($this->_tidy->css as $k => $decls) { foreach ($this->_tidy->css as $k => $decls) {
// $decls are all CSS declarations inside an @ selector // $decls are all CSS declarations inside an @ selector
$new_decls = array(); $new_decls = array();
if (is_array($decls)) {
foreach ($decls as $selector => $style) { foreach ($decls as $selector => $style) {
$selector = trim($selector); $selector = trim($selector);
if ($selector === '') { if ($selector === '') {
@@ -316,6 +317,9 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
} }
$new_decls[$selector] = $style; $new_decls[$selector] = $style;
} }
} else {
continue;
}
$new_css[$k] = $new_decls; $new_css[$k] = $new_decls;
} }
// remove stuff that shouldn't be used, could be reenabled // remove stuff that shouldn't be used, could be reenabled

View File

@@ -109,7 +109,7 @@ class HTMLPurifier_LanguageFactory
} else { } else {
$class = 'HTMLPurifier_Language_' . $pcode; $class = 'HTMLPurifier_Language_' . $pcode;
$file = $this->dir . '/Language/classes/' . $code . '.php'; $file = $this->dir . '/Language/classes/' . $code . '.php';
if (file_exists($file) || class_exists($class, false)) { if (file_exists($file) || class_exists($class)) {
$lang = new $class($config, $context); $lang = new $class($config, $context);
} else { } else {
// Go fallback // Go fallback

View File

@@ -101,7 +101,7 @@ class HTMLPurifier_Lexer
break; break;
} }
if (class_exists('DOMDocument', false) && if (class_exists('DOMDocument') &&
method_exists('DOMDocument', 'loadHTML') && method_exists('DOMDocument', 'loadHTML') &&
!extension_loaded('domxml') !extension_loaded('domxml')
) { ) {

View File

@@ -33,9 +33,9 @@ class HTMLPurifier_URIScheme_tel extends HTMLPurifier_URIScheme
$uri->host = null; $uri->host = null;
$uri->port = null; $uri->port = null;
// Delete all non-numeric characters, non-x characters // Delete all non-numeric characters, commas, and non-x characters
// from phone number, EXCEPT for a leading plus sign. // from phone number, EXCEPT for a leading plus sign.
$uri->path = preg_replace('/(?!^\+)[^\dx]/', '', $uri->path = preg_replace('/(?!^\+)[^\dx,]/', '',
// Normalize e(x)tension to lower-case // Normalize e(x)tension to lower-case
str_replace('X', 'x', rawurldecode($uri->path))); str_replace('X', 'x', rawurldecode($uri->path)));

View File

@@ -261,7 +261,7 @@ class HTMLPurifier_UnitConverter
*/ */
private function round($n, $sigfigs) private function round($n, $sigfigs)
{ {
$new_log = (int)floor(log(abs($n), 10)); // Number of digits left of decimal - 1 $new_log = (int)floor(log(abs((float)$n), 10)); // Number of digits left of decimal - 1
$rp = $sigfigs - $new_log - 1; // Number of decimal places needed $rp = $sigfigs - $new_log - 1; // Number of decimal places needed
$neg = $n < 0 ? '-' : ''; // Negative sign $neg = $n < 0 ? '-' : ''; // Negative sign
if ($this->bcmath) { if ($this->bcmath) {
@@ -276,7 +276,7 @@ class HTMLPurifier_UnitConverter
} }
return $n; return $n;
} else { } else {
return $this->scale(round($n, $sigfigs - $new_log - 1), $rp + 1); return $this->scale(round((float)$n, $sigfigs - $new_log - 1), $rp + 1);
} }
} }
@@ -300,7 +300,7 @@ class HTMLPurifier_UnitConverter
// Now we return it, truncating the zero that was rounded off. // Now we return it, truncating the zero that was rounded off.
return substr($precise, 0, -1) . str_repeat('0', -$scale + 1); return substr($precise, 0, -1) . str_repeat('0', -$scale + 1);
} }
return sprintf('%.' . $scale . 'f', (float)$r); return number_format((float)$r, $scale, '.', '');
} }
} }

View File

@@ -214,6 +214,19 @@ text-align:right
); );
} }
public function test_keepImportantComments()
{
$this->assertCleanCSS(
"/*! Important */
div {
text-align:right /*! Important2 */
}",
"div {
text-align:right
}"
);
}
public function test_atSelector() public function test_atSelector()
{ {
$this->assertCleanCSS( $this->assertCleanCSS(

View File

@@ -102,6 +102,13 @@ class HTMLPurifier_UnitConverterTest extends HTMLPurifier_Harness
$this->assertConversion('11.112pt', '0.15433in'); $this->assertConversion('11.112pt', '0.15433in');
} }
public function testDecimalSeparatorComma()
{
setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu');
$this->assertConversion('11.11px', '0.294cm');
setlocale(LC_ALL, '');
}
public function testRoundingBigNumber() public function testRoundingBigNumber()
{ {
$this->assertConversion('444400000000000000000000in', '42660000000000000000000000px'); $this->assertConversion('444400000000000000000000in', '42660000000000000000000000px');