Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
+18
@@ -37,3 +37,21 @@ BaconQrCode comes with multiple back ends for rendering images. Currently includ
|
||||
- `ImagickImageBackEnd`: renders raster images using the Imagick library
|
||||
- `SvgImageBackEnd`: renders SVG files using XMLWriter
|
||||
- `EpsImageBackEnd`: renders EPS files
|
||||
|
||||
### GDLib Renderer
|
||||
GD library has so many limitations, that GD support is not added as backend, but as separated renderer.
|
||||
Use `GDLibRenderer` instead of `ImageRenderer`. These are the limitations:
|
||||
|
||||
- Does not support gradient.
|
||||
- Does not support any curves, so you QR code is always squared.
|
||||
|
||||
Example usage:
|
||||
|
||||
```php
|
||||
use BaconQrCode\Renderer\GDLibRenderer;
|
||||
use BaconQrCode\Writer;
|
||||
|
||||
$renderer = new GDLibRenderer(400);
|
||||
$writer = new Writer($renderer);
|
||||
$writer->writeFile('Hello World!', 'qrcode.png');
|
||||
```
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
"description": "BaconQrCode is a QR code generator for PHP.",
|
||||
"license": "BSD-2-Clause",
|
||||
"homepage": "https://github.com/Bacon/BaconQrCode",
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"ext-iconv": "*",
|
||||
"dasprid/enum": "^1.0.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-imagick": "to generate QR code images"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Scholzen 'DASPRiD'",
|
||||
"email": "mail@dasprids.de",
|
||||
"homepage": "https://dasprids.de/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"BaconQrCode\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"BaconQrCodeTest\\": "test/"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.5.11 || 11.0.4",
|
||||
"spatie/phpunit-snapshot-assertions": "^5.1.5",
|
||||
"squizlabs/php_codesniffer": "^3.9",
|
||||
"phly/keep-a-changelog": "^2.12"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"ocramius/package-versions": true,
|
||||
"php-http/discovery": true
|
||||
}
|
||||
},
|
||||
"archive": {
|
||||
"exclude": [
|
||||
"/test",
|
||||
"/phpunit.xml.dist"
|
||||
]
|
||||
}
|
||||
}
|
||||
+4
-12
@@ -16,21 +16,13 @@ final class BitArray
|
||||
*
|
||||
* @var SplFixedArray<int>
|
||||
*/
|
||||
private $bits;
|
||||
|
||||
/**
|
||||
* Size of the bit array in bits.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $size;
|
||||
private SplFixedArray $bits;
|
||||
|
||||
/**
|
||||
* Creates a new bit array with a given size.
|
||||
*/
|
||||
public function __construct(int $size = 0)
|
||||
public function __construct(private int $size = 0)
|
||||
{
|
||||
$this->size = $size;
|
||||
$this->bits = SplFixedArray::fromArray(array_fill(0, ($this->size + 31) >> 3, 0));
|
||||
}
|
||||
|
||||
@@ -107,7 +99,7 @@ final class BitArray
|
||||
}
|
||||
|
||||
$result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
|
||||
return $result > $this->size ? $this->size : $result;
|
||||
return min($result, $this->size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +125,7 @@ final class BitArray
|
||||
}
|
||||
|
||||
$result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
|
||||
return $result > $this->size ? $this->size : $result;
|
||||
return min($result, $this->size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-12
@@ -17,36 +17,30 @@ class BitMatrix
|
||||
{
|
||||
/**
|
||||
* Width of the bit matrix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $width;
|
||||
private int $width;
|
||||
|
||||
/**
|
||||
* Height of the bit matrix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $height;
|
||||
private ?int $height;
|
||||
|
||||
/**
|
||||
* Size in bits of each individual row.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $rowSize;
|
||||
private int $rowSize;
|
||||
|
||||
/**
|
||||
* Bits representation.
|
||||
*
|
||||
* @var SplFixedArray<int>
|
||||
*/
|
||||
private $bits;
|
||||
private SplFixedArray $bits;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if a dimension is smaller than zero
|
||||
*/
|
||||
public function __construct(int $width, int $height = null)
|
||||
public function __construct(int $width, ?int $height = null)
|
||||
{
|
||||
if (null === $height) {
|
||||
$height = $width;
|
||||
@@ -138,7 +132,7 @@ class BitMatrix
|
||||
/**
|
||||
* A fast method to retrieve one row of data from the matrix as a BitArray.
|
||||
*/
|
||||
public function getRow(int $y, BitArray $row = null) : BitArray
|
||||
public function getRow(int $y, ?BitArray $row = null) : BitArray
|
||||
{
|
||||
if (null === $row || $row->getSize() < $this->width) {
|
||||
$row = new BitArray($this->width);
|
||||
|
||||
+7
-10
@@ -69,29 +69,26 @@ final class CharacterSetEci extends AbstractEnum
|
||||
protected const GB18030 = [[29], 'GB2312', 'EUC_CN', 'GBK'];
|
||||
protected const EUC_KR = [[30], 'EUC-KR'];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
private $values;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $otherEncodingNames;
|
||||
private array $otherEncodingNames;
|
||||
|
||||
/**
|
||||
* @var array<int, self>|null
|
||||
*/
|
||||
private static $valueToEci;
|
||||
private static ?array $valueToEci;
|
||||
|
||||
/**
|
||||
* @var array<string, self>|null
|
||||
*/
|
||||
private static $nameToEci;
|
||||
private static ?array $nameToEci = null;
|
||||
|
||||
public function __construct(array $values, string ...$otherEncodingNames)
|
||||
/**
|
||||
* @param int[] $values
|
||||
*/
|
||||
public function __construct(private readonly array $values, string ...$otherEncodingNames)
|
||||
{
|
||||
$this->values = $values;
|
||||
$this->otherEncodingNames = $otherEncodingNames;
|
||||
}
|
||||
|
||||
|
||||
+1
-17
@@ -11,24 +11,8 @@ namespace BaconQrCode\Common;
|
||||
*/
|
||||
final class EcBlock
|
||||
{
|
||||
/**
|
||||
* How many times the block is used.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $count;
|
||||
|
||||
/**
|
||||
* Number of data codewords.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $dataCodewords;
|
||||
|
||||
public function __construct(int $count, int $dataCodewords)
|
||||
public function __construct(private readonly int $count, private readonly int $dataCodewords)
|
||||
{
|
||||
$this->count = $count;
|
||||
$this->dataCodewords = $dataCodewords;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-10
@@ -12,23 +12,15 @@ namespace BaconQrCode\Common;
|
||||
*/
|
||||
final class EcBlocks
|
||||
{
|
||||
/**
|
||||
* Number of EC codewords per block.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $ecCodewordsPerBlock;
|
||||
|
||||
/**
|
||||
* List of EC blocks.
|
||||
*
|
||||
* @var EcBlock[]
|
||||
*/
|
||||
private $ecBlocks;
|
||||
private array $ecBlocks;
|
||||
|
||||
public function __construct(int $ecCodewordsPerBlock, EcBlock ...$ecBlocks)
|
||||
public function __construct(private readonly int $ecCodewordsPerBlock, EcBlock ...$ecBlocks)
|
||||
{
|
||||
$this->ecCodewordsPerBlock = $ecCodewordsPerBlock;
|
||||
$this->ecBlocks = $ecBlocks;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,8 @@ final class ErrorCorrectionLevel extends AbstractEnum
|
||||
protected const Q = [0x03];
|
||||
protected const H = [0x02];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $bits;
|
||||
|
||||
protected function __construct(int $bits)
|
||||
protected function __construct(private readonly int $bits)
|
||||
{
|
||||
$this->bits = $bits;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,23 +62,16 @@ class FormatInformation
|
||||
/**
|
||||
* Offset i holds the number of 1 bits in the binary representation of i.
|
||||
*
|
||||
* @var array
|
||||
* @var int[]
|
||||
*/
|
||||
private const BITS_SET_IN_HALF_BYTE = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];
|
||||
|
||||
/**
|
||||
* Error correction level.
|
||||
*
|
||||
* @var ErrorCorrectionLevel
|
||||
*/
|
||||
private $ecLevel;
|
||||
private ErrorCorrectionLevel $ecLevel;
|
||||
|
||||
/**
|
||||
* Data mask.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $dataMask;
|
||||
private int $dataMask;
|
||||
|
||||
protected function __construct(int $formatInfo)
|
||||
{
|
||||
|
||||
+5
-12
@@ -33,19 +33,12 @@ final class Mode extends AbstractEnum
|
||||
protected const HANZI = [[8, 10, 12], 0x0d];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @param int[] $characterCountBitsForVersions
|
||||
*/
|
||||
private $characterCountBitsForVersions;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $bits;
|
||||
|
||||
protected function __construct(array $characterCountBitsForVersions, int $bits)
|
||||
{
|
||||
$this->characterCountBitsForVersions = $characterCountBitsForVersions;
|
||||
$this->bits = $bits;
|
||||
protected function __construct(
|
||||
private readonly array $characterCountBitsForVersions,
|
||||
private readonly int $bits
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+11
-25
@@ -16,73 +16,59 @@ final class ReedSolomonCodec
|
||||
{
|
||||
/**
|
||||
* Symbol size in bits.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $symbolSize;
|
||||
private int $symbolSize;
|
||||
|
||||
/**
|
||||
* Block size in symbols.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $blockSize;
|
||||
private int $blockSize;
|
||||
|
||||
/**
|
||||
* First root of RS code generator polynomial, index form.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $firstRoot;
|
||||
private int $firstRoot;
|
||||
|
||||
/**
|
||||
* Primitive element to generate polynomial roots, index form.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $primitive;
|
||||
private int $primitive;
|
||||
|
||||
/**
|
||||
* Prim-th root of 1, index form.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $iPrimitive;
|
||||
private int $iPrimitive;
|
||||
|
||||
/**
|
||||
* RS code generator polynomial degree (number of roots).
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $numRoots;
|
||||
private int $numRoots;
|
||||
|
||||
/**
|
||||
* Padding bytes at front of shortened block.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $padding;
|
||||
private int $padding;
|
||||
|
||||
/**
|
||||
* Log lookup table.
|
||||
*
|
||||
* @var SplFixedArray
|
||||
*/
|
||||
private $alphaTo;
|
||||
private SplFixedArray $alphaTo;
|
||||
|
||||
/**
|
||||
* Anti-Log lookup table.
|
||||
*
|
||||
* @var SplFixedArray
|
||||
*/
|
||||
private $indexOf;
|
||||
private SplFixedArray $indexOf;
|
||||
|
||||
/**
|
||||
* Generator polynomial.
|
||||
*
|
||||
* @var SplFixedArray
|
||||
*/
|
||||
private $generatorPoly;
|
||||
private SplFixedArray $generatorPoly;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if symbol size ist not between 0 and 8
|
||||
@@ -222,7 +208,7 @@ final class ReedSolomonCodec
|
||||
/**
|
||||
* Decodes received data.
|
||||
*/
|
||||
public function decode(SplFixedArray $data, SplFixedArray $erasures = null) : ?int
|
||||
public function decode(SplFixedArray $data, ?SplFixedArray $erasures = null) : ?int
|
||||
{
|
||||
// This speeds up the initialization a bit.
|
||||
$numRootsPlusOne = SplFixedArray::fromArray(array_fill(0, $this->numRoots + 1, 0), false);
|
||||
|
||||
+7
-11
@@ -50,38 +50,34 @@ final class Version
|
||||
|
||||
/**
|
||||
* Version number of this version.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $versionNumber;
|
||||
private int $versionNumber;
|
||||
|
||||
/**
|
||||
* Alignment pattern centers.
|
||||
*
|
||||
* @var SplFixedArray
|
||||
* @var SplFixedArray|array
|
||||
*/
|
||||
private $alignmentPatternCenters;
|
||||
private SplFixedArray|array $alignmentPatternCenters;
|
||||
|
||||
/**
|
||||
* Error correction blocks.
|
||||
*
|
||||
* @var EcBlocks[]
|
||||
*/
|
||||
private $ecBlocks;
|
||||
private array $ecBlocks;
|
||||
|
||||
/**
|
||||
* Total number of codewords.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $totalCodewords;
|
||||
private null|int|float $totalCodewords;
|
||||
|
||||
/**
|
||||
* Cached version instances.
|
||||
*
|
||||
* @var array<int, self>|null
|
||||
*/
|
||||
private static $versions;
|
||||
private static ?array $versions = null;
|
||||
|
||||
/**
|
||||
* @param int[] $alignmentPatternCenters
|
||||
@@ -300,7 +296,7 @@ final class Version
|
||||
[6, 26],
|
||||
new EcBlocks(20, new EcBlock(1, 80)),
|
||||
new EcBlocks(18, new EcBlock(2, 32)),
|
||||
new EcBlocks(26, new EcBlock(3, 24)),
|
||||
new EcBlocks(26, new EcBlock(2, 24)),
|
||||
new EcBlocks(16, new EcBlock(4, 9))
|
||||
),
|
||||
new self(
|
||||
|
||||
+6
-20
@@ -10,30 +10,16 @@ use SplFixedArray;
|
||||
*/
|
||||
final class BlockPair
|
||||
{
|
||||
/**
|
||||
* Data bytes in the block.
|
||||
*
|
||||
* @var SplFixedArray<int>
|
||||
*/
|
||||
private $dataBytes;
|
||||
|
||||
/**
|
||||
* Error correction bytes in the block.
|
||||
*
|
||||
* @var SplFixedArray<int>
|
||||
*/
|
||||
private $errorCorrectionBytes;
|
||||
|
||||
/**
|
||||
* Creates a new block pair.
|
||||
*
|
||||
* @param SplFixedArray<int> $data
|
||||
* @param SplFixedArray<int> $errorCorrection
|
||||
* @param SplFixedArray<int> $dataBytes Data bytes in the block.
|
||||
* @param SplFixedArray<int> $errorCorrectionBytes Error correction bytes in the block.
|
||||
*/
|
||||
public function __construct(SplFixedArray $data, SplFixedArray $errorCorrection)
|
||||
{
|
||||
$this->dataBytes = $data;
|
||||
$this->errorCorrectionBytes = $errorCorrection;
|
||||
public function __construct(
|
||||
private readonly SplFixedArray $dataBytes,
|
||||
private readonly SplFixedArray $errorCorrectionBytes
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-18
@@ -16,26 +16,10 @@ final class ByteMatrix
|
||||
*
|
||||
* @var SplFixedArray<SplFixedArray<int>>
|
||||
*/
|
||||
private $bytes;
|
||||
private SplFixedArray $bytes;
|
||||
|
||||
/**
|
||||
* Width of the matrix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $width;
|
||||
|
||||
/**
|
||||
* Height of the matrix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $height;
|
||||
|
||||
public function __construct(int $width, int $height)
|
||||
public function __construct(private readonly int $width, private readonly int $height)
|
||||
{
|
||||
$this->height = $height;
|
||||
$this->width = $width;
|
||||
$this->bytes = new SplFixedArray($height);
|
||||
|
||||
for ($y = 0; $y < $height; ++$y) {
|
||||
|
||||
+23
-12
@@ -20,7 +20,10 @@ final class Encoder
|
||||
/**
|
||||
* Default byte encoding.
|
||||
*/
|
||||
public const DEFAULT_BYTE_MODE_ECODING = 'ISO-8859-1';
|
||||
public const DEFAULT_BYTE_MODE_ENCODING = 'ISO-8859-1';
|
||||
|
||||
/** @deprecated use DEFAULT_BYTE_MODE_ENCODING */
|
||||
public const DEFAULT_BYTE_MODE_ECODING = self::DEFAULT_BYTE_MODE_ENCODING;
|
||||
|
||||
/**
|
||||
* The original table is defined in the table 5 of JISX0510:2004 (p.19).
|
||||
@@ -37,9 +40,9 @@ final class Encoder
|
||||
/**
|
||||
* Codec cache.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string,ReedSolomonCodec>
|
||||
*/
|
||||
private static $codecs = [];
|
||||
private static array $codecs = [];
|
||||
|
||||
/**
|
||||
* Encodes "content" with the error correction level "ecLevel".
|
||||
@@ -47,8 +50,10 @@ final class Encoder
|
||||
public static function encode(
|
||||
string $content,
|
||||
ErrorCorrectionLevel $ecLevel,
|
||||
string $encoding = self::DEFAULT_BYTE_MODE_ECODING,
|
||||
?Version $forcedVersion = null
|
||||
string $encoding = self::DEFAULT_BYTE_MODE_ENCODING,
|
||||
?Version $forcedVersion = null,
|
||||
// Barcode scanner might not be able to read the encoded message of the QR code with the prefix ECI of UTF-8
|
||||
bool $prefixEci = true
|
||||
) : QrCode {
|
||||
// Pick an encoding mode appropriate for the content. Note that this
|
||||
// will not attempt to use multiple modes / segments even if that were
|
||||
@@ -60,7 +65,7 @@ final class Encoder
|
||||
$headerBits = new BitArray();
|
||||
|
||||
// Append ECI segment if applicable
|
||||
if (Mode::BYTE() === $mode && self::DEFAULT_BYTE_MODE_ECODING !== $encoding) {
|
||||
if ($prefixEci && Mode::BYTE() === $mode && self::DEFAULT_BYTE_MODE_ENCODING !== $encoding) {
|
||||
$eci = CharacterSetEci::getCharacterSetEciByName($encoding);
|
||||
|
||||
if (null !== $eci) {
|
||||
@@ -155,7 +160,7 @@ final class Encoder
|
||||
/**
|
||||
* Chooses the best mode for a given content.
|
||||
*/
|
||||
private static function chooseMode(string $content, string $encoding = null) : Mode
|
||||
private static function chooseMode(string $content, ?string $encoding = null) : Mode
|
||||
{
|
||||
if (null !== $encoding && 0 === strcasecmp($encoding, 'SHIFT-JIS')) {
|
||||
return self::isOnlyDoubleByteKanji($content) ? Mode::KANJI() : Mode::BYTE();
|
||||
@@ -217,7 +222,7 @@ final class Encoder
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $length; $i += 2) {
|
||||
$byte = $bytes[$i] & 0xff;
|
||||
$byte = ord($bytes[$i]) & 0xff;
|
||||
|
||||
if (($byte < 0x81 || $byte > 0x9f) && $byte < 0xe0 || $byte > 0xeb) {
|
||||
return false;
|
||||
@@ -629,17 +634,23 @@ final class Encoder
|
||||
*/
|
||||
private static function appendKanjiBytes(string $content, BitArray $bits) : void
|
||||
{
|
||||
if (strlen($content) % 2 > 0) {
|
||||
$bytes = @iconv('utf-8', 'SHIFT-JIS', $content);
|
||||
|
||||
if (false === $bytes) {
|
||||
throw new WriterException('Content could not be converted to SHIFT-JIS');
|
||||
}
|
||||
|
||||
if (strlen($bytes) % 2 > 0) {
|
||||
// We just do a simple length check here. The for loop will check
|
||||
// individual characters.
|
||||
throw new WriterException('Content does not seem to be encoded in SHIFT-JIS');
|
||||
}
|
||||
|
||||
$length = strlen($content);
|
||||
$length = strlen($bytes);
|
||||
|
||||
for ($i = 0; $i < $length; $i += 2) {
|
||||
$byte1 = ord($content[$i]) & 0xff;
|
||||
$byte2 = ord($content[$i + 1]) & 0xff;
|
||||
$byte1 = ord($bytes[$i]) & 0xff;
|
||||
$byte2 = ord($bytes[$i + 1]) & 0xff;
|
||||
$code = ($byte1 << 8) | $byte2;
|
||||
|
||||
if ($code >= 0x8140 && $code <= 0x9ffc) {
|
||||
|
||||
+4
-4
@@ -14,10 +14,10 @@ final class MaskUtil
|
||||
/**#@+
|
||||
* Penalty weights from section 6.8.2.1
|
||||
*/
|
||||
const N1 = 3;
|
||||
const N2 = 3;
|
||||
const N3 = 40;
|
||||
const N4 = 10;
|
||||
public const N1 = 3;
|
||||
public const N2 = 3;
|
||||
public const N3 = 40;
|
||||
public const N4 = 10;
|
||||
/**#@-*/
|
||||
|
||||
private function __construct()
|
||||
|
||||
+8
-41
@@ -17,51 +17,23 @@ final class QrCode
|
||||
*/
|
||||
public const NUM_MASK_PATTERNS = 8;
|
||||
|
||||
/**
|
||||
* Mode of the QR code.
|
||||
*
|
||||
* @var Mode
|
||||
*/
|
||||
private $mode;
|
||||
|
||||
/**
|
||||
* EC level of the QR code.
|
||||
*
|
||||
* @var ErrorCorrectionLevel
|
||||
*/
|
||||
private $errorCorrectionLevel;
|
||||
|
||||
/**
|
||||
* Version of the QR code.
|
||||
*
|
||||
* @var Version
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* Mask pattern of the QR code.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maskPattern = -1;
|
||||
private int $maskPattern = -1;
|
||||
|
||||
/**
|
||||
* Matrix of the QR code.
|
||||
*
|
||||
* @var ByteMatrix
|
||||
*/
|
||||
private $matrix;
|
||||
private ByteMatrix $matrix;
|
||||
|
||||
public function __construct(
|
||||
Mode $mode,
|
||||
ErrorCorrectionLevel $errorCorrectionLevel,
|
||||
Version $version,
|
||||
int $maskPattern,
|
||||
ByteMatrix $matrix
|
||||
private readonly Mode $mode,
|
||||
private readonly ErrorCorrectionLevel $errorCorrectionLevel,
|
||||
private readonly Version $version,
|
||||
int $maskPattern,
|
||||
ByteMatrix $matrix
|
||||
) {
|
||||
$this->mode = $mode;
|
||||
$this->errorCorrectionLevel = $errorCorrectionLevel;
|
||||
$this->version = $version;
|
||||
$this->maskPattern = $maskPattern;
|
||||
$this->matrix = $matrix;
|
||||
}
|
||||
@@ -98,12 +70,7 @@ final class QrCode
|
||||
return $this->maskPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the matrix.
|
||||
*
|
||||
* @return ByteMatrix
|
||||
*/
|
||||
public function getMatrix()
|
||||
public function getMatrix(): ByteMatrix
|
||||
{
|
||||
return $this->matrix;
|
||||
}
|
||||
|
||||
+1
-14
@@ -7,27 +7,14 @@ use BaconQrCode\Exception;
|
||||
|
||||
final class Alpha implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $alpha;
|
||||
|
||||
/**
|
||||
* @var ColorInterface
|
||||
*/
|
||||
private $baseColor;
|
||||
|
||||
/**
|
||||
* @param int $alpha the alpha value, 0 to 100
|
||||
*/
|
||||
public function __construct(int $alpha, ColorInterface $baseColor)
|
||||
public function __construct(private readonly int $alpha, private readonly ColorInterface $baseColor)
|
||||
{
|
||||
if ($alpha < 0 || $alpha > 100) {
|
||||
throw new Exception\InvalidArgumentException('Alpha must be between 0 and 100');
|
||||
}
|
||||
|
||||
$this->alpha = $alpha;
|
||||
$this->baseColor = $baseColor;
|
||||
}
|
||||
|
||||
public function getAlpha() : int
|
||||
|
||||
+6
-27
@@ -7,34 +7,18 @@ use BaconQrCode\Exception;
|
||||
|
||||
final class Cmyk implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $cyan;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $magenta;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $yellow;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $black;
|
||||
|
||||
/**
|
||||
* @param int $cyan the cyan amount, 0 to 100
|
||||
* @param int $magenta the magenta amount, 0 to 100
|
||||
* @param int $yellow the yellow amount, 0 to 100
|
||||
* @param int $black the black amount, 0 to 100
|
||||
*/
|
||||
public function __construct(int $cyan, int $magenta, int $yellow, int $black)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly int $cyan,
|
||||
private readonly int $magenta,
|
||||
private readonly int $yellow,
|
||||
private readonly int $black
|
||||
) {
|
||||
if ($cyan < 0 || $cyan > 100) {
|
||||
throw new Exception\InvalidArgumentException('Cyan must be between 0 and 100');
|
||||
}
|
||||
@@ -50,11 +34,6 @@ final class Cmyk implements ColorInterface
|
||||
if ($black < 0 || $black > 100) {
|
||||
throw new Exception\InvalidArgumentException('Black must be between 0 and 100');
|
||||
}
|
||||
|
||||
$this->cyan = $cyan;
|
||||
$this->magenta = $magenta;
|
||||
$this->yellow = $yellow;
|
||||
$this->black = $black;
|
||||
}
|
||||
|
||||
public function getCyan() : int
|
||||
|
||||
@@ -7,21 +7,14 @@ use BaconQrCode\Exception;
|
||||
|
||||
final class Gray implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $gray;
|
||||
|
||||
/**
|
||||
* @param int $gray the gray value between 0 (black) and 100 (white)
|
||||
*/
|
||||
public function __construct(int $gray)
|
||||
public function __construct(private readonly int $gray)
|
||||
{
|
||||
if ($gray < 0 || $gray > 100) {
|
||||
throw new Exception\InvalidArgumentException('Gray must be between 0 and 100');
|
||||
}
|
||||
|
||||
$this->gray = (int) $gray;
|
||||
}
|
||||
|
||||
public function getGray() : int
|
||||
|
||||
+5
-20
@@ -7,27 +7,12 @@ use BaconQrCode\Exception;
|
||||
|
||||
final class Rgb implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $red;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $green;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $blue;
|
||||
|
||||
/**
|
||||
* @param int $red the red amount of the color, 0 to 255
|
||||
* @param int $green the green amount of the color, 0 to 255
|
||||
* @param int $blue the blue amount of the color, 0 to 255
|
||||
*/
|
||||
public function __construct(int $red, int $green, int $blue)
|
||||
public function __construct(private readonly int $red, private readonly int $green, private readonly int $blue)
|
||||
{
|
||||
if ($red < 0 || $red > 255) {
|
||||
throw new Exception\InvalidArgumentException('Red must be between 0 and 255');
|
||||
@@ -40,10 +25,6 @@ final class Rgb implements ColorInterface
|
||||
if ($blue < 0 || $blue > 255) {
|
||||
throw new Exception\InvalidArgumentException('Blue must be between 0 and 255');
|
||||
}
|
||||
|
||||
$this->red = $red;
|
||||
$this->green = $green;
|
||||
$this->blue = $blue;
|
||||
}
|
||||
|
||||
public function getRed() : int
|
||||
@@ -73,6 +54,10 @@ final class Rgb implements ColorInterface
|
||||
$y = 1 - ($this->blue / 255);
|
||||
$k = min($c, $m, $y);
|
||||
|
||||
if ($k === 0) {
|
||||
return new Cmyk(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return new Cmyk(
|
||||
(int) (100 * ($c - $k) / (1 - $k)),
|
||||
(int) (100 * ($m - $k) / (1 - $k)),
|
||||
|
||||
@@ -10,20 +10,8 @@ use BaconQrCode\Renderer\Path\Path;
|
||||
*/
|
||||
final class CompositeEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var EyeInterface
|
||||
*/
|
||||
private $externalEye;
|
||||
|
||||
/**
|
||||
* @var EyeInterface
|
||||
*/
|
||||
private $internalEye;
|
||||
|
||||
public function __construct(EyeInterface $externalEye, EyeInterface $internalEye)
|
||||
public function __construct(private readonly EyeInterface $externalEye, private readonly EyeInterface $internalEye)
|
||||
{
|
||||
$this->externalEye = $externalEye;
|
||||
$this->internalEye = $internalEye;
|
||||
}
|
||||
|
||||
public function getExternalPath() : Path
|
||||
|
||||
@@ -12,14 +12,8 @@ use BaconQrCode\Renderer\Path\Path;
|
||||
*/
|
||||
final class ModuleEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var ModuleInterface
|
||||
*/
|
||||
private $module;
|
||||
|
||||
public function __construct(ModuleInterface $module)
|
||||
public function __construct(private readonly ModuleInterface $module)
|
||||
{
|
||||
$this->module = $module;
|
||||
}
|
||||
|
||||
public function getExternalPath() : Path
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Eye;
|
||||
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Renders the outer eye as solid with a curved corner and inner eye as a circle.
|
||||
*/
|
||||
final class PointyEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function instance() : self
|
||||
{
|
||||
return self::$instance ?: self::$instance = new self();
|
||||
}
|
||||
|
||||
public function getExternalPath() : Path
|
||||
{
|
||||
return (new Path())
|
||||
->move(-3.5, 3.5)
|
||||
->line(-3.5, 0)
|
||||
->ellipticArc(3.5, 3.5, 0, false, true, 0, -3.5)
|
||||
->line(3.5, -3.5)
|
||||
->line(3.5, 3.5)
|
||||
->close()
|
||||
->move(2.5, 0)
|
||||
->ellipticArc(2.5, 2.5, 0, false, true, 0, 2.5)
|
||||
->ellipticArc(2.5, 2.5, 0, false, true, -2.5, 0)
|
||||
->ellipticArc(2.5, 2.5, 0, false, true, 0, -2.5)
|
||||
->ellipticArc(2.5, 2.5, 0, false, true, 2.5, 0)
|
||||
->close()
|
||||
;
|
||||
}
|
||||
|
||||
public function getInternalPath() : Path
|
||||
{
|
||||
return (new Path())
|
||||
->move(1.5, 0)
|
||||
->ellipticArc(1.5, 1.5, 0., false, true, 0., 1.5)
|
||||
->ellipticArc(1.5, 1.5, 0., false, true, -1.5, 0.)
|
||||
->ellipticArc(1.5, 1.5, 0., false, true, 0., -1.5)
|
||||
->ellipticArc(1.5, 1.5, 0., false, true, 1.5, 0.)
|
||||
->close()
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,7 @@ use BaconQrCode\Renderer\Path\Path;
|
||||
*/
|
||||
final class SimpleCircleEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
private static ?SimpleCircleEye $instance = null;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
|
||||
@@ -10,10 +10,7 @@ use BaconQrCode\Renderer\Path\Path;
|
||||
*/
|
||||
final class SquareEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
private static ?SquareEye $instance = null;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BaconQrCode\Renderer;
|
||||
|
||||
use BaconQrCode\Encoder\ByteMatrix;
|
||||
use BaconQrCode\Encoder\MatrixUtil;
|
||||
use BaconQrCode\Encoder\QrCode;
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use BaconQrCode\Renderer\Color\Alpha;
|
||||
use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
use BaconQrCode\Renderer\RendererStyle\EyeFill;
|
||||
use BaconQrCode\Renderer\RendererStyle\Fill;
|
||||
use GdImage;
|
||||
|
||||
final class GDLibRenderer implements RendererInterface
|
||||
{
|
||||
private ?GdImage $image;
|
||||
|
||||
/**
|
||||
* @var array<string, int>
|
||||
*/
|
||||
private array $colors;
|
||||
|
||||
public function __construct(
|
||||
private int $size,
|
||||
private int $margin = 4,
|
||||
private string $imageFormat = 'png',
|
||||
private int $compressionQuality = 9,
|
||||
private ?Fill $fill = null
|
||||
) {
|
||||
if (! extension_loaded('gd') || ! function_exists('gd_info')) {
|
||||
throw new RuntimeException('You need to install the GD extension to use this back end');
|
||||
}
|
||||
|
||||
if ($this->fill === null) {
|
||||
$this->fill = Fill::default();
|
||||
}
|
||||
if ($this->fill->hasGradientFill()) {
|
||||
throw new InvalidArgumentException('GDLibRenderer does not support gradients');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if matrix width doesn't match height
|
||||
*/
|
||||
public function render(QrCode $qrCode): string
|
||||
{
|
||||
$matrix = $qrCode->getMatrix();
|
||||
$matrixSize = $matrix->getWidth();
|
||||
|
||||
if ($matrixSize !== $matrix->getHeight()) {
|
||||
throw new InvalidArgumentException('Matrix must have the same width and height');
|
||||
}
|
||||
|
||||
MatrixUtil::removePositionDetectionPatterns($matrix);
|
||||
$this->newImage();
|
||||
$this->draw($matrix);
|
||||
|
||||
return $this->renderImage();
|
||||
}
|
||||
|
||||
private function newImage(): void
|
||||
{
|
||||
$img = imagecreatetruecolor($this->size, $this->size);
|
||||
if ($img === false) {
|
||||
throw new RuntimeException('Failed to create image of that size');
|
||||
}
|
||||
|
||||
$this->image = $img;
|
||||
imagealphablending($this->image, false);
|
||||
imagesavealpha($this->image, true);
|
||||
|
||||
|
||||
$bg = $this->getColor($this->fill->getBackgroundColor());
|
||||
imagefilledrectangle($this->image, 0, 0, $this->size, $this->size, $bg);
|
||||
imagealphablending($this->image, true);
|
||||
}
|
||||
|
||||
private function draw(ByteMatrix $matrix): void
|
||||
{
|
||||
$matrixSize = $matrix->getWidth();
|
||||
|
||||
$pointsOnSide = $matrix->getWidth() + $this->margin * 2;
|
||||
$pointInPx = $this->size / $pointsOnSide;
|
||||
|
||||
$this->drawEye(0, 0, $pointInPx, $this->fill->getTopLeftEyeFill());
|
||||
$this->drawEye($matrixSize - 7, 0, $pointInPx, $this->fill->getTopRightEyeFill());
|
||||
$this->drawEye(0, $matrixSize - 7, $pointInPx, $this->fill->getBottomLeftEyeFill());
|
||||
|
||||
$rows = $matrix->getArray()->toArray();
|
||||
$color = $this->getColor($this->fill->getForegroundColor());
|
||||
for ($y = 0; $y < $matrixSize; $y += 1) {
|
||||
for ($x = 0; $x < $matrixSize; $x += 1) {
|
||||
if (! $rows[$y][$x]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$points = $this->normalizePoints([
|
||||
($this->margin + $x) * $pointInPx, ($this->margin + $y) * $pointInPx,
|
||||
($this->margin + $x + 1) * $pointInPx, ($this->margin + $y) * $pointInPx,
|
||||
($this->margin + $x + 1) * $pointInPx, ($this->margin + $y + 1) * $pointInPx,
|
||||
($this->margin + $x) * $pointInPx, ($this->margin + $y + 1) * $pointInPx,
|
||||
]);
|
||||
imagefilledpolygon($this->image, $points, $color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function drawEye(int $xOffset, int $yOffset, float $pointInPx, EyeFill $eyeFill): void
|
||||
{
|
||||
$internalColor = $this->getColor($eyeFill->inheritsInternalColor()
|
||||
? $this->fill->getForegroundColor()
|
||||
: $eyeFill->getInternalColor());
|
||||
|
||||
$externalColor = $this->getColor($eyeFill->inheritsExternalColor()
|
||||
? $this->fill->getForegroundColor()
|
||||
: $eyeFill->getExternalColor());
|
||||
|
||||
for ($y = 0; $y < 7; $y += 1) {
|
||||
for ($x = 0; $x < 7; $x += 1) {
|
||||
if ((($y === 1 || $y === 5) && $x > 0 && $x < 6) || (($x === 1 || $x === 5) && $y > 0 && $y < 6)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$points = $this->normalizePoints([
|
||||
($this->margin + $x + $xOffset) * $pointInPx, ($this->margin + $y + $yOffset) * $pointInPx,
|
||||
($this->margin + $x + $xOffset + 1) * $pointInPx, ($this->margin + $y + $yOffset) * $pointInPx,
|
||||
($this->margin + $x + $xOffset + 1) * $pointInPx, ($this->margin + $y + $yOffset + 1) * $pointInPx,
|
||||
($this->margin + $x + $xOffset) * $pointInPx, ($this->margin + $y + $yOffset + 1) * $pointInPx,
|
||||
]);
|
||||
|
||||
if ($y > 1 && $y < 5 && $x > 1 && $x < 5) {
|
||||
imagefilledpolygon($this->image, $points, $internalColor);
|
||||
} else {
|
||||
imagefilledpolygon($this->image, $points, $externalColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize points will trim right and bottom line by 1 pixel.
|
||||
* Otherwise pixels of neighbors are overlapping which leads to issue with transparency and small QR codes.
|
||||
*/
|
||||
private function normalizePoints(array $points): array
|
||||
{
|
||||
$maxX = $maxY = 0;
|
||||
for ($i = 0; $i < count($points); $i += 2) {
|
||||
// Do manual round as GD just removes decimal part
|
||||
$points[$i] = $newX = round($points[$i]);
|
||||
$points[$i + 1] = $newY = round($points[$i + 1]);
|
||||
|
||||
$maxX = max($maxX, $newX);
|
||||
$maxY = max($maxY, $newY);
|
||||
}
|
||||
|
||||
// Do trimming only if there are 4 points (8 coordinates), assumes this is square.
|
||||
|
||||
for ($i = 0; $i < count($points); $i += 2) {
|
||||
$points[$i] = min($points[$i], $maxX - 1);
|
||||
$points[$i + 1] = min($points[$i + 1], $maxY - 1);
|
||||
}
|
||||
|
||||
return $points;
|
||||
}
|
||||
|
||||
private function renderImage(): string
|
||||
{
|
||||
ob_start();
|
||||
$quality = $this->compressionQuality;
|
||||
switch ($this->imageFormat) {
|
||||
case 'png':
|
||||
if ($quality > 9 || $quality < 0) {
|
||||
$quality = 9;
|
||||
}
|
||||
imagepng($this->image, null, $quality);
|
||||
break;
|
||||
|
||||
case 'gif':
|
||||
imagegif($this->image, null);
|
||||
break;
|
||||
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
if ($quality > 100 || $quality < 0) {
|
||||
$quality = 85;
|
||||
}
|
||||
imagejpeg($this->image, null, $quality);
|
||||
break;
|
||||
default:
|
||||
ob_end_clean();
|
||||
throw new InvalidArgumentException(
|
||||
'Supported image formats are jpeg, png and gif, got: ' . $this->imageFormat
|
||||
);
|
||||
}
|
||||
|
||||
imagedestroy($this->image);
|
||||
$this->colors = [];
|
||||
$this->image = null;
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
private function getColor(ColorInterface $color): int
|
||||
{
|
||||
$alpha = 100;
|
||||
|
||||
if ($color instanceof Alpha) {
|
||||
$alpha = $color->getAlpha();
|
||||
$color = $color->getBaseColor();
|
||||
}
|
||||
|
||||
$rgb = $color->toRgb();
|
||||
|
||||
$colorKey = sprintf('%02X%02X%02X%02X', $rgb->getRed(), $rgb->getGreen(), $rgb->getBlue(), $alpha);
|
||||
|
||||
if (! isset($this->colors[$colorKey])) {
|
||||
$colorId = imagecolorallocatealpha(
|
||||
$this->image,
|
||||
$rgb->getRed(),
|
||||
$rgb->getGreen(),
|
||||
$rgb->getBlue(),
|
||||
(int)((100 - $alpha) / 100 * 127) // Alpha for GD is in range 0 (opaque) - 127 (transparent)
|
||||
);
|
||||
|
||||
if ($colorId === false) {
|
||||
throw new RuntimeException('Failed to create color: #' . $colorKey);
|
||||
}
|
||||
|
||||
$this->colors[$colorKey] = $colorId;
|
||||
}
|
||||
|
||||
return $this->colors[$colorKey];
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,7 @@ final class EpsImageBackEnd implements ImageBackEndInterface
|
||||
{
|
||||
private const PRECISION = 3;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $eps;
|
||||
private ?string $eps;
|
||||
|
||||
public function new(int $size, ColorInterface $backgroundColor) : void
|
||||
{
|
||||
|
||||
@@ -23,40 +23,22 @@ use ImagickPixel;
|
||||
|
||||
final class ImagickImageBackEnd implements ImageBackEndInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $imageFormat;
|
||||
private string $imageFormat;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $compressionQuality;
|
||||
private int $compressionQuality;
|
||||
|
||||
/**
|
||||
* @var Imagick|null
|
||||
*/
|
||||
private $image;
|
||||
private ?Imagick $image;
|
||||
|
||||
/**
|
||||
* @var ImagickDraw|null
|
||||
*/
|
||||
private $draw;
|
||||
private ?ImagickDraw $draw;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $gradientCount;
|
||||
private ?int $gradientCount;
|
||||
|
||||
/**
|
||||
* @var TransformationMatrix[]|null
|
||||
*/
|
||||
private $matrices;
|
||||
private ?array $matrices;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $matrixIndex;
|
||||
private ?int $matrixIndex;
|
||||
|
||||
public function __construct(string $imageFormat = 'png', int $compressionQuality = 100)
|
||||
{
|
||||
|
||||
@@ -19,28 +19,16 @@ use XMLWriter;
|
||||
final class SvgImageBackEnd implements ImageBackEndInterface
|
||||
{
|
||||
private const PRECISION = 3;
|
||||
private const SCALE_FORMAT = 'scale(%.' . self::PRECISION . 'F)';
|
||||
private const TRANSLATE_FORMAT = 'translate(%.' . self::PRECISION . 'F,%.' . self::PRECISION . 'F)';
|
||||
private const SCALE_FORMAT = 'scale(%.' . self::PRECISION . 'F)';
|
||||
private const TRANSLATE_FORMAT = 'translate(%.' . self::PRECISION . 'F,%.' . self::PRECISION . 'F)';
|
||||
|
||||
/**
|
||||
* @var XMLWriter|null
|
||||
*/
|
||||
private $xmlWriter;
|
||||
private ?XMLWriter $xmlWriter;
|
||||
|
||||
/**
|
||||
* @var int[]|null
|
||||
*/
|
||||
private $stack;
|
||||
private ?array $stack;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $currentStack;
|
||||
private ?int $currentStack;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $gradientCount;
|
||||
private ?int $gradientCount;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -99,7 +87,7 @@ final class SvgImageBackEnd implements ImageBackEndInterface
|
||||
$this->xmlWriter->startElement('g');
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'transform',
|
||||
sprintf(self::SCALE_FORMAT, round($size, self::PRECISION))
|
||||
sprintf(self::SCALE_FORMAT, round($size, self::PRECISION))
|
||||
);
|
||||
++$this->stack[$this->currentStack];
|
||||
}
|
||||
@@ -113,7 +101,7 @@ final class SvgImageBackEnd implements ImageBackEndInterface
|
||||
$this->xmlWriter->startElement('g');
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'transform',
|
||||
sprintf(self::TRANSLATE_FORMAT, round($x, self::PRECISION), round($y, self::PRECISION))
|
||||
sprintf(self::TRANSLATE_FORMAT, round($x, self::PRECISION), round($y, self::PRECISION))
|
||||
);
|
||||
++$this->stack[$this->currentStack];
|
||||
}
|
||||
@@ -336,7 +324,7 @@ final class SvgImageBackEnd implements ImageBackEndInterface
|
||||
$this->xmlWriter->writeAttribute('stop-color', $this->getColorString($startColor));
|
||||
|
||||
if ($startColor instanceof Alpha) {
|
||||
$this->xmlWriter->writeAttribute('stop-opacity', $startColor->getAlpha());
|
||||
$this->xmlWriter->writeAttribute('stop-opacity', (string) $startColor->getAlpha());
|
||||
}
|
||||
|
||||
$this->xmlWriter->endElement();
|
||||
@@ -346,7 +334,7 @@ final class SvgImageBackEnd implements ImageBackEndInterface
|
||||
$this->xmlWriter->writeAttribute('stop-color', $this->getColorString($endColor));
|
||||
|
||||
if ($endColor instanceof Alpha) {
|
||||
$this->xmlWriter->writeAttribute('stop-opacity', $endColor->getAlpha());
|
||||
$this->xmlWriter->writeAttribute('stop-opacity', (string) $endColor->getAlpha());
|
||||
}
|
||||
|
||||
$this->xmlWriter->endElement();
|
||||
|
||||
@@ -8,7 +8,7 @@ final class TransformationMatrix
|
||||
/**
|
||||
* @var float[]
|
||||
*/
|
||||
private $values;
|
||||
private array $values;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
+16
-18
@@ -13,20 +13,10 @@ use BaconQrCode\Renderer\RendererStyle\RendererStyle;
|
||||
|
||||
final class ImageRenderer implements RendererInterface
|
||||
{
|
||||
/**
|
||||
* @var RendererStyle
|
||||
*/
|
||||
private $rendererStyle;
|
||||
|
||||
/**
|
||||
* @var ImageBackEndInterface
|
||||
*/
|
||||
private $imageBackEnd;
|
||||
|
||||
public function __construct(RendererStyle $rendererStyle, ImageBackEndInterface $imageBackEnd)
|
||||
{
|
||||
$this->rendererStyle = $rendererStyle;
|
||||
$this->imageBackEnd = $imageBackEnd;
|
||||
public function __construct(
|
||||
private readonly RendererStyle $rendererStyle,
|
||||
private readonly ImageBackEndInterface $imageBackEnd
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,8 +112,12 @@ final class ImageRenderer implements RendererInterface
|
||||
) : Path {
|
||||
if ($fill->inheritsBothColors()) {
|
||||
return $modulePath
|
||||
->append($externalPath->translate($xTranslation, $yTranslation))
|
||||
->append($internalPath->translate($xTranslation, $yTranslation));
|
||||
->append(
|
||||
$externalPath->rotate($rotation)->translate($xTranslation, $yTranslation)
|
||||
)
|
||||
->append(
|
||||
$internalPath->rotate($rotation)->translate($xTranslation, $yTranslation)
|
||||
);
|
||||
}
|
||||
|
||||
$this->imageBackEnd->push();
|
||||
@@ -134,13 +128,17 @@ final class ImageRenderer implements RendererInterface
|
||||
}
|
||||
|
||||
if ($fill->inheritsExternalColor()) {
|
||||
$modulePath = $modulePath->append($externalPath->translate($xTranslation, $yTranslation));
|
||||
$modulePath = $modulePath->append(
|
||||
$externalPath->rotate($rotation)->translate($xTranslation, $yTranslation)
|
||||
);
|
||||
} else {
|
||||
$this->imageBackEnd->drawPathWithColor($externalPath, $fill->getExternalColor());
|
||||
}
|
||||
|
||||
if ($fill->inheritsInternalColor()) {
|
||||
$modulePath = $modulePath->append($internalPath->translate($xTranslation, $yTranslation));
|
||||
$modulePath = $modulePath->append(
|
||||
$internalPath->rotate($rotation)->translate($xTranslation, $yTranslation)
|
||||
);
|
||||
} else {
|
||||
$this->imageBackEnd->drawPathWithColor($internalPath, $fill->getInternalColor());
|
||||
}
|
||||
|
||||
@@ -16,18 +16,11 @@ final class DotsModule implements ModuleInterface
|
||||
public const MEDIUM = .8;
|
||||
public const SMALL = .6;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $size;
|
||||
|
||||
public function __construct(float $size)
|
||||
public function __construct(private readonly float $size)
|
||||
{
|
||||
if ($size <= 0 || $size > 1) {
|
||||
throw new InvalidArgumentException('Size must between 0 (exclusive) and 1 (inclusive)');
|
||||
}
|
||||
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
public function createPath(ByteMatrix $matrix) : Path
|
||||
|
||||
@@ -5,44 +5,26 @@ namespace BaconQrCode\Renderer\Module\EdgeIterator;
|
||||
|
||||
final class Edge
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $positive;
|
||||
|
||||
/**
|
||||
* @var array<int[]>
|
||||
*/
|
||||
private $points = [];
|
||||
private array $points = [];
|
||||
|
||||
/**
|
||||
* @var array<int[]>|null
|
||||
*/
|
||||
private $simplifiedPoints;
|
||||
private ?array $simplifiedPoints = null;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $minX = PHP_INT_MAX;
|
||||
private int $minX = PHP_INT_MAX;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $minY = PHP_INT_MAX;
|
||||
private int $minY = PHP_INT_MAX;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $maxX = -1;
|
||||
private int $maxX = -1;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $maxY = -1;
|
||||
private int $maxY = -1;
|
||||
|
||||
public function __construct(bool $positive)
|
||||
public function __construct(private readonly bool $positive)
|
||||
{
|
||||
$this->positive = $positive;
|
||||
}
|
||||
|
||||
public function addPoint(int $x, int $y) : void
|
||||
|
||||
+5
-14
@@ -15,22 +15,13 @@ final class EdgeIterator implements IteratorAggregate
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
private $bytes = [];
|
||||
private array $bytes = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $size;
|
||||
private ?int $size;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $width;
|
||||
private int $width;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $height;
|
||||
private int $height;
|
||||
|
||||
public function __construct(ByteMatrix $matrix)
|
||||
{
|
||||
@@ -41,7 +32,7 @@ final class EdgeIterator implements IteratorAggregate
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Edge[]
|
||||
* @return Traversable<Edge>
|
||||
*/
|
||||
public function getIterator() : Traversable
|
||||
{
|
||||
|
||||
@@ -17,12 +17,7 @@ final class RoundnessModule implements ModuleInterface
|
||||
public const MEDIUM = .5;
|
||||
public const SOFT = .25;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $intensity;
|
||||
|
||||
public function __construct(float $intensity)
|
||||
public function __construct(private float $intensity)
|
||||
{
|
||||
if ($intensity <= 0 || $intensity > 1) {
|
||||
throw new InvalidArgumentException('Intensity must between 0 (exclusive) and 1 (inclusive)');
|
||||
|
||||
@@ -12,10 +12,7 @@ use BaconQrCode\Renderer\Path\Path;
|
||||
*/
|
||||
final class SquareModule implements ModuleInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
private static ?SquareModule $instance = null;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
|
||||
@@ -5,10 +5,7 @@ namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class Close implements OperationInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
private static ?Close $instance = null;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
@@ -26,4 +23,12 @@ final class Close implements OperationInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function rotate(int $degrees) : OperationInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
+32
-38
@@ -5,44 +5,14 @@ namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class Curve implements OperationInterface
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x1;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y1;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x2;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y2;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x3;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y3;
|
||||
|
||||
public function __construct(float $x1, float $y1, float $x2, float $y2, float $x3, float $y3)
|
||||
{
|
||||
$this->x1 = $x1;
|
||||
$this->y1 = $y1;
|
||||
$this->x2 = $x2;
|
||||
$this->y2 = $y2;
|
||||
$this->x3 = $x3;
|
||||
$this->y3 = $y3;
|
||||
public function __construct(
|
||||
private readonly float $x1,
|
||||
private readonly float $y1,
|
||||
private readonly float $x2,
|
||||
private readonly float $y2,
|
||||
private readonly float $x3,
|
||||
private readonly float $y3
|
||||
) {
|
||||
}
|
||||
|
||||
public function getX1() : float
|
||||
@@ -89,4 +59,28 @@ final class Curve implements OperationInterface
|
||||
$this->y3 + $y
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function rotate(int $degrees) : OperationInterface
|
||||
{
|
||||
$radians = deg2rad($degrees);
|
||||
$sin = sin($radians);
|
||||
$cos = cos($radians);
|
||||
$x1r = $this->x1 * $cos - $this->y1 * $sin;
|
||||
$y1r = $this->x1 * $sin + $this->y1 * $cos;
|
||||
$x2r = $this->x2 * $cos - $this->y2 * $sin;
|
||||
$y2r = $this->x2 * $sin + $this->y2 * $cos;
|
||||
$x3r = $this->x3 * $cos - $this->y3 * $sin;
|
||||
$y3r = $this->x3 * $sin + $this->y3 * $cos;
|
||||
return new self(
|
||||
$x1r,
|
||||
$y1r,
|
||||
$x2r,
|
||||
$y2r,
|
||||
$x3r,
|
||||
$y3r
|
||||
);
|
||||
}
|
||||
}
|
||||
+33
-47
@@ -7,57 +7,22 @@ final class EllipticArc implements OperationInterface
|
||||
{
|
||||
private const ZERO_TOLERANCE = 1e-05;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $xRadius;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $yRadius;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $xAxisAngle;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $largeArc;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $sweep;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y;
|
||||
private float $xRadius;
|
||||
private float $yRadius;
|
||||
private float $xAxisAngle;
|
||||
|
||||
public function __construct(
|
||||
float $xRadius,
|
||||
float $yRadius,
|
||||
float $xAxisAngle,
|
||||
bool $largeArc,
|
||||
bool $sweep,
|
||||
float $x,
|
||||
float $y
|
||||
float $xRadius,
|
||||
float $yRadius,
|
||||
float $xAxisAngle,
|
||||
private readonly bool $largeArc,
|
||||
private readonly bool $sweep,
|
||||
private readonly float $x,
|
||||
private readonly float $y
|
||||
) {
|
||||
$this->xRadius = abs($xRadius);
|
||||
$this->yRadius = abs($yRadius);
|
||||
$this->xAxisAngle = $xAxisAngle % 360;
|
||||
$this->largeArc = $largeArc;
|
||||
$this->sweep = $sweep;
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
}
|
||||
|
||||
public function getXRadius() : float
|
||||
@@ -111,6 +76,27 @@ final class EllipticArc implements OperationInterface
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function rotate(int $degrees) : OperationInterface
|
||||
{
|
||||
$radians = deg2rad($degrees);
|
||||
$sin = sin($radians);
|
||||
$cos = cos($radians);
|
||||
$xr = $this->x * $cos - $this->y * $sin;
|
||||
$yr = $this->x * $sin + $this->y * $cos;
|
||||
return new self(
|
||||
$this->xRadius,
|
||||
$this->yRadius,
|
||||
$this->xAxisAngle,
|
||||
$this->largeArc,
|
||||
$this->sweep,
|
||||
$xr,
|
||||
$yr
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the elliptic arc to multiple curves.
|
||||
*
|
||||
@@ -136,7 +122,7 @@ final class EllipticArc implements OperationInterface
|
||||
/**
|
||||
* @return Curve[]
|
||||
*/
|
||||
private function createCurves(float $fromX, $fromY) : array
|
||||
private function createCurves(float $fromX, float $fromY) : array
|
||||
{
|
||||
$xAngle = deg2rad($this->xAxisAngle);
|
||||
list($centerX, $centerY, $radiusX, $radiusY, $startAngle, $deltaAngle) =
|
||||
@@ -179,7 +165,7 @@ final class EllipticArc implements OperationInterface
|
||||
/**
|
||||
* @return float[]
|
||||
*/
|
||||
private function calculateCenterPointParameters(float $fromX, float $fromY, float $xAngle)
|
||||
private function calculateCenterPointParameters(float $fromX, float $fromY, float $xAngle): array
|
||||
{
|
||||
$rX = $this->xRadius;
|
||||
$rY = $this->yRadius;
|
||||
|
||||
+14
-13
@@ -5,20 +5,8 @@ namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class Line implements OperationInterface
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y;
|
||||
|
||||
public function __construct(float $x, float $y)
|
||||
public function __construct(private readonly float $x, private readonly float $y)
|
||||
{
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
}
|
||||
|
||||
public function getX() : float
|
||||
@@ -38,4 +26,17 @@ final class Line implements OperationInterface
|
||||
{
|
||||
return new self($this->x + $x, $this->y + $y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function rotate(int $degrees) : OperationInterface
|
||||
{
|
||||
$radians = deg2rad($degrees);
|
||||
$sin = sin($radians);
|
||||
$cos = cos($radians);
|
||||
$xr = $this->x * $cos - $this->y * $sin;
|
||||
$yr = $this->x * $sin + $this->y * $cos;
|
||||
return new self($xr, $yr);
|
||||
}
|
||||
}
|
||||
+14
-13
@@ -5,20 +5,8 @@ namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class Move implements OperationInterface
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y;
|
||||
|
||||
public function __construct(float $x, float $y)
|
||||
public function __construct(private readonly float $x, private readonly float $y)
|
||||
{
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
}
|
||||
|
||||
public function getX() : float
|
||||
@@ -38,4 +26,17 @@ final class Move implements OperationInterface
|
||||
{
|
||||
return new self($this->x + $x, $this->y + $y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function rotate(int $degrees) : OperationInterface
|
||||
{
|
||||
$radians = deg2rad($degrees);
|
||||
$sin = sin($radians);
|
||||
$cos = cos($radians);
|
||||
$xr = $this->x * $cos - $this->y * $sin;
|
||||
$yr = $this->x * $sin + $this->y * $cos;
|
||||
return new self($xr, $yr);
|
||||
}
|
||||
}
|
||||
@@ -9,4 +9,9 @@ interface OperationInterface
|
||||
* Translates the operation's coordinates.
|
||||
*/
|
||||
public function translate(float $x, float $y) : self;
|
||||
|
||||
/**
|
||||
* Rotates the operation's coordinates.
|
||||
*/
|
||||
public function rotate(int $degrees) : self;
|
||||
}
|
||||
+13
-2
@@ -14,7 +14,7 @@ final class Path implements IteratorAggregate
|
||||
/**
|
||||
* @var OperationInterface[]
|
||||
*/
|
||||
private $operations = [];
|
||||
private array $operations = [];
|
||||
|
||||
/**
|
||||
* Moves the drawing operation to a certain position.
|
||||
@@ -94,8 +94,19 @@ final class Path implements IteratorAggregate
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function rotate(int $degrees) : self
|
||||
{
|
||||
$path = new self();
|
||||
|
||||
foreach ($this->operations as $operation) {
|
||||
$path->operations[] = $operation->rotate($degrees);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OperationInterface[]|Traversable
|
||||
* @return Traversable<int, OperationInterface>
|
||||
*/
|
||||
public function getIterator() : Traversable
|
||||
{
|
||||
|
||||
@@ -28,14 +28,8 @@ final class PlainTextRenderer implements RendererInterface
|
||||
*/
|
||||
private const EMPTY_BLOCK = "\xc2\xa0";
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $margin;
|
||||
|
||||
public function __construct(int $margin = 2)
|
||||
public function __construct(private readonly int $margin = 2)
|
||||
{
|
||||
$this->margin = $margin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,25 +8,12 @@ use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
|
||||
final class EyeFill
|
||||
{
|
||||
/**
|
||||
* @var ColorInterface|null
|
||||
*/
|
||||
private $externalColor;
|
||||
private static ?EyeFill $inherit = null;
|
||||
|
||||
/**
|
||||
* @var ColorInterface|null
|
||||
*/
|
||||
private $internalColor;
|
||||
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $inherit;
|
||||
|
||||
public function __construct(?ColorInterface $externalColor, ?ColorInterface $internalColor)
|
||||
{
|
||||
$this->externalColor = $externalColor;
|
||||
$this->internalColor = $internalColor;
|
||||
public function __construct(
|
||||
private readonly ?ColorInterface $externalColor,
|
||||
private readonly ?ColorInterface $internalColor
|
||||
) {
|
||||
}
|
||||
|
||||
public static function uniform(ColorInterface $color) : self
|
||||
|
||||
@@ -9,55 +9,16 @@ use BaconQrCode\Renderer\Color\Gray;
|
||||
|
||||
final class Fill
|
||||
{
|
||||
/**
|
||||
* @var ColorInterface
|
||||
*/
|
||||
private $backgroundColor;
|
||||
|
||||
/**
|
||||
* @var ColorInterface|null
|
||||
*/
|
||||
private $foregroundColor;
|
||||
|
||||
/**
|
||||
* @var Gradient|null
|
||||
*/
|
||||
private $foregroundGradient;
|
||||
|
||||
/**
|
||||
* @var EyeFill
|
||||
*/
|
||||
private $topLeftEyeFill;
|
||||
|
||||
/**
|
||||
* @var EyeFill
|
||||
*/
|
||||
private $topRightEyeFill;
|
||||
|
||||
/**
|
||||
* @var EyeFill
|
||||
*/
|
||||
private $bottomLeftEyeFill;
|
||||
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $default;
|
||||
private static ?Fill $default = null;
|
||||
|
||||
private function __construct(
|
||||
ColorInterface $backgroundColor,
|
||||
?ColorInterface $foregroundColor,
|
||||
?Gradient $foregroundGradient,
|
||||
EyeFill $topLeftEyeFill,
|
||||
EyeFill $topRightEyeFill,
|
||||
EyeFill $bottomLeftEyeFill
|
||||
private readonly ColorInterface $backgroundColor,
|
||||
private readonly ?ColorInterface $foregroundColor,
|
||||
private readonly ?Gradient $foregroundGradient,
|
||||
private readonly EyeFill $topLeftEyeFill,
|
||||
private readonly EyeFill $topRightEyeFill,
|
||||
private readonly EyeFill $bottomLeftEyeFill
|
||||
) {
|
||||
$this->backgroundColor = $backgroundColor;
|
||||
$this->foregroundColor = $foregroundColor;
|
||||
$this->foregroundGradient = $foregroundGradient;
|
||||
$this->topLeftEyeFill = $topLeftEyeFill;
|
||||
$this->topRightEyeFill = $topRightEyeFill;
|
||||
$this->bottomLeftEyeFill = $bottomLeftEyeFill;
|
||||
}
|
||||
|
||||
public static function default() : self
|
||||
|
||||
@@ -7,26 +7,11 @@ use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
|
||||
final class Gradient
|
||||
{
|
||||
/**
|
||||
* @var ColorInterface
|
||||
*/
|
||||
private $startColor;
|
||||
|
||||
/**
|
||||
* @var ColorInterface
|
||||
*/
|
||||
private $endColor;
|
||||
|
||||
/**
|
||||
* @var GradientType
|
||||
*/
|
||||
private $type;
|
||||
|
||||
public function __construct(ColorInterface $startColor, ColorInterface $endColor, GradientType $type)
|
||||
{
|
||||
$this->startColor = $startColor;
|
||||
$this->endColor = $endColor;
|
||||
$this->type = $type;
|
||||
public function __construct(
|
||||
private readonly ColorInterface $startColor,
|
||||
private readonly ColorInterface $endColor,
|
||||
private readonly GradientType $type
|
||||
) {
|
||||
}
|
||||
|
||||
public function getStartColor() : ColorInterface
|
||||
|
||||
@@ -10,40 +10,19 @@ use BaconQrCode\Renderer\Module\SquareModule;
|
||||
|
||||
final class RendererStyle
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $size;
|
||||
private ModuleInterface $module;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $margin;
|
||||
private EyeInterface|null $eye;
|
||||
|
||||
/**
|
||||
* @var ModuleInterface
|
||||
*/
|
||||
private $module;
|
||||
|
||||
/**
|
||||
* @var EyeInterface|null
|
||||
*/
|
||||
private $eye;
|
||||
|
||||
/**
|
||||
* @var Fill
|
||||
*/
|
||||
private $fill;
|
||||
private Fill $fill;
|
||||
|
||||
public function __construct(
|
||||
int $size,
|
||||
int $margin = 4,
|
||||
private int $size,
|
||||
private int $margin = 4,
|
||||
?ModuleInterface $module = null,
|
||||
?EyeInterface $eye = null,
|
||||
?Fill $fill = null
|
||||
) {
|
||||
$this->margin = $margin;
|
||||
$this->size = $size;
|
||||
$this->module = $module ?: SquareModule::instance();
|
||||
$this->eye = $eye ?: new ModuleEye($this->module);
|
||||
$this->fill = $fill ?: Fill::default();
|
||||
|
||||
+3
-11
@@ -14,19 +14,11 @@ use BaconQrCode\Renderer\RendererInterface;
|
||||
*/
|
||||
final class Writer
|
||||
{
|
||||
/**
|
||||
* Renderer instance.
|
||||
*
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
|
||||
/**
|
||||
* Creates a new writer with a specific renderer.
|
||||
*/
|
||||
public function __construct(RendererInterface $renderer)
|
||||
public function __construct(private readonly RendererInterface $renderer)
|
||||
{
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +31,7 @@ final class Writer
|
||||
*/
|
||||
public function writeString(
|
||||
string $content,
|
||||
string $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING,
|
||||
string $encoding = Encoder::DEFAULT_BYTE_MODE_ENCODING,
|
||||
?ErrorCorrectionLevel $ecLevel = null,
|
||||
?Version $forcedVersion = null
|
||||
) : string {
|
||||
@@ -62,7 +54,7 @@ final class Writer
|
||||
public function writeFile(
|
||||
string $content,
|
||||
string $filename,
|
||||
string $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING,
|
||||
string $encoding = Encoder::DEFAULT_BYTE_MODE_ENCODING,
|
||||
?ErrorCorrectionLevel $ecLevel = null,
|
||||
?Version $forcedVersion = null
|
||||
) : void {
|
||||
|
||||
Vendored
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+11
-11
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a stub include that automatically configures the include path.
|
||||
*/
|
||||
|
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||
require_once 'HTMLPurifier/Bootstrap.php';
|
||||
require_once 'HTMLPurifier.autoload.php';
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a stub include that automatically configures the include path.
|
||||
*/
|
||||
|
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||
require_once 'HTMLPurifier/Bootstrap.php';
|
||||
require_once 'HTMLPurifier.autoload.php';
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+14
-14
@@ -1,14 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Legacy autoloader for systems lacking spl_autoload_register
|
||||
*
|
||||
*/
|
||||
|
||||
spl_autoload_register(function($class)
|
||||
{
|
||||
return HTMLPurifier_Bootstrap::autoload($class);
|
||||
});
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Legacy autoloader for systems lacking spl_autoload_register
|
||||
*
|
||||
*/
|
||||
|
||||
spl_autoload_register(function($class)
|
||||
{
|
||||
return HTMLPurifier_Bootstrap::autoload($class);
|
||||
});
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+25
-25
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Convenience file that registers autoload handler for HTML Purifier.
|
||||
* It also does some sanity checks.
|
||||
*/
|
||||
|
||||
if (function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) {
|
||||
// We need unregister for our pre-registering functionality
|
||||
HTMLPurifier_Bootstrap::registerAutoload();
|
||||
if (function_exists('__autoload')) {
|
||||
// Be polite and ensure that userland autoload gets retained
|
||||
spl_autoload_register('__autoload');
|
||||
}
|
||||
} elseif (!function_exists('__autoload')) {
|
||||
require dirname(__FILE__) . '/HTMLPurifier.autoload-legacy.php';
|
||||
}
|
||||
|
||||
// phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.zend_ze1_compatibility_modeRemoved
|
||||
if (ini_get('zend.ze1_compatibility_mode')) {
|
||||
trigger_error("HTML Purifier is not compatible with zend.ze1_compatibility_mode; please turn it off", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Convenience file that registers autoload handler for HTML Purifier.
|
||||
* It also does some sanity checks.
|
||||
*/
|
||||
|
||||
if (function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) {
|
||||
// We need unregister for our pre-registering functionality
|
||||
HTMLPurifier_Bootstrap::registerAutoload();
|
||||
if (function_exists('__autoload')) {
|
||||
// Be polite and ensure that userland autoload gets retained
|
||||
spl_autoload_register('__autoload');
|
||||
}
|
||||
} elseif (!function_exists('__autoload')) {
|
||||
require dirname(__FILE__) . '/HTMLPurifier.autoload-legacy.php';
|
||||
}
|
||||
|
||||
// phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.zend_ze1_compatibility_modeRemoved
|
||||
if (ini_get('zend.ze1_compatibility_mode')) {
|
||||
trigger_error("HTML Purifier is not compatible with zend.ze1_compatibility_mode; please turn it off", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
if (!defined('HTMLPURIFIER_PREFIX')) {
|
||||
define('HTMLPURIFIER_PREFIX', dirname(__FILE__));
|
||||
}
|
||||
<?php
|
||||
if (!defined('HTMLPURIFIER_PREFIX')) {
|
||||
define('HTMLPURIFIER_PREFIX', dirname(__FILE__));
|
||||
}
|
||||
+25
-25
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines a function wrapper for HTML Purifier for quick use.
|
||||
* @note ''HTMLPurifier()'' is NOT the same as ''new HTMLPurifier()''
|
||||
*/
|
||||
|
||||
/**
|
||||
* Purify HTML.
|
||||
* @param string $html String HTML to purify
|
||||
* @param mixed $config Configuration to use, can be any value accepted by
|
||||
* HTMLPurifier_Config::create()
|
||||
* @return string
|
||||
*/
|
||||
function HTMLPurifier($html, $config = null)
|
||||
{
|
||||
static $purifier = false;
|
||||
if (!$purifier) {
|
||||
$purifier = new HTMLPurifier();
|
||||
}
|
||||
return $purifier->purify($html, $config);
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines a function wrapper for HTML Purifier for quick use.
|
||||
* @note ''HTMLPurifier()'' is NOT the same as ''new HTMLPurifier()''
|
||||
*/
|
||||
|
||||
/**
|
||||
* Purify HTML.
|
||||
* @param string $html String HTML to purify
|
||||
* @param mixed $config Configuration to use, can be any value accepted by
|
||||
* HTMLPurifier_Config::create()
|
||||
* @return string
|
||||
*/
|
||||
function HTMLPurifier($html, $config = null)
|
||||
{
|
||||
static $purifier = false;
|
||||
if (!$purifier) {
|
||||
$purifier = new HTMLPurifier();
|
||||
}
|
||||
return $purifier->purify($html, $config);
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+235
-236
@@ -1,236 +1,235 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file was auto-generated by generate-includes.php and includes all of
|
||||
* the core files required by HTML Purifier. Use this if performance is a
|
||||
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
|
||||
* FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* @version 4.18.0
|
||||
*
|
||||
* @warning
|
||||
* You must *not* include any other HTML Purifier files before this file,
|
||||
* because 'require' not 'require_once' is used.
|
||||
*
|
||||
* @warning
|
||||
* This file requires that the include path contains the HTML Purifier
|
||||
* library directory; this is not auto-set.
|
||||
*/
|
||||
|
||||
require 'HTMLPurifier.php';
|
||||
require 'HTMLPurifier/Arborize.php';
|
||||
require 'HTMLPurifier/AttrCollections.php';
|
||||
require 'HTMLPurifier/AttrDef.php';
|
||||
require 'HTMLPurifier/AttrTransform.php';
|
||||
require 'HTMLPurifier/AttrTypes.php';
|
||||
require 'HTMLPurifier/AttrValidator.php';
|
||||
require 'HTMLPurifier/Bootstrap.php';
|
||||
require 'HTMLPurifier/Definition.php';
|
||||
require 'HTMLPurifier/CSSDefinition.php';
|
||||
require 'HTMLPurifier/ChildDef.php';
|
||||
require 'HTMLPurifier/Config.php';
|
||||
require 'HTMLPurifier/ConfigSchema.php';
|
||||
require 'HTMLPurifier/ContentSets.php';
|
||||
require 'HTMLPurifier/Context.php';
|
||||
require 'HTMLPurifier/DefinitionCache.php';
|
||||
require 'HTMLPurifier/DefinitionCacheFactory.php';
|
||||
require 'HTMLPurifier/Doctype.php';
|
||||
require 'HTMLPurifier/DoctypeRegistry.php';
|
||||
require 'HTMLPurifier/ElementDef.php';
|
||||
require 'HTMLPurifier/Encoder.php';
|
||||
require 'HTMLPurifier/EntityLookup.php';
|
||||
require 'HTMLPurifier/EntityParser.php';
|
||||
require 'HTMLPurifier/ErrorCollector.php';
|
||||
require 'HTMLPurifier/ErrorStruct.php';
|
||||
require 'HTMLPurifier/Exception.php';
|
||||
require 'HTMLPurifier/Filter.php';
|
||||
require 'HTMLPurifier/Generator.php';
|
||||
require 'HTMLPurifier/HTMLDefinition.php';
|
||||
require 'HTMLPurifier/HTMLModule.php';
|
||||
require 'HTMLPurifier/HTMLModuleManager.php';
|
||||
require 'HTMLPurifier/IDAccumulator.php';
|
||||
require 'HTMLPurifier/Injector.php';
|
||||
require 'HTMLPurifier/Language.php';
|
||||
require 'HTMLPurifier/LanguageFactory.php';
|
||||
require 'HTMLPurifier/Length.php';
|
||||
require 'HTMLPurifier/Lexer.php';
|
||||
require 'HTMLPurifier/Node.php';
|
||||
require 'HTMLPurifier/PercentEncoder.php';
|
||||
require 'HTMLPurifier/PropertyList.php';
|
||||
require 'HTMLPurifier/PropertyListIterator.php';
|
||||
require 'HTMLPurifier/Queue.php';
|
||||
require 'HTMLPurifier/Strategy.php';
|
||||
require 'HTMLPurifier/StringHash.php';
|
||||
require 'HTMLPurifier/StringHashParser.php';
|
||||
require 'HTMLPurifier/TagTransform.php';
|
||||
require 'HTMLPurifier/Token.php';
|
||||
require 'HTMLPurifier/TokenFactory.php';
|
||||
require 'HTMLPurifier/URI.php';
|
||||
require 'HTMLPurifier/URIDefinition.php';
|
||||
require 'HTMLPurifier/URIFilter.php';
|
||||
require 'HTMLPurifier/URIParser.php';
|
||||
require 'HTMLPurifier/URIScheme.php';
|
||||
require 'HTMLPurifier/URISchemeRegistry.php';
|
||||
require 'HTMLPurifier/UnitConverter.php';
|
||||
require 'HTMLPurifier/VarParser.php';
|
||||
require 'HTMLPurifier/VarParserException.php';
|
||||
require 'HTMLPurifier/Zipper.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS.php';
|
||||
require 'HTMLPurifier/AttrDef/Clone.php';
|
||||
require 'HTMLPurifier/AttrDef/Enum.php';
|
||||
require 'HTMLPurifier/AttrDef/Integer.php';
|
||||
require 'HTMLPurifier/AttrDef/Lang.php';
|
||||
require 'HTMLPurifier/AttrDef/Switch.php';
|
||||
require 'HTMLPurifier/AttrDef/Text.php';
|
||||
require 'HTMLPurifier/AttrDef/URI.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/AlphaValue.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Background.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Border.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Color.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Composite.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Font.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Ident.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Ratio.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/URI.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Class.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Color.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/ContentEditable.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/ID.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Length.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Email.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Host.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
|
||||
require 'HTMLPurifier/AttrTransform/Background.php';
|
||||
require 'HTMLPurifier/AttrTransform/BdoDir.php';
|
||||
require 'HTMLPurifier/AttrTransform/BgColor.php';
|
||||
require 'HTMLPurifier/AttrTransform/BoolToCSS.php';
|
||||
require 'HTMLPurifier/AttrTransform/Border.php';
|
||||
require 'HTMLPurifier/AttrTransform/EnumToCSS.php';
|
||||
require 'HTMLPurifier/AttrTransform/ImgRequired.php';
|
||||
require 'HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||
require 'HTMLPurifier/AttrTransform/Input.php';
|
||||
require 'HTMLPurifier/AttrTransform/Lang.php';
|
||||
require 'HTMLPurifier/AttrTransform/Length.php';
|
||||
require 'HTMLPurifier/AttrTransform/Name.php';
|
||||
require 'HTMLPurifier/AttrTransform/NameSync.php';
|
||||
require 'HTMLPurifier/AttrTransform/Nofollow.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeObject.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeParam.php';
|
||||
require 'HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetBlank.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetNoopener.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetNoreferrer.php';
|
||||
require 'HTMLPurifier/AttrTransform/Textarea.php';
|
||||
require 'HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require 'HTMLPurifier/ChildDef/Custom.php';
|
||||
require 'HTMLPurifier/ChildDef/Empty.php';
|
||||
require 'HTMLPurifier/ChildDef/List.php';
|
||||
require 'HTMLPurifier/ChildDef/Required.php';
|
||||
require 'HTMLPurifier/ChildDef/Optional.php';
|
||||
require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
require 'HTMLPurifier/ChildDef/Table.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Null.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Serializer.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator/Memory.php';
|
||||
require 'HTMLPurifier/HTMLModule/Bdo.php';
|
||||
require 'HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Edit.php';
|
||||
require 'HTMLPurifier/HTMLModule/Forms.php';
|
||||
require 'HTMLPurifier/HTMLModule/Hypertext.php';
|
||||
require 'HTMLPurifier/HTMLModule/Iframe.php';
|
||||
require 'HTMLPurifier/HTMLModule/Image.php';
|
||||
require 'HTMLPurifier/HTMLModule/Legacy.php';
|
||||
require 'HTMLPurifier/HTMLModule/List.php';
|
||||
require 'HTMLPurifier/HTMLModule/Name.php';
|
||||
require 'HTMLPurifier/HTMLModule/Nofollow.php';
|
||||
require 'HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Object.php';
|
||||
require 'HTMLPurifier/HTMLModule/Presentation.php';
|
||||
require 'HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require 'HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeObject.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeScripting.php';
|
||||
require 'HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tables.php';
|
||||
require 'HTMLPurifier/HTMLModule/Target.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetBlank.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetNoopener.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetNoreferrer.php';
|
||||
require 'HTMLPurifier/HTMLModule/Text.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy.php';
|
||||
require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Name.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Strict.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Transitional.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||
require 'HTMLPurifier/Injector/AutoParagraph.php';
|
||||
require 'HTMLPurifier/Injector/DisplayLinkURI.php';
|
||||
require 'HTMLPurifier/Injector/Linkify.php';
|
||||
require 'HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require 'HTMLPurifier/Injector/RemoveEmpty.php';
|
||||
require 'HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
|
||||
require 'HTMLPurifier/Injector/SafeObject.php';
|
||||
require 'HTMLPurifier/Lexer/DOMLex.php';
|
||||
require 'HTMLPurifier/Lexer/DirectLex.php';
|
||||
require 'HTMLPurifier/Node/Comment.php';
|
||||
require 'HTMLPurifier/Node/Element.php';
|
||||
require 'HTMLPurifier/Node/Text.php';
|
||||
require 'HTMLPurifier/Strategy/Composite.php';
|
||||
require 'HTMLPurifier/Strategy/Core.php';
|
||||
require 'HTMLPurifier/Strategy/FixNesting.php';
|
||||
require 'HTMLPurifier/Strategy/MakeWellFormed.php';
|
||||
require 'HTMLPurifier/Strategy/RemoveForeignElements.php';
|
||||
require 'HTMLPurifier/Strategy/ValidateAttributes.php';
|
||||
require 'HTMLPurifier/TagTransform/Font.php';
|
||||
require 'HTMLPurifier/TagTransform/Simple.php';
|
||||
require 'HTMLPurifier/Token/Comment.php';
|
||||
require 'HTMLPurifier/Token/Tag.php';
|
||||
require 'HTMLPurifier/Token/Empty.php';
|
||||
require 'HTMLPurifier/Token/End.php';
|
||||
require 'HTMLPurifier/Token/Start.php';
|
||||
require 'HTMLPurifier/Token/Text.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableResources.php';
|
||||
require 'HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require 'HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require 'HTMLPurifier/URIFilter/Munge.php';
|
||||
require 'HTMLPurifier/URIFilter/SafeIframe.php';
|
||||
require 'HTMLPurifier/URIScheme/data.php';
|
||||
require 'HTMLPurifier/URIScheme/file.php';
|
||||
require 'HTMLPurifier/URIScheme/ftp.php';
|
||||
require 'HTMLPurifier/URIScheme/http.php';
|
||||
require 'HTMLPurifier/URIScheme/https.php';
|
||||
require 'HTMLPurifier/URIScheme/mailto.php';
|
||||
require 'HTMLPurifier/URIScheme/news.php';
|
||||
require 'HTMLPurifier/URIScheme/nntp.php';
|
||||
require 'HTMLPurifier/URIScheme/tel.php';
|
||||
require 'HTMLPurifier/VarParser/Flexible.php';
|
||||
require 'HTMLPurifier/VarParser/Native.php';
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file was auto-generated by generate-includes.php and includes all of
|
||||
* the core files required by HTML Purifier. Use this if performance is a
|
||||
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
|
||||
* FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* @version 4.17.0
|
||||
*
|
||||
* @warning
|
||||
* You must *not* include any other HTML Purifier files before this file,
|
||||
* because 'require' not 'require_once' is used.
|
||||
*
|
||||
* @warning
|
||||
* This file requires that the include path contains the HTML Purifier
|
||||
* library directory; this is not auto-set.
|
||||
*/
|
||||
|
||||
require 'HTMLPurifier.php';
|
||||
require 'HTMLPurifier/Arborize.php';
|
||||
require 'HTMLPurifier/AttrCollections.php';
|
||||
require 'HTMLPurifier/AttrDef.php';
|
||||
require 'HTMLPurifier/AttrTransform.php';
|
||||
require 'HTMLPurifier/AttrTypes.php';
|
||||
require 'HTMLPurifier/AttrValidator.php';
|
||||
require 'HTMLPurifier/Bootstrap.php';
|
||||
require 'HTMLPurifier/Definition.php';
|
||||
require 'HTMLPurifier/CSSDefinition.php';
|
||||
require 'HTMLPurifier/ChildDef.php';
|
||||
require 'HTMLPurifier/Config.php';
|
||||
require 'HTMLPurifier/ConfigSchema.php';
|
||||
require 'HTMLPurifier/ContentSets.php';
|
||||
require 'HTMLPurifier/Context.php';
|
||||
require 'HTMLPurifier/DefinitionCache.php';
|
||||
require 'HTMLPurifier/DefinitionCacheFactory.php';
|
||||
require 'HTMLPurifier/Doctype.php';
|
||||
require 'HTMLPurifier/DoctypeRegistry.php';
|
||||
require 'HTMLPurifier/ElementDef.php';
|
||||
require 'HTMLPurifier/Encoder.php';
|
||||
require 'HTMLPurifier/EntityLookup.php';
|
||||
require 'HTMLPurifier/EntityParser.php';
|
||||
require 'HTMLPurifier/ErrorCollector.php';
|
||||
require 'HTMLPurifier/ErrorStruct.php';
|
||||
require 'HTMLPurifier/Exception.php';
|
||||
require 'HTMLPurifier/Filter.php';
|
||||
require 'HTMLPurifier/Generator.php';
|
||||
require 'HTMLPurifier/HTMLDefinition.php';
|
||||
require 'HTMLPurifier/HTMLModule.php';
|
||||
require 'HTMLPurifier/HTMLModuleManager.php';
|
||||
require 'HTMLPurifier/IDAccumulator.php';
|
||||
require 'HTMLPurifier/Injector.php';
|
||||
require 'HTMLPurifier/Language.php';
|
||||
require 'HTMLPurifier/LanguageFactory.php';
|
||||
require 'HTMLPurifier/Length.php';
|
||||
require 'HTMLPurifier/Lexer.php';
|
||||
require 'HTMLPurifier/Node.php';
|
||||
require 'HTMLPurifier/PercentEncoder.php';
|
||||
require 'HTMLPurifier/PropertyList.php';
|
||||
require 'HTMLPurifier/PropertyListIterator.php';
|
||||
require 'HTMLPurifier/Queue.php';
|
||||
require 'HTMLPurifier/Strategy.php';
|
||||
require 'HTMLPurifier/StringHash.php';
|
||||
require 'HTMLPurifier/StringHashParser.php';
|
||||
require 'HTMLPurifier/TagTransform.php';
|
||||
require 'HTMLPurifier/Token.php';
|
||||
require 'HTMLPurifier/TokenFactory.php';
|
||||
require 'HTMLPurifier/URI.php';
|
||||
require 'HTMLPurifier/URIDefinition.php';
|
||||
require 'HTMLPurifier/URIFilter.php';
|
||||
require 'HTMLPurifier/URIParser.php';
|
||||
require 'HTMLPurifier/URIScheme.php';
|
||||
require 'HTMLPurifier/URISchemeRegistry.php';
|
||||
require 'HTMLPurifier/UnitConverter.php';
|
||||
require 'HTMLPurifier/VarParser.php';
|
||||
require 'HTMLPurifier/VarParserException.php';
|
||||
require 'HTMLPurifier/Zipper.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS.php';
|
||||
require 'HTMLPurifier/AttrDef/Clone.php';
|
||||
require 'HTMLPurifier/AttrDef/Enum.php';
|
||||
require 'HTMLPurifier/AttrDef/Integer.php';
|
||||
require 'HTMLPurifier/AttrDef/Lang.php';
|
||||
require 'HTMLPurifier/AttrDef/Switch.php';
|
||||
require 'HTMLPurifier/AttrDef/Text.php';
|
||||
require 'HTMLPurifier/AttrDef/URI.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/AlphaValue.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Background.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Border.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Color.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Composite.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Font.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Ident.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/URI.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Class.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Color.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/ContentEditable.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/ID.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Length.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Email.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Host.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
|
||||
require 'HTMLPurifier/AttrTransform/Background.php';
|
||||
require 'HTMLPurifier/AttrTransform/BdoDir.php';
|
||||
require 'HTMLPurifier/AttrTransform/BgColor.php';
|
||||
require 'HTMLPurifier/AttrTransform/BoolToCSS.php';
|
||||
require 'HTMLPurifier/AttrTransform/Border.php';
|
||||
require 'HTMLPurifier/AttrTransform/EnumToCSS.php';
|
||||
require 'HTMLPurifier/AttrTransform/ImgRequired.php';
|
||||
require 'HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||
require 'HTMLPurifier/AttrTransform/Input.php';
|
||||
require 'HTMLPurifier/AttrTransform/Lang.php';
|
||||
require 'HTMLPurifier/AttrTransform/Length.php';
|
||||
require 'HTMLPurifier/AttrTransform/Name.php';
|
||||
require 'HTMLPurifier/AttrTransform/NameSync.php';
|
||||
require 'HTMLPurifier/AttrTransform/Nofollow.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeObject.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeParam.php';
|
||||
require 'HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetBlank.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetNoopener.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetNoreferrer.php';
|
||||
require 'HTMLPurifier/AttrTransform/Textarea.php';
|
||||
require 'HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require 'HTMLPurifier/ChildDef/Custom.php';
|
||||
require 'HTMLPurifier/ChildDef/Empty.php';
|
||||
require 'HTMLPurifier/ChildDef/List.php';
|
||||
require 'HTMLPurifier/ChildDef/Required.php';
|
||||
require 'HTMLPurifier/ChildDef/Optional.php';
|
||||
require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
require 'HTMLPurifier/ChildDef/Table.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Null.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Serializer.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator/Memory.php';
|
||||
require 'HTMLPurifier/HTMLModule/Bdo.php';
|
||||
require 'HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Edit.php';
|
||||
require 'HTMLPurifier/HTMLModule/Forms.php';
|
||||
require 'HTMLPurifier/HTMLModule/Hypertext.php';
|
||||
require 'HTMLPurifier/HTMLModule/Iframe.php';
|
||||
require 'HTMLPurifier/HTMLModule/Image.php';
|
||||
require 'HTMLPurifier/HTMLModule/Legacy.php';
|
||||
require 'HTMLPurifier/HTMLModule/List.php';
|
||||
require 'HTMLPurifier/HTMLModule/Name.php';
|
||||
require 'HTMLPurifier/HTMLModule/Nofollow.php';
|
||||
require 'HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Object.php';
|
||||
require 'HTMLPurifier/HTMLModule/Presentation.php';
|
||||
require 'HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require 'HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeObject.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeScripting.php';
|
||||
require 'HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tables.php';
|
||||
require 'HTMLPurifier/HTMLModule/Target.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetBlank.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetNoopener.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetNoreferrer.php';
|
||||
require 'HTMLPurifier/HTMLModule/Text.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy.php';
|
||||
require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Name.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Strict.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Transitional.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||
require 'HTMLPurifier/Injector/AutoParagraph.php';
|
||||
require 'HTMLPurifier/Injector/DisplayLinkURI.php';
|
||||
require 'HTMLPurifier/Injector/Linkify.php';
|
||||
require 'HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require 'HTMLPurifier/Injector/RemoveEmpty.php';
|
||||
require 'HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
|
||||
require 'HTMLPurifier/Injector/SafeObject.php';
|
||||
require 'HTMLPurifier/Lexer/DOMLex.php';
|
||||
require 'HTMLPurifier/Lexer/DirectLex.php';
|
||||
require 'HTMLPurifier/Node/Comment.php';
|
||||
require 'HTMLPurifier/Node/Element.php';
|
||||
require 'HTMLPurifier/Node/Text.php';
|
||||
require 'HTMLPurifier/Strategy/Composite.php';
|
||||
require 'HTMLPurifier/Strategy/Core.php';
|
||||
require 'HTMLPurifier/Strategy/FixNesting.php';
|
||||
require 'HTMLPurifier/Strategy/MakeWellFormed.php';
|
||||
require 'HTMLPurifier/Strategy/RemoveForeignElements.php';
|
||||
require 'HTMLPurifier/Strategy/ValidateAttributes.php';
|
||||
require 'HTMLPurifier/TagTransform/Font.php';
|
||||
require 'HTMLPurifier/TagTransform/Simple.php';
|
||||
require 'HTMLPurifier/Token/Comment.php';
|
||||
require 'HTMLPurifier/Token/Tag.php';
|
||||
require 'HTMLPurifier/Token/Empty.php';
|
||||
require 'HTMLPurifier/Token/End.php';
|
||||
require 'HTMLPurifier/Token/Start.php';
|
||||
require 'HTMLPurifier/Token/Text.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableResources.php';
|
||||
require 'HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require 'HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require 'HTMLPurifier/URIFilter/Munge.php';
|
||||
require 'HTMLPurifier/URIFilter/SafeIframe.php';
|
||||
require 'HTMLPurifier/URIScheme/data.php';
|
||||
require 'HTMLPurifier/URIScheme/file.php';
|
||||
require 'HTMLPurifier/URIScheme/ftp.php';
|
||||
require 'HTMLPurifier/URIScheme/http.php';
|
||||
require 'HTMLPurifier/URIScheme/https.php';
|
||||
require 'HTMLPurifier/URIScheme/mailto.php';
|
||||
require 'HTMLPurifier/URIScheme/news.php';
|
||||
require 'HTMLPurifier/URIScheme/nntp.php';
|
||||
require 'HTMLPurifier/URIScheme/tel.php';
|
||||
require 'HTMLPurifier/VarParser/Flexible.php';
|
||||
require 'HTMLPurifier/VarParser/Native.php';
|
||||
+30
-30
@@ -1,30 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Emulation layer for code that used kses(), substituting in HTML Purifier.
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . '/HTMLPurifier.auto.php';
|
||||
|
||||
function kses($string, $allowed_html, $allowed_protocols = null)
|
||||
{
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$allowed_elements = array();
|
||||
$allowed_attributes = array();
|
||||
foreach ($allowed_html as $element => $attributes) {
|
||||
$allowed_elements[$element] = true;
|
||||
foreach ($attributes as $attribute => $x) {
|
||||
$allowed_attributes["$element.$attribute"] = true;
|
||||
}
|
||||
}
|
||||
$config->set('HTML.AllowedElements', $allowed_elements);
|
||||
$config->set('HTML.AllowedAttributes', $allowed_attributes);
|
||||
if ($allowed_protocols !== null) {
|
||||
$config->set('URI.AllowedSchemes', $allowed_protocols);
|
||||
}
|
||||
$purifier = new HTMLPurifier($config);
|
||||
return $purifier->purify($string);
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Emulation layer for code that used kses(), substituting in HTML Purifier.
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . '/HTMLPurifier.auto.php';
|
||||
|
||||
function kses($string, $allowed_html, $allowed_protocols = null)
|
||||
{
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$allowed_elements = array();
|
||||
$allowed_attributes = array();
|
||||
foreach ($allowed_html as $element => $attributes) {
|
||||
$allowed_elements[$element] = true;
|
||||
foreach ($attributes as $attribute => $x) {
|
||||
$allowed_attributes["$element.$attribute"] = true;
|
||||
}
|
||||
}
|
||||
$config->set('HTML.AllowedElements', $allowed_elements);
|
||||
$config->set('HTML.AllowedAttributes', $allowed_attributes);
|
||||
if ($allowed_protocols !== null) {
|
||||
$config->set('URI.AllowedSchemes', $allowed_protocols);
|
||||
}
|
||||
$purifier = new HTMLPurifier($config);
|
||||
return $purifier->purify($string);
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+11
-11
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Convenience stub file that adds HTML Purifier's library file to the path
|
||||
* without any other side-effects.
|
||||
*/
|
||||
|
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Convenience stub file that adds HTML Purifier's library file to the path
|
||||
* without any other side-effects.
|
||||
*/
|
||||
|
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+297
-297
@@ -1,297 +1,297 @@
|
||||
<?php
|
||||
|
||||
/*! @mainpage
|
||||
*
|
||||
* HTML Purifier is an HTML filter that will take an arbitrary snippet of
|
||||
* HTML and rigorously test, validate and filter it into a version that
|
||||
* is safe for output onto webpages. It achieves this by:
|
||||
*
|
||||
* -# Lexing (parsing into tokens) the document,
|
||||
* -# Executing various strategies on the tokens:
|
||||
* -# Removing all elements not in the whitelist,
|
||||
* -# Making the tokens well-formed,
|
||||
* -# Fixing the nesting of the nodes, and
|
||||
* -# Validating attributes of the nodes; and
|
||||
* -# Generating HTML from the purified tokens.
|
||||
*
|
||||
* However, most users will only need to interface with the HTMLPurifier
|
||||
* and HTMLPurifier_Config.
|
||||
*/
|
||||
|
||||
/*
|
||||
HTML Purifier 4.18.0 - Standards Compliant HTML Filtering
|
||||
Copyright (C) 2006-2008 Edward Z. Yang
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Facade that coordinates HTML Purifier's subsystems in order to purify HTML.
|
||||
*
|
||||
* @note There are several points in which configuration can be specified
|
||||
* for HTML Purifier. The precedence of these (from lowest to
|
||||
* highest) is as follows:
|
||||
* -# Instance: new HTMLPurifier($config)
|
||||
* -# Invocation: purify($html, $config)
|
||||
* These configurations are entirely independent of each other and
|
||||
* are *not* merged (this behavior may change in the future).
|
||||
*
|
||||
* @todo We need an easier way to inject strategies using the configuration
|
||||
* object.
|
||||
*/
|
||||
class HTMLPurifier
|
||||
{
|
||||
|
||||
/**
|
||||
* Version of HTML Purifier.
|
||||
* @type string
|
||||
*/
|
||||
public $version = '4.18.0';
|
||||
|
||||
/**
|
||||
* Constant with version of HTML Purifier.
|
||||
*/
|
||||
const VERSION = '4.18.0';
|
||||
|
||||
/**
|
||||
* Global configuration object.
|
||||
* @type HTMLPurifier_Config
|
||||
*/
|
||||
public $config;
|
||||
|
||||
/**
|
||||
* Array of extra filter objects to run on HTML,
|
||||
* for backwards compatibility.
|
||||
* @type HTMLPurifier_Filter[]
|
||||
*/
|
||||
private $filters = array();
|
||||
|
||||
/**
|
||||
* Single instance of HTML Purifier.
|
||||
* @type HTMLPurifier
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Strategy_Core
|
||||
*/
|
||||
protected $strategy;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Generator
|
||||
*/
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* Resultant context of last run purification.
|
||||
* Is an array of contexts if the last called method was purifyArray().
|
||||
* @type HTMLPurifier_Context
|
||||
*/
|
||||
public $context;
|
||||
|
||||
/**
|
||||
* Initializes the purifier.
|
||||
*
|
||||
* @param HTMLPurifier_Config|mixed $config Optional HTMLPurifier_Config object
|
||||
* for all instances of the purifier, if omitted, a default
|
||||
* configuration is supplied (which can be overridden on a
|
||||
* per-use basis).
|
||||
* The parameter can also be any type that
|
||||
* HTMLPurifier_Config::create() supports.
|
||||
*/
|
||||
public function __construct($config = null)
|
||||
{
|
||||
$this->config = HTMLPurifier_Config::create($config);
|
||||
$this->strategy = new HTMLPurifier_Strategy_Core();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filter to process the output. First come first serve
|
||||
*
|
||||
* @param HTMLPurifier_Filter $filter HTMLPurifier_Filter object
|
||||
*/
|
||||
public function addFilter($filter)
|
||||
{
|
||||
trigger_error(
|
||||
'HTMLPurifier->addFilter() is deprecated, use configuration directives' .
|
||||
' in the Filter namespace or Filter.Custom',
|
||||
E_USER_WARNING
|
||||
);
|
||||
$this->filters[] = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an HTML snippet/document to be XSS-free and standards-compliant.
|
||||
*
|
||||
* @param string $html String of HTML to purify
|
||||
* @param HTMLPurifier_Config $config Config object for this operation,
|
||||
* if omitted, defaults to the config object specified during this
|
||||
* object's construction. The parameter can also be any type
|
||||
* that HTMLPurifier_Config::create() supports.
|
||||
*
|
||||
* @return string Purified HTML
|
||||
*/
|
||||
public function purify($html, $config = null)
|
||||
{
|
||||
// :TODO: make the config merge in, instead of replace
|
||||
$config = $config ? HTMLPurifier_Config::create($config) : $this->config;
|
||||
|
||||
// implementation is partially environment dependant, partially
|
||||
// configuration dependant
|
||||
$lexer = HTMLPurifier_Lexer::create($config);
|
||||
|
||||
$context = new HTMLPurifier_Context();
|
||||
|
||||
// setup HTML generator
|
||||
$this->generator = new HTMLPurifier_Generator($config, $context);
|
||||
$context->register('Generator', $this->generator);
|
||||
|
||||
// set up global context variables
|
||||
if ($config->get('Core.CollectErrors')) {
|
||||
// may get moved out if other facilities use it
|
||||
$language_factory = HTMLPurifier_LanguageFactory::instance();
|
||||
$language = $language_factory->create($config, $context);
|
||||
$context->register('Locale', $language);
|
||||
|
||||
$error_collector = new HTMLPurifier_ErrorCollector($context);
|
||||
$context->register('ErrorCollector', $error_collector);
|
||||
}
|
||||
|
||||
// setup id_accumulator context, necessary due to the fact that
|
||||
// AttrValidator can be called from many places
|
||||
$id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);
|
||||
$context->register('IDAccumulator', $id_accumulator);
|
||||
|
||||
$html = HTMLPurifier_Encoder::convertToUTF8($html, $config, $context);
|
||||
|
||||
// setup filters
|
||||
$filter_flags = $config->getBatch('Filter');
|
||||
$custom_filters = $filter_flags['Custom'];
|
||||
unset($filter_flags['Custom']);
|
||||
$filters = array();
|
||||
foreach ($filter_flags as $filter => $flag) {
|
||||
if (!$flag) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($filter, '.') !== false) {
|
||||
continue;
|
||||
}
|
||||
$class = "HTMLPurifier_Filter_$filter";
|
||||
$filters[] = new $class;
|
||||
}
|
||||
foreach ($custom_filters as $filter) {
|
||||
// maybe "HTMLPurifier_Filter_$filter", but be consistent with AutoFormat
|
||||
$filters[] = $filter;
|
||||
}
|
||||
$filters = array_merge($filters, $this->filters);
|
||||
// maybe prepare(), but later
|
||||
|
||||
for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) {
|
||||
$html = $filters[$i]->preFilter($html, $config, $context);
|
||||
}
|
||||
|
||||
// purified HTML
|
||||
$html =
|
||||
$this->generator->generateFromTokens(
|
||||
// list of tokens
|
||||
$this->strategy->execute(
|
||||
// list of un-purified tokens
|
||||
$lexer->tokenizeHTML(
|
||||
// un-purified HTML
|
||||
$html,
|
||||
$config,
|
||||
$context
|
||||
),
|
||||
$config,
|
||||
$context
|
||||
)
|
||||
);
|
||||
|
||||
for ($i = $filter_size - 1; $i >= 0; $i--) {
|
||||
$html = $filters[$i]->postFilter($html, $config, $context);
|
||||
}
|
||||
|
||||
$html = HTMLPurifier_Encoder::convertFromUTF8($html, $config, $context);
|
||||
$this->context =& $context;
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an array of HTML snippets
|
||||
*
|
||||
* @param string[] $array_of_html Array of html snippets
|
||||
* @param HTMLPurifier_Config $config Optional config object for this operation.
|
||||
* See HTMLPurifier::purify() for more details.
|
||||
*
|
||||
* @return string[] Array of purified HTML
|
||||
*/
|
||||
public function purifyArray($array_of_html, $config = null)
|
||||
{
|
||||
$context_array = array();
|
||||
$array = array();
|
||||
foreach($array_of_html as $key=>$value){
|
||||
if (is_array($value)) {
|
||||
$array[$key] = $this->purifyArray($value, $config);
|
||||
} else {
|
||||
$array[$key] = $this->purify($value, $config);
|
||||
}
|
||||
$context_array[$key] = $this->context;
|
||||
}
|
||||
$this->context = $context_array;
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton for enforcing just one HTML Purifier in your system
|
||||
*
|
||||
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
|
||||
* HTMLPurifier instance to overload singleton with,
|
||||
* or HTMLPurifier_Config instance to configure the
|
||||
* generated version with.
|
||||
*
|
||||
* @return HTMLPurifier
|
||||
*/
|
||||
public static function instance($prototype = null)
|
||||
{
|
||||
if (!self::$instance || $prototype) {
|
||||
if ($prototype instanceof HTMLPurifier) {
|
||||
self::$instance = $prototype;
|
||||
} elseif ($prototype) {
|
||||
self::$instance = new HTMLPurifier($prototype);
|
||||
} else {
|
||||
self::$instance = new HTMLPurifier();
|
||||
}
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton for enforcing just one HTML Purifier in your system
|
||||
*
|
||||
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
|
||||
* HTMLPurifier instance to overload singleton with,
|
||||
* or HTMLPurifier_Config instance to configure the
|
||||
* generated version with.
|
||||
*
|
||||
* @return HTMLPurifier
|
||||
* @note Backwards compatibility, see instance()
|
||||
*/
|
||||
public static function getInstance($prototype = null)
|
||||
{
|
||||
return HTMLPurifier::instance($prototype);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/*! @mainpage
|
||||
*
|
||||
* HTML Purifier is an HTML filter that will take an arbitrary snippet of
|
||||
* HTML and rigorously test, validate and filter it into a version that
|
||||
* is safe for output onto webpages. It achieves this by:
|
||||
*
|
||||
* -# Lexing (parsing into tokens) the document,
|
||||
* -# Executing various strategies on the tokens:
|
||||
* -# Removing all elements not in the whitelist,
|
||||
* -# Making the tokens well-formed,
|
||||
* -# Fixing the nesting of the nodes, and
|
||||
* -# Validating attributes of the nodes; and
|
||||
* -# Generating HTML from the purified tokens.
|
||||
*
|
||||
* However, most users will only need to interface with the HTMLPurifier
|
||||
* and HTMLPurifier_Config.
|
||||
*/
|
||||
|
||||
/*
|
||||
HTML Purifier 4.17.0 - Standards Compliant HTML Filtering
|
||||
Copyright (C) 2006-2008 Edward Z. Yang
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Facade that coordinates HTML Purifier's subsystems in order to purify HTML.
|
||||
*
|
||||
* @note There are several points in which configuration can be specified
|
||||
* for HTML Purifier. The precedence of these (from lowest to
|
||||
* highest) is as follows:
|
||||
* -# Instance: new HTMLPurifier($config)
|
||||
* -# Invocation: purify($html, $config)
|
||||
* These configurations are entirely independent of each other and
|
||||
* are *not* merged (this behavior may change in the future).
|
||||
*
|
||||
* @todo We need an easier way to inject strategies using the configuration
|
||||
* object.
|
||||
*/
|
||||
class HTMLPurifier
|
||||
{
|
||||
|
||||
/**
|
||||
* Version of HTML Purifier.
|
||||
* @type string
|
||||
*/
|
||||
public $version = '4.17.0';
|
||||
|
||||
/**
|
||||
* Constant with version of HTML Purifier.
|
||||
*/
|
||||
const VERSION = '4.17.0';
|
||||
|
||||
/**
|
||||
* Global configuration object.
|
||||
* @type HTMLPurifier_Config
|
||||
*/
|
||||
public $config;
|
||||
|
||||
/**
|
||||
* Array of extra filter objects to run on HTML,
|
||||
* for backwards compatibility.
|
||||
* @type HTMLPurifier_Filter[]
|
||||
*/
|
||||
private $filters = array();
|
||||
|
||||
/**
|
||||
* Single instance of HTML Purifier.
|
||||
* @type HTMLPurifier
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Strategy_Core
|
||||
*/
|
||||
protected $strategy;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Generator
|
||||
*/
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* Resultant context of last run purification.
|
||||
* Is an array of contexts if the last called method was purifyArray().
|
||||
* @type HTMLPurifier_Context
|
||||
*/
|
||||
public $context;
|
||||
|
||||
/**
|
||||
* Initializes the purifier.
|
||||
*
|
||||
* @param HTMLPurifier_Config|mixed $config Optional HTMLPurifier_Config object
|
||||
* for all instances of the purifier, if omitted, a default
|
||||
* configuration is supplied (which can be overridden on a
|
||||
* per-use basis).
|
||||
* The parameter can also be any type that
|
||||
* HTMLPurifier_Config::create() supports.
|
||||
*/
|
||||
public function __construct($config = null)
|
||||
{
|
||||
$this->config = HTMLPurifier_Config::create($config);
|
||||
$this->strategy = new HTMLPurifier_Strategy_Core();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filter to process the output. First come first serve
|
||||
*
|
||||
* @param HTMLPurifier_Filter $filter HTMLPurifier_Filter object
|
||||
*/
|
||||
public function addFilter($filter)
|
||||
{
|
||||
trigger_error(
|
||||
'HTMLPurifier->addFilter() is deprecated, use configuration directives' .
|
||||
' in the Filter namespace or Filter.Custom',
|
||||
E_USER_WARNING
|
||||
);
|
||||
$this->filters[] = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an HTML snippet/document to be XSS-free and standards-compliant.
|
||||
*
|
||||
* @param string $html String of HTML to purify
|
||||
* @param HTMLPurifier_Config $config Config object for this operation,
|
||||
* if omitted, defaults to the config object specified during this
|
||||
* object's construction. The parameter can also be any type
|
||||
* that HTMLPurifier_Config::create() supports.
|
||||
*
|
||||
* @return string Purified HTML
|
||||
*/
|
||||
public function purify($html, $config = null)
|
||||
{
|
||||
// :TODO: make the config merge in, instead of replace
|
||||
$config = $config ? HTMLPurifier_Config::create($config) : $this->config;
|
||||
|
||||
// implementation is partially environment dependant, partially
|
||||
// configuration dependant
|
||||
$lexer = HTMLPurifier_Lexer::create($config);
|
||||
|
||||
$context = new HTMLPurifier_Context();
|
||||
|
||||
// setup HTML generator
|
||||
$this->generator = new HTMLPurifier_Generator($config, $context);
|
||||
$context->register('Generator', $this->generator);
|
||||
|
||||
// set up global context variables
|
||||
if ($config->get('Core.CollectErrors')) {
|
||||
// may get moved out if other facilities use it
|
||||
$language_factory = HTMLPurifier_LanguageFactory::instance();
|
||||
$language = $language_factory->create($config, $context);
|
||||
$context->register('Locale', $language);
|
||||
|
||||
$error_collector = new HTMLPurifier_ErrorCollector($context);
|
||||
$context->register('ErrorCollector', $error_collector);
|
||||
}
|
||||
|
||||
// setup id_accumulator context, necessary due to the fact that
|
||||
// AttrValidator can be called from many places
|
||||
$id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);
|
||||
$context->register('IDAccumulator', $id_accumulator);
|
||||
|
||||
$html = HTMLPurifier_Encoder::convertToUTF8($html, $config, $context);
|
||||
|
||||
// setup filters
|
||||
$filter_flags = $config->getBatch('Filter');
|
||||
$custom_filters = $filter_flags['Custom'];
|
||||
unset($filter_flags['Custom']);
|
||||
$filters = array();
|
||||
foreach ($filter_flags as $filter => $flag) {
|
||||
if (!$flag) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($filter, '.') !== false) {
|
||||
continue;
|
||||
}
|
||||
$class = "HTMLPurifier_Filter_$filter";
|
||||
$filters[] = new $class;
|
||||
}
|
||||
foreach ($custom_filters as $filter) {
|
||||
// maybe "HTMLPurifier_Filter_$filter", but be consistent with AutoFormat
|
||||
$filters[] = $filter;
|
||||
}
|
||||
$filters = array_merge($filters, $this->filters);
|
||||
// maybe prepare(), but later
|
||||
|
||||
for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) {
|
||||
$html = $filters[$i]->preFilter($html, $config, $context);
|
||||
}
|
||||
|
||||
// purified HTML
|
||||
$html =
|
||||
$this->generator->generateFromTokens(
|
||||
// list of tokens
|
||||
$this->strategy->execute(
|
||||
// list of un-purified tokens
|
||||
$lexer->tokenizeHTML(
|
||||
// un-purified HTML
|
||||
$html,
|
||||
$config,
|
||||
$context
|
||||
),
|
||||
$config,
|
||||
$context
|
||||
)
|
||||
);
|
||||
|
||||
for ($i = $filter_size - 1; $i >= 0; $i--) {
|
||||
$html = $filters[$i]->postFilter($html, $config, $context);
|
||||
}
|
||||
|
||||
$html = HTMLPurifier_Encoder::convertFromUTF8($html, $config, $context);
|
||||
$this->context =& $context;
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an array of HTML snippets
|
||||
*
|
||||
* @param string[] $array_of_html Array of html snippets
|
||||
* @param HTMLPurifier_Config $config Optional config object for this operation.
|
||||
* See HTMLPurifier::purify() for more details.
|
||||
*
|
||||
* @return string[] Array of purified HTML
|
||||
*/
|
||||
public function purifyArray($array_of_html, $config = null)
|
||||
{
|
||||
$context_array = array();
|
||||
$array = array();
|
||||
foreach($array_of_html as $key=>$value){
|
||||
if (is_array($value)) {
|
||||
$array[$key] = $this->purifyArray($value, $config);
|
||||
} else {
|
||||
$array[$key] = $this->purify($value, $config);
|
||||
}
|
||||
$context_array[$key] = $this->context;
|
||||
}
|
||||
$this->context = $context_array;
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton for enforcing just one HTML Purifier in your system
|
||||
*
|
||||
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
|
||||
* HTMLPurifier instance to overload singleton with,
|
||||
* or HTMLPurifier_Config instance to configure the
|
||||
* generated version with.
|
||||
*
|
||||
* @return HTMLPurifier
|
||||
*/
|
||||
public static function instance($prototype = null)
|
||||
{
|
||||
if (!self::$instance || $prototype) {
|
||||
if ($prototype instanceof HTMLPurifier) {
|
||||
self::$instance = $prototype;
|
||||
} elseif ($prototype) {
|
||||
self::$instance = new HTMLPurifier($prototype);
|
||||
} else {
|
||||
self::$instance = new HTMLPurifier();
|
||||
}
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton for enforcing just one HTML Purifier in your system
|
||||
*
|
||||
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
|
||||
* HTMLPurifier instance to overload singleton with,
|
||||
* or HTMLPurifier_Config instance to configure the
|
||||
* generated version with.
|
||||
*
|
||||
* @return HTMLPurifier
|
||||
* @note Backwards compatibility, see instance()
|
||||
*/
|
||||
public static function getInstance($prototype = null)
|
||||
{
|
||||
return HTMLPurifier::instance($prototype);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+229
-230
@@ -1,230 +1,229 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file was auto-generated by generate-includes.php and includes all of
|
||||
* the core files required by HTML Purifier. This is a convenience stub that
|
||||
* includes all files using dirname(__FILE__) and require_once. PLEASE DO NOT
|
||||
* EDIT THIS FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* Changes to include_path are not necessary.
|
||||
*/
|
||||
|
||||
$__dir = dirname(__FILE__);
|
||||
|
||||
require_once $__dir . '/HTMLPurifier.php';
|
||||
require_once $__dir . '/HTMLPurifier/Arborize.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrCollections.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTypes.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrValidator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Bootstrap.php';
|
||||
require_once $__dir . '/HTMLPurifier/Definition.php';
|
||||
require_once $__dir . '/HTMLPurifier/CSSDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/Config.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigSchema.php';
|
||||
require_once $__dir . '/HTMLPurifier/ContentSets.php';
|
||||
require_once $__dir . '/HTMLPurifier/Context.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCacheFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/Doctype.php';
|
||||
require_once $__dir . '/HTMLPurifier/DoctypeRegistry.php';
|
||||
require_once $__dir . '/HTMLPurifier/ElementDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/Encoder.php';
|
||||
require_once $__dir . '/HTMLPurifier/EntityLookup.php';
|
||||
require_once $__dir . '/HTMLPurifier/EntityParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/ErrorCollector.php';
|
||||
require_once $__dir . '/HTMLPurifier/ErrorStruct.php';
|
||||
require_once $__dir . '/HTMLPurifier/Exception.php';
|
||||
require_once $__dir . '/HTMLPurifier/Filter.php';
|
||||
require_once $__dir . '/HTMLPurifier/Generator.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModuleManager.php';
|
||||
require_once $__dir . '/HTMLPurifier/IDAccumulator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector.php';
|
||||
require_once $__dir . '/HTMLPurifier/Language.php';
|
||||
require_once $__dir . '/HTMLPurifier/LanguageFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node.php';
|
||||
require_once $__dir . '/HTMLPurifier/PercentEncoder.php';
|
||||
require_once $__dir . '/HTMLPurifier/PropertyList.php';
|
||||
require_once $__dir . '/HTMLPurifier/PropertyListIterator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Queue.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy.php';
|
||||
require_once $__dir . '/HTMLPurifier/StringHash.php';
|
||||
require_once $__dir . '/HTMLPurifier/StringHashParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token.php';
|
||||
require_once $__dir . '/HTMLPurifier/TokenFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme.php';
|
||||
require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php';
|
||||
require_once $__dir . '/HTMLPurifier/UnitConverter.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParserException.php';
|
||||
require_once $__dir . '/HTMLPurifier/Zipper.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Clone.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Switch.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/AlphaValue.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Background.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Border.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Color.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Composite.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Font.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ident.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ratio.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Class.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ContentEditable.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/FrameTarget.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ID.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Host.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Background.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BdoDir.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BgColor.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BoolToCSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Border.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/EnumToCSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ImgRequired.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Input.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/NameSync.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Nofollow.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetBlank.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoopener.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoreferrer.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Textarea.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Empty.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/List.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Required.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Table.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Null.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Serializer.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Memory.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Bdo.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Edit.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Forms.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Hypertext.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Iframe.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Image.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Legacy.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/List.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Nofollow.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Object.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Presentation.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeScripting.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetBlank.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoopener.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoreferrer.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Strict.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Transitional.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/AutoParagraph.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/DisplayLinkURI.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/Linkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/RemoveEmpty.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Comment.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Element.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Composite.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Core.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/MakeWellFormed.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/RemoveForeignElements.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/ValidateAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform/Font.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform/Simple.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Comment.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Tag.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Empty.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/End.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Start.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableResources.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/Munge.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/SafeIframe.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/data.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/file.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/ftp.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/http.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/https.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/news.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/nntp.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/tel.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser/Flexible.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser/Native.php';
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file was auto-generated by generate-includes.php and includes all of
|
||||
* the core files required by HTML Purifier. This is a convenience stub that
|
||||
* includes all files using dirname(__FILE__) and require_once. PLEASE DO NOT
|
||||
* EDIT THIS FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* Changes to include_path are not necessary.
|
||||
*/
|
||||
|
||||
$__dir = dirname(__FILE__);
|
||||
|
||||
require_once $__dir . '/HTMLPurifier.php';
|
||||
require_once $__dir . '/HTMLPurifier/Arborize.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrCollections.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTypes.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrValidator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Bootstrap.php';
|
||||
require_once $__dir . '/HTMLPurifier/Definition.php';
|
||||
require_once $__dir . '/HTMLPurifier/CSSDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/Config.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigSchema.php';
|
||||
require_once $__dir . '/HTMLPurifier/ContentSets.php';
|
||||
require_once $__dir . '/HTMLPurifier/Context.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCacheFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/Doctype.php';
|
||||
require_once $__dir . '/HTMLPurifier/DoctypeRegistry.php';
|
||||
require_once $__dir . '/HTMLPurifier/ElementDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/Encoder.php';
|
||||
require_once $__dir . '/HTMLPurifier/EntityLookup.php';
|
||||
require_once $__dir . '/HTMLPurifier/EntityParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/ErrorCollector.php';
|
||||
require_once $__dir . '/HTMLPurifier/ErrorStruct.php';
|
||||
require_once $__dir . '/HTMLPurifier/Exception.php';
|
||||
require_once $__dir . '/HTMLPurifier/Filter.php';
|
||||
require_once $__dir . '/HTMLPurifier/Generator.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModuleManager.php';
|
||||
require_once $__dir . '/HTMLPurifier/IDAccumulator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector.php';
|
||||
require_once $__dir . '/HTMLPurifier/Language.php';
|
||||
require_once $__dir . '/HTMLPurifier/LanguageFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node.php';
|
||||
require_once $__dir . '/HTMLPurifier/PercentEncoder.php';
|
||||
require_once $__dir . '/HTMLPurifier/PropertyList.php';
|
||||
require_once $__dir . '/HTMLPurifier/PropertyListIterator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Queue.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy.php';
|
||||
require_once $__dir . '/HTMLPurifier/StringHash.php';
|
||||
require_once $__dir . '/HTMLPurifier/StringHashParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token.php';
|
||||
require_once $__dir . '/HTMLPurifier/TokenFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme.php';
|
||||
require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php';
|
||||
require_once $__dir . '/HTMLPurifier/UnitConverter.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParserException.php';
|
||||
require_once $__dir . '/HTMLPurifier/Zipper.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Clone.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Switch.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/AlphaValue.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Background.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Border.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Color.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Composite.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Font.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ident.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Class.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ContentEditable.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/FrameTarget.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ID.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Host.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Background.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BdoDir.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BgColor.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BoolToCSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Border.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/EnumToCSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ImgRequired.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Input.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/NameSync.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Nofollow.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetBlank.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoopener.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoreferrer.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Textarea.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Empty.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/List.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Required.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Table.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Null.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Serializer.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Memory.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Bdo.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Edit.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Forms.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Hypertext.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Iframe.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Image.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Legacy.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/List.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Nofollow.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Object.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Presentation.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeScripting.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetBlank.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoopener.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoreferrer.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Strict.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Transitional.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/AutoParagraph.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/DisplayLinkURI.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/Linkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/RemoveEmpty.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Comment.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Element.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Composite.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Core.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/MakeWellFormed.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/RemoveForeignElements.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/ValidateAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform/Font.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform/Simple.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Comment.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Tag.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Empty.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/End.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Start.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableResources.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/Munge.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/SafeIframe.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/data.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/file.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/ftp.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/http.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/https.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/news.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/nntp.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/tel.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser/Flexible.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser/Native.php';
|
||||
+71
-71
@@ -1,71 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Converts a stream of HTMLPurifier_Token into an HTMLPurifier_Node,
|
||||
* and back again.
|
||||
*
|
||||
* @note This transformation is not an equivalence. We mutate the input
|
||||
* token stream to make it so; see all [MUT] markers in code.
|
||||
*/
|
||||
class HTMLPurifier_Arborize
|
||||
{
|
||||
public static function arborize($tokens, $config, $context) {
|
||||
$definition = $config->getHTMLDefinition();
|
||||
$parent = new HTMLPurifier_Token_Start($definition->info_parent);
|
||||
$stack = array($parent->toNode());
|
||||
foreach ($tokens as $token) {
|
||||
$token->skip = null; // [MUT]
|
||||
$token->carryover = null; // [MUT]
|
||||
if ($token instanceof HTMLPurifier_Token_End) {
|
||||
$token->start = null; // [MUT]
|
||||
$r = array_pop($stack);
|
||||
//assert($r->name === $token->name);
|
||||
//assert(empty($token->attr));
|
||||
$r->endCol = $token->col;
|
||||
$r->endLine = $token->line;
|
||||
$r->endArmor = $token->armor;
|
||||
continue;
|
||||
}
|
||||
$node = $token->toNode();
|
||||
$stack[count($stack)-1]->children[] = $node;
|
||||
if ($token instanceof HTMLPurifier_Token_Start) {
|
||||
$stack[] = $node;
|
||||
}
|
||||
}
|
||||
//assert(count($stack) == 1);
|
||||
return $stack[0];
|
||||
}
|
||||
|
||||
public static function flatten($node, $config, $context) {
|
||||
$level = 0;
|
||||
$nodes = array($level => new HTMLPurifier_Queue(array($node)));
|
||||
$closingTokens = array();
|
||||
$tokens = array();
|
||||
do {
|
||||
while (!$nodes[$level]->isEmpty()) {
|
||||
$node = $nodes[$level]->shift(); // FIFO
|
||||
list($start, $end) = $node->toTokenPair();
|
||||
if ($level > 0) {
|
||||
$tokens[] = $start;
|
||||
}
|
||||
if ($end !== NULL) {
|
||||
$closingTokens[$level][] = $end;
|
||||
}
|
||||
if ($node instanceof HTMLPurifier_Node_Element) {
|
||||
$level++;
|
||||
$nodes[$level] = new HTMLPurifier_Queue();
|
||||
foreach ($node->children as $childNode) {
|
||||
$nodes[$level]->push($childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
$level--;
|
||||
if ($level && isset($closingTokens[$level])) {
|
||||
while ($token = array_pop($closingTokens[$level])) {
|
||||
$tokens[] = $token;
|
||||
}
|
||||
}
|
||||
} while ($level > 0);
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Converts a stream of HTMLPurifier_Token into an HTMLPurifier_Node,
|
||||
* and back again.
|
||||
*
|
||||
* @note This transformation is not an equivalence. We mutate the input
|
||||
* token stream to make it so; see all [MUT] markers in code.
|
||||
*/
|
||||
class HTMLPurifier_Arborize
|
||||
{
|
||||
public static function arborize($tokens, $config, $context) {
|
||||
$definition = $config->getHTMLDefinition();
|
||||
$parent = new HTMLPurifier_Token_Start($definition->info_parent);
|
||||
$stack = array($parent->toNode());
|
||||
foreach ($tokens as $token) {
|
||||
$token->skip = null; // [MUT]
|
||||
$token->carryover = null; // [MUT]
|
||||
if ($token instanceof HTMLPurifier_Token_End) {
|
||||
$token->start = null; // [MUT]
|
||||
$r = array_pop($stack);
|
||||
//assert($r->name === $token->name);
|
||||
//assert(empty($token->attr));
|
||||
$r->endCol = $token->col;
|
||||
$r->endLine = $token->line;
|
||||
$r->endArmor = $token->armor;
|
||||
continue;
|
||||
}
|
||||
$node = $token->toNode();
|
||||
$stack[count($stack)-1]->children[] = $node;
|
||||
if ($token instanceof HTMLPurifier_Token_Start) {
|
||||
$stack[] = $node;
|
||||
}
|
||||
}
|
||||
//assert(count($stack) == 1);
|
||||
return $stack[0];
|
||||
}
|
||||
|
||||
public static function flatten($node, $config, $context) {
|
||||
$level = 0;
|
||||
$nodes = array($level => new HTMLPurifier_Queue(array($node)));
|
||||
$closingTokens = array();
|
||||
$tokens = array();
|
||||
do {
|
||||
while (!$nodes[$level]->isEmpty()) {
|
||||
$node = $nodes[$level]->shift(); // FIFO
|
||||
list($start, $end) = $node->toTokenPair();
|
||||
if ($level > 0) {
|
||||
$tokens[] = $start;
|
||||
}
|
||||
if ($end !== NULL) {
|
||||
$closingTokens[$level][] = $end;
|
||||
}
|
||||
if ($node instanceof HTMLPurifier_Node_Element) {
|
||||
$level++;
|
||||
$nodes[$level] = new HTMLPurifier_Queue();
|
||||
foreach ($node->children as $childNode) {
|
||||
$nodes[$level]->push($childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
$level--;
|
||||
if ($level && isset($closingTokens[$level])) {
|
||||
while ($token = array_pop($closingTokens[$level])) {
|
||||
$tokens[] = $token;
|
||||
}
|
||||
}
|
||||
} while ($level > 0);
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
+148
-148
@@ -1,148 +1,148 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Defines common attribute collections that modules reference
|
||||
*/
|
||||
|
||||
class HTMLPurifier_AttrCollections
|
||||
{
|
||||
|
||||
/**
|
||||
* Associative array of attribute collections, indexed by name.
|
||||
* @type array
|
||||
*/
|
||||
public $info = array();
|
||||
|
||||
/**
|
||||
* Performs all expansions on internal data for use by other inclusions
|
||||
* It also collects all attribute collection extensions from
|
||||
* modules
|
||||
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
|
||||
* @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members
|
||||
*/
|
||||
public function __construct($attr_types, $modules)
|
||||
{
|
||||
$this->doConstruct($attr_types, $modules);
|
||||
}
|
||||
|
||||
public function doConstruct($attr_types, $modules)
|
||||
{
|
||||
// load extensions from the modules
|
||||
foreach ($modules as $module) {
|
||||
foreach ($module->attr_collections as $coll_i => $coll) {
|
||||
if (!isset($this->info[$coll_i])) {
|
||||
$this->info[$coll_i] = array();
|
||||
}
|
||||
foreach ($coll as $attr_i => $attr) {
|
||||
if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
|
||||
// merge in includes
|
||||
$this->info[$coll_i][$attr_i] = array_merge(
|
||||
$this->info[$coll_i][$attr_i],
|
||||
$attr
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$this->info[$coll_i][$attr_i] = $attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
// perform internal expansions and inclusions
|
||||
foreach ($this->info as $name => $attr) {
|
||||
// merge attribute collections that include others
|
||||
$this->performInclusions($this->info[$name]);
|
||||
// replace string identifiers with actual attribute objects
|
||||
$this->expandIdentifiers($this->info[$name], $attr_types);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a reference to an attribute associative array and performs
|
||||
* all inclusions specified by the zero index.
|
||||
* @param array &$attr Reference to attribute array
|
||||
*/
|
||||
public function performInclusions(&$attr)
|
||||
{
|
||||
if (!isset($attr[0])) {
|
||||
return;
|
||||
}
|
||||
$merge = $attr[0];
|
||||
$seen = array(); // recursion guard
|
||||
// loop through all the inclusions
|
||||
for ($i = 0; isset($merge[$i]); $i++) {
|
||||
if (isset($seen[$merge[$i]])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$merge[$i]] = true;
|
||||
// foreach attribute of the inclusion, copy it over
|
||||
if (!isset($this->info[$merge[$i]])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($this->info[$merge[$i]] as $key => $value) {
|
||||
if (isset($attr[$key])) {
|
||||
continue;
|
||||
} // also catches more inclusions
|
||||
$attr[$key] = $value;
|
||||
}
|
||||
if (isset($this->info[$merge[$i]][0])) {
|
||||
// recursion
|
||||
$merge = array_merge($merge, $this->info[$merge[$i]][0]);
|
||||
}
|
||||
}
|
||||
unset($attr[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands all string identifiers in an attribute array by replacing
|
||||
* them with the appropriate values inside HTMLPurifier_AttrTypes
|
||||
* @param array &$attr Reference to attribute array
|
||||
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
|
||||
*/
|
||||
public function expandIdentifiers(&$attr, $attr_types)
|
||||
{
|
||||
// because foreach will process new elements we add, make sure we
|
||||
// skip duplicates
|
||||
$processed = array();
|
||||
|
||||
foreach ($attr as $def_i => $def) {
|
||||
// skip inclusions
|
||||
if ($def_i === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($processed[$def_i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// determine whether or not attribute is required
|
||||
if ($required = (strpos($def_i, '*') !== false)) {
|
||||
// rename the definition
|
||||
unset($attr[$def_i]);
|
||||
$def_i = trim($def_i, '*');
|
||||
$attr[$def_i] = $def;
|
||||
}
|
||||
|
||||
$processed[$def_i] = true;
|
||||
|
||||
// if we've already got a literal object, move on
|
||||
if (is_object($def)) {
|
||||
// preserve previous required
|
||||
$attr[$def_i]->required = ($required || $attr[$def_i]->required);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($def === false) {
|
||||
unset($attr[$def_i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($t = $attr_types->get($def)) {
|
||||
$attr[$def_i] = $t;
|
||||
$attr[$def_i]->required = $required;
|
||||
} else {
|
||||
unset($attr[$def_i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Defines common attribute collections that modules reference
|
||||
*/
|
||||
|
||||
class HTMLPurifier_AttrCollections
|
||||
{
|
||||
|
||||
/**
|
||||
* Associative array of attribute collections, indexed by name.
|
||||
* @type array
|
||||
*/
|
||||
public $info = array();
|
||||
|
||||
/**
|
||||
* Performs all expansions on internal data for use by other inclusions
|
||||
* It also collects all attribute collection extensions from
|
||||
* modules
|
||||
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
|
||||
* @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members
|
||||
*/
|
||||
public function __construct($attr_types, $modules)
|
||||
{
|
||||
$this->doConstruct($attr_types, $modules);
|
||||
}
|
||||
|
||||
public function doConstruct($attr_types, $modules)
|
||||
{
|
||||
// load extensions from the modules
|
||||
foreach ($modules as $module) {
|
||||
foreach ($module->attr_collections as $coll_i => $coll) {
|
||||
if (!isset($this->info[$coll_i])) {
|
||||
$this->info[$coll_i] = array();
|
||||
}
|
||||
foreach ($coll as $attr_i => $attr) {
|
||||
if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
|
||||
// merge in includes
|
||||
$this->info[$coll_i][$attr_i] = array_merge(
|
||||
$this->info[$coll_i][$attr_i],
|
||||
$attr
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$this->info[$coll_i][$attr_i] = $attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
// perform internal expansions and inclusions
|
||||
foreach ($this->info as $name => $attr) {
|
||||
// merge attribute collections that include others
|
||||
$this->performInclusions($this->info[$name]);
|
||||
// replace string identifiers with actual attribute objects
|
||||
$this->expandIdentifiers($this->info[$name], $attr_types);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a reference to an attribute associative array and performs
|
||||
* all inclusions specified by the zero index.
|
||||
* @param array &$attr Reference to attribute array
|
||||
*/
|
||||
public function performInclusions(&$attr)
|
||||
{
|
||||
if (!isset($attr[0])) {
|
||||
return;
|
||||
}
|
||||
$merge = $attr[0];
|
||||
$seen = array(); // recursion guard
|
||||
// loop through all the inclusions
|
||||
for ($i = 0; isset($merge[$i]); $i++) {
|
||||
if (isset($seen[$merge[$i]])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$merge[$i]] = true;
|
||||
// foreach attribute of the inclusion, copy it over
|
||||
if (!isset($this->info[$merge[$i]])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($this->info[$merge[$i]] as $key => $value) {
|
||||
if (isset($attr[$key])) {
|
||||
continue;
|
||||
} // also catches more inclusions
|
||||
$attr[$key] = $value;
|
||||
}
|
||||
if (isset($this->info[$merge[$i]][0])) {
|
||||
// recursion
|
||||
$merge = array_merge($merge, $this->info[$merge[$i]][0]);
|
||||
}
|
||||
}
|
||||
unset($attr[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands all string identifiers in an attribute array by replacing
|
||||
* them with the appropriate values inside HTMLPurifier_AttrTypes
|
||||
* @param array &$attr Reference to attribute array
|
||||
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
|
||||
*/
|
||||
public function expandIdentifiers(&$attr, $attr_types)
|
||||
{
|
||||
// because foreach will process new elements we add, make sure we
|
||||
// skip duplicates
|
||||
$processed = array();
|
||||
|
||||
foreach ($attr as $def_i => $def) {
|
||||
// skip inclusions
|
||||
if ($def_i === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($processed[$def_i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// determine whether or not attribute is required
|
||||
if ($required = (strpos($def_i, '*') !== false)) {
|
||||
// rename the definition
|
||||
unset($attr[$def_i]);
|
||||
$def_i = trim($def_i, '*');
|
||||
$attr[$def_i] = $def;
|
||||
}
|
||||
|
||||
$processed[$def_i] = true;
|
||||
|
||||
// if we've already got a literal object, move on
|
||||
if (is_object($def)) {
|
||||
// preserve previous required
|
||||
$attr[$def_i]->required = ($required || $attr[$def_i]->required);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($def === false) {
|
||||
unset($attr[$def_i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($t = $attr_types->get($def)) {
|
||||
$attr[$def_i] = $t;
|
||||
$attr[$def_i]->required = $required;
|
||||
} else {
|
||||
unset($attr[$def_i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+144
-144
@@ -1,144 +1,144 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Base class for all validating attribute definitions.
|
||||
*
|
||||
* This family of classes forms the core for not only HTML attribute validation,
|
||||
* but also any sort of string that needs to be validated or cleaned (which
|
||||
* means CSS properties and composite definitions are defined here too).
|
||||
* Besides defining (through code) what precisely makes the string valid,
|
||||
* subclasses are also responsible for cleaning the code if possible.
|
||||
*/
|
||||
|
||||
abstract class HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Tells us whether or not an HTML attribute is minimized.
|
||||
* Has no meaning in other contexts.
|
||||
* @type bool
|
||||
*/
|
||||
public $minimized = false;
|
||||
|
||||
/**
|
||||
* Tells us whether or not an HTML attribute is required.
|
||||
* Has no meaning in other contexts
|
||||
* @type bool
|
||||
*/
|
||||
public $required = false;
|
||||
|
||||
/**
|
||||
* Validates and cleans passed string according to a definition.
|
||||
*
|
||||
* @param string $string String to be validated and cleaned.
|
||||
* @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object.
|
||||
* @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object.
|
||||
*/
|
||||
abstract public function validate($string, $config, $context);
|
||||
|
||||
/**
|
||||
* Convenience method that parses a string as if it were CDATA.
|
||||
*
|
||||
* This method process a string in the manner specified at
|
||||
* <http://www.w3.org/TR/html4/types.html#h-6.2> by removing
|
||||
* leading and trailing whitespace, ignoring line feeds, and replacing
|
||||
* carriage returns and tabs with spaces. While most useful for HTML
|
||||
* attributes specified as CDATA, it can also be applied to most CSS
|
||||
* values.
|
||||
*
|
||||
* @note This method is not entirely standards compliant, as trim() removes
|
||||
* more types of whitespace than specified in the spec. In practice,
|
||||
* this is rarely a problem, as those extra characters usually have
|
||||
* already been removed by HTMLPurifier_Encoder.
|
||||
*
|
||||
* @warning This processing is inconsistent with XML's whitespace handling
|
||||
* as specified by section 3.3.3 and referenced XHTML 1.0 section
|
||||
* 4.7. However, note that we are NOT necessarily
|
||||
* parsing XML, thus, this behavior may still be correct. We
|
||||
* assume that newlines have been normalized.
|
||||
*/
|
||||
public function parseCDATA($string)
|
||||
{
|
||||
$string = trim($string);
|
||||
$string = str_replace(array("\n", "\t", "\r"), ' ', $string);
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method for creating this class from a string.
|
||||
* @param string $string String construction info
|
||||
* @return HTMLPurifier_AttrDef Created AttrDef object corresponding to $string
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
// default implementation, return a flyweight of this object.
|
||||
// If $string has an effect on the returned object (i.e. you
|
||||
// need to overload this method), it is best
|
||||
// to clone or instantiate new copies. (Instantiation is safer.)
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
|
||||
* properly. THIS IS A HACK!
|
||||
* @param string $string a CSS colour definition
|
||||
* @return string
|
||||
*/
|
||||
protected function mungeRgb($string)
|
||||
{
|
||||
$p = '\s*(\d+(\.\d+)?([%]?))\s*';
|
||||
|
||||
if (preg_match('/(rgba|hsla)\(/', $string)) {
|
||||
return preg_replace('/(rgba|hsla)\('.$p.','.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8,\11)', $string);
|
||||
}
|
||||
|
||||
return preg_replace('/(rgb|hsl)\('.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8)', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a possibly escaped CSS string and returns the "pure"
|
||||
* version of it.
|
||||
*/
|
||||
protected function expandCSSEscape($string)
|
||||
{
|
||||
// flexibly parse it
|
||||
$ret = '';
|
||||
for ($i = 0, $c = strlen($string); $i < $c; $i++) {
|
||||
if ($string[$i] === '\\') {
|
||||
$i++;
|
||||
if ($i >= $c) {
|
||||
$ret .= '\\';
|
||||
break;
|
||||
}
|
||||
if (ctype_xdigit($string[$i])) {
|
||||
$code = $string[$i];
|
||||
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
|
||||
if (!ctype_xdigit($string[$i])) {
|
||||
break;
|
||||
}
|
||||
$code .= $string[$i];
|
||||
}
|
||||
// We have to be extremely careful when adding
|
||||
// new characters, to make sure we're not breaking
|
||||
// the encoding.
|
||||
$char = HTMLPurifier_Encoder::unichr(hexdec($code));
|
||||
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') {
|
||||
continue;
|
||||
}
|
||||
$ret .= $char;
|
||||
if ($i < $c && trim($string[$i]) !== '') {
|
||||
$i--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($string[$i] === "\n") {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$ret .= $string[$i];
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Base class for all validating attribute definitions.
|
||||
*
|
||||
* This family of classes forms the core for not only HTML attribute validation,
|
||||
* but also any sort of string that needs to be validated or cleaned (which
|
||||
* means CSS properties and composite definitions are defined here too).
|
||||
* Besides defining (through code) what precisely makes the string valid,
|
||||
* subclasses are also responsible for cleaning the code if possible.
|
||||
*/
|
||||
|
||||
abstract class HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Tells us whether or not an HTML attribute is minimized.
|
||||
* Has no meaning in other contexts.
|
||||
* @type bool
|
||||
*/
|
||||
public $minimized = false;
|
||||
|
||||
/**
|
||||
* Tells us whether or not an HTML attribute is required.
|
||||
* Has no meaning in other contexts
|
||||
* @type bool
|
||||
*/
|
||||
public $required = false;
|
||||
|
||||
/**
|
||||
* Validates and cleans passed string according to a definition.
|
||||
*
|
||||
* @param string $string String to be validated and cleaned.
|
||||
* @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object.
|
||||
* @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object.
|
||||
*/
|
||||
abstract public function validate($string, $config, $context);
|
||||
|
||||
/**
|
||||
* Convenience method that parses a string as if it were CDATA.
|
||||
*
|
||||
* This method process a string in the manner specified at
|
||||
* <http://www.w3.org/TR/html4/types.html#h-6.2> by removing
|
||||
* leading and trailing whitespace, ignoring line feeds, and replacing
|
||||
* carriage returns and tabs with spaces. While most useful for HTML
|
||||
* attributes specified as CDATA, it can also be applied to most CSS
|
||||
* values.
|
||||
*
|
||||
* @note This method is not entirely standards compliant, as trim() removes
|
||||
* more types of whitespace than specified in the spec. In practice,
|
||||
* this is rarely a problem, as those extra characters usually have
|
||||
* already been removed by HTMLPurifier_Encoder.
|
||||
*
|
||||
* @warning This processing is inconsistent with XML's whitespace handling
|
||||
* as specified by section 3.3.3 and referenced XHTML 1.0 section
|
||||
* 4.7. However, note that we are NOT necessarily
|
||||
* parsing XML, thus, this behavior may still be correct. We
|
||||
* assume that newlines have been normalized.
|
||||
*/
|
||||
public function parseCDATA($string)
|
||||
{
|
||||
$string = trim($string);
|
||||
$string = str_replace(array("\n", "\t", "\r"), ' ', $string);
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method for creating this class from a string.
|
||||
* @param string $string String construction info
|
||||
* @return HTMLPurifier_AttrDef Created AttrDef object corresponding to $string
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
// default implementation, return a flyweight of this object.
|
||||
// If $string has an effect on the returned object (i.e. you
|
||||
// need to overload this method), it is best
|
||||
// to clone or instantiate new copies. (Instantiation is safer.)
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
|
||||
* properly. THIS IS A HACK!
|
||||
* @param string $string a CSS colour definition
|
||||
* @return string
|
||||
*/
|
||||
protected function mungeRgb($string)
|
||||
{
|
||||
$p = '\s*(\d+(\.\d+)?([%]?))\s*';
|
||||
|
||||
if (preg_match('/(rgba|hsla)\(/', $string)) {
|
||||
return preg_replace('/(rgba|hsla)\('.$p.','.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8,\11)', $string);
|
||||
}
|
||||
|
||||
return preg_replace('/(rgb|hsl)\('.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8)', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a possibly escaped CSS string and returns the "pure"
|
||||
* version of it.
|
||||
*/
|
||||
protected function expandCSSEscape($string)
|
||||
{
|
||||
// flexibly parse it
|
||||
$ret = '';
|
||||
for ($i = 0, $c = strlen($string); $i < $c; $i++) {
|
||||
if ($string[$i] === '\\') {
|
||||
$i++;
|
||||
if ($i >= $c) {
|
||||
$ret .= '\\';
|
||||
break;
|
||||
}
|
||||
if (ctype_xdigit($string[$i])) {
|
||||
$code = $string[$i];
|
||||
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
|
||||
if (!ctype_xdigit($string[$i])) {
|
||||
break;
|
||||
}
|
||||
$code .= $string[$i];
|
||||
}
|
||||
// We have to be extremely careful when adding
|
||||
// new characters, to make sure we're not breaking
|
||||
// the encoding.
|
||||
$char = HTMLPurifier_Encoder::unichr(hexdec($code));
|
||||
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') {
|
||||
continue;
|
||||
}
|
||||
$ret .= $char;
|
||||
if ($i < $c && trim($string[$i]) !== '') {
|
||||
$i--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($string[$i] === "\n") {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$ret .= $string[$i];
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+136
-140
@@ -1,140 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates the HTML attribute style, otherwise known as CSS.
|
||||
* @note We don't implement the whole CSS specification, so it might be
|
||||
* difficult to reuse this component in the context of validating
|
||||
* actual stylesheet declarations.
|
||||
* @note If we were really serious about validating the CSS, we would
|
||||
* tokenize the styles and then parse the tokens. Obviously, we
|
||||
* are not doing that. Doing that could seriously harm performance,
|
||||
* but would make these components a lot more viable for a CSS
|
||||
* filtering solution.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $css
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($css, $config, $context)
|
||||
{
|
||||
$css = $this->parseCDATA($css);
|
||||
|
||||
$definition = $config->getCSSDefinition();
|
||||
$allow_duplicates = $config->get("CSS.AllowDuplicates");
|
||||
|
||||
$universal_attrdef = new HTMLPurifier_AttrDef_Enum(
|
||||
array(
|
||||
'initial',
|
||||
'inherit',
|
||||
'unset',
|
||||
)
|
||||
);
|
||||
|
||||
// According to the CSS2.1 spec, the places where a
|
||||
// non-delimiting semicolon can appear are in strings
|
||||
// escape sequences. So here is some dumb hack to
|
||||
// handle quotes.
|
||||
$len = strlen($css);
|
||||
$accum = "";
|
||||
$declarations = array();
|
||||
$quoted = false;
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$c = strcspn($css, ";'\"", $i);
|
||||
$accum .= substr($css, $i, $c);
|
||||
$i += $c;
|
||||
if ($i == $len) break;
|
||||
$d = $css[$i];
|
||||
if ($quoted) {
|
||||
$accum .= $d;
|
||||
if ($d == $quoted) {
|
||||
$quoted = false;
|
||||
}
|
||||
} else {
|
||||
if ($d == ";") {
|
||||
$declarations[] = $accum;
|
||||
$accum = "";
|
||||
} else {
|
||||
$accum .= $d;
|
||||
$quoted = $d;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($accum != "") $declarations[] = $accum;
|
||||
|
||||
$propvalues = array();
|
||||
$new_declarations = '';
|
||||
|
||||
/**
|
||||
* Name of the current CSS property being validated.
|
||||
*/
|
||||
$property = false;
|
||||
$context->register('CurrentCSSProperty', $property);
|
||||
|
||||
foreach ($declarations as $declaration) {
|
||||
if (!$declaration) {
|
||||
continue;
|
||||
}
|
||||
if (!strpos($declaration, ':')) {
|
||||
continue;
|
||||
}
|
||||
list($property, $value) = explode(':', $declaration, 2);
|
||||
$property = trim($property);
|
||||
$value = trim($value);
|
||||
$ok = false;
|
||||
do {
|
||||
if (isset($definition->info[$property])) {
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
if (ctype_lower($property)) {
|
||||
break;
|
||||
}
|
||||
$property = strtolower($property);
|
||||
if (isset($definition->info[$property])) {
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
if (!$ok) {
|
||||
continue;
|
||||
}
|
||||
$result = $universal_attrdef->validate($value, $config, $context);
|
||||
if ($result === false) {
|
||||
$result = $definition->info[$property]->validate(
|
||||
$value,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
}
|
||||
if ($result === false) {
|
||||
continue;
|
||||
}
|
||||
if ($allow_duplicates) {
|
||||
$new_declarations .= "$property:$result;";
|
||||
} else {
|
||||
$propvalues[$property] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
$context->destroy('CurrentCSSProperty');
|
||||
|
||||
// procedure does not write the new CSS simultaneously, so it's
|
||||
// slightly inefficient, but it's the only way of getting rid of
|
||||
// duplicates. Perhaps config to optimize it, but not now.
|
||||
|
||||
foreach ($propvalues as $prop => $value) {
|
||||
$new_declarations .= "$prop:$value;";
|
||||
}
|
||||
|
||||
return $new_declarations ? $new_declarations : false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates the HTML attribute style, otherwise known as CSS.
|
||||
* @note We don't implement the whole CSS specification, so it might be
|
||||
* difficult to reuse this component in the context of validating
|
||||
* actual stylesheet declarations.
|
||||
* @note If we were really serious about validating the CSS, we would
|
||||
* tokenize the styles and then parse the tokens. Obviously, we
|
||||
* are not doing that. Doing that could seriously harm performance,
|
||||
* but would make these components a lot more viable for a CSS
|
||||
* filtering solution.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $css
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($css, $config, $context)
|
||||
{
|
||||
$css = $this->parseCDATA($css);
|
||||
|
||||
$definition = $config->getCSSDefinition();
|
||||
$allow_duplicates = $config->get("CSS.AllowDuplicates");
|
||||
|
||||
|
||||
// According to the CSS2.1 spec, the places where a
|
||||
// non-delimiting semicolon can appear are in strings
|
||||
// escape sequences. So here is some dumb hack to
|
||||
// handle quotes.
|
||||
$len = strlen($css);
|
||||
$accum = "";
|
||||
$declarations = array();
|
||||
$quoted = false;
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$c = strcspn($css, ";'\"", $i);
|
||||
$accum .= substr($css, $i, $c);
|
||||
$i += $c;
|
||||
if ($i == $len) break;
|
||||
$d = $css[$i];
|
||||
if ($quoted) {
|
||||
$accum .= $d;
|
||||
if ($d == $quoted) {
|
||||
$quoted = false;
|
||||
}
|
||||
} else {
|
||||
if ($d == ";") {
|
||||
$declarations[] = $accum;
|
||||
$accum = "";
|
||||
} else {
|
||||
$accum .= $d;
|
||||
$quoted = $d;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($accum != "") $declarations[] = $accum;
|
||||
|
||||
$propvalues = array();
|
||||
$new_declarations = '';
|
||||
|
||||
/**
|
||||
* Name of the current CSS property being validated.
|
||||
*/
|
||||
$property = false;
|
||||
$context->register('CurrentCSSProperty', $property);
|
||||
|
||||
foreach ($declarations as $declaration) {
|
||||
if (!$declaration) {
|
||||
continue;
|
||||
}
|
||||
if (!strpos($declaration, ':')) {
|
||||
continue;
|
||||
}
|
||||
list($property, $value) = explode(':', $declaration, 2);
|
||||
$property = trim($property);
|
||||
$value = trim($value);
|
||||
$ok = false;
|
||||
do {
|
||||
if (isset($definition->info[$property])) {
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
if (ctype_lower($property)) {
|
||||
break;
|
||||
}
|
||||
$property = strtolower($property);
|
||||
if (isset($definition->info[$property])) {
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
if (!$ok) {
|
||||
continue;
|
||||
}
|
||||
// inefficient call, since the validator will do this again
|
||||
if (strtolower(trim($value)) !== 'inherit') {
|
||||
// inherit works for everything (but only on the base property)
|
||||
$result = $definition->info[$property]->validate(
|
||||
$value,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
} else {
|
||||
$result = 'inherit';
|
||||
}
|
||||
if ($result === false) {
|
||||
continue;
|
||||
}
|
||||
if ($allow_duplicates) {
|
||||
$new_declarations .= "$property:$result;";
|
||||
} else {
|
||||
$propvalues[$property] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
$context->destroy('CurrentCSSProperty');
|
||||
|
||||
// procedure does not write the new CSS simultaneously, so it's
|
||||
// slightly inefficient, but it's the only way of getting rid of
|
||||
// duplicates. Perhaps config to optimize it, but not now.
|
||||
|
||||
foreach ($propvalues as $prop => $value) {
|
||||
$new_declarations .= "$prop:$value;";
|
||||
}
|
||||
|
||||
return $new_declarations ? $new_declarations : false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,34 +1,34 @@
|
||||
<?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
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return string
|
||||
*/
|
||||
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
|
||||
<?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
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return string
|
||||
*/
|
||||
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
|
||||
+113
-113
@@ -1,113 +1,113 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates shorthand CSS property background.
|
||||
* @warning Does not support url tokens that have internal spaces.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Local copy of component validators.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
|
||||
*/
|
||||
protected $info;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['background-color'] = $def->info['background-color'];
|
||||
$this->info['background-image'] = $def->info['background-image'];
|
||||
$this->info['background-repeat'] = $def->info['background-repeat'];
|
||||
$this->info['background-attachment'] = $def->info['background-attachment'];
|
||||
$this->info['background-position'] = $def->info['background-position'];
|
||||
$this->info['background-size'] = $def->info['background-size'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// munge rgb() decl if necessary
|
||||
$string = $this->mungeRgb($string);
|
||||
|
||||
// assumes URI doesn't have spaces in it
|
||||
$bits = explode(' ', $string); // bits to process
|
||||
|
||||
$caught = array();
|
||||
$caught['color'] = false;
|
||||
$caught['image'] = false;
|
||||
$caught['repeat'] = false;
|
||||
$caught['attachment'] = false;
|
||||
$caught['position'] = false;
|
||||
$caught['size'] = false;
|
||||
|
||||
$i = 0; // number of catches
|
||||
|
||||
foreach ($bits as $bit) {
|
||||
if ($bit === '') {
|
||||
continue;
|
||||
}
|
||||
foreach ($caught as $key => $status) {
|
||||
if ($key != 'position') {
|
||||
if ($status !== false) {
|
||||
continue;
|
||||
}
|
||||
$r = $this->info['background-' . $key]->validate($bit, $config, $context);
|
||||
} else {
|
||||
$r = $bit;
|
||||
}
|
||||
if ($r === false) {
|
||||
continue;
|
||||
}
|
||||
if ($key == 'position') {
|
||||
if ($caught[$key] === false) {
|
||||
$caught[$key] = '';
|
||||
}
|
||||
$caught[$key] .= $r . ' ';
|
||||
} else {
|
||||
$caught[$key] = $r;
|
||||
}
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) {
|
||||
return false;
|
||||
}
|
||||
if ($caught['position'] !== false) {
|
||||
$caught['position'] = $this->info['background-position']->
|
||||
validate($caught['position'], $config, $context);
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
foreach ($caught as $value) {
|
||||
if ($value === false) {
|
||||
continue;
|
||||
}
|
||||
$ret[] = $value;
|
||||
}
|
||||
|
||||
if (empty($ret)) {
|
||||
return false;
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates shorthand CSS property background.
|
||||
* @warning Does not support url tokens that have internal spaces.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Local copy of component validators.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
|
||||
*/
|
||||
protected $info;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['background-color'] = $def->info['background-color'];
|
||||
$this->info['background-image'] = $def->info['background-image'];
|
||||
$this->info['background-repeat'] = $def->info['background-repeat'];
|
||||
$this->info['background-attachment'] = $def->info['background-attachment'];
|
||||
$this->info['background-position'] = $def->info['background-position'];
|
||||
$this->info['background-size'] = $def->info['background-size'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// munge rgb() decl if necessary
|
||||
$string = $this->mungeRgb($string);
|
||||
|
||||
// assumes URI doesn't have spaces in it
|
||||
$bits = explode(' ', $string); // bits to process
|
||||
|
||||
$caught = array();
|
||||
$caught['color'] = false;
|
||||
$caught['image'] = false;
|
||||
$caught['repeat'] = false;
|
||||
$caught['attachment'] = false;
|
||||
$caught['position'] = false;
|
||||
$caught['size'] = false;
|
||||
|
||||
$i = 0; // number of catches
|
||||
|
||||
foreach ($bits as $bit) {
|
||||
if ($bit === '') {
|
||||
continue;
|
||||
}
|
||||
foreach ($caught as $key => $status) {
|
||||
if ($key != 'position') {
|
||||
if ($status !== false) {
|
||||
continue;
|
||||
}
|
||||
$r = $this->info['background-' . $key]->validate($bit, $config, $context);
|
||||
} else {
|
||||
$r = $bit;
|
||||
}
|
||||
if ($r === false) {
|
||||
continue;
|
||||
}
|
||||
if ($key == 'position') {
|
||||
if ($caught[$key] === false) {
|
||||
$caught[$key] = '';
|
||||
}
|
||||
$caught[$key] .= $r . ' ';
|
||||
} else {
|
||||
$caught[$key] = $r;
|
||||
}
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) {
|
||||
return false;
|
||||
}
|
||||
if ($caught['position'] !== false) {
|
||||
$caught['position'] = $this->info['background-position']->
|
||||
validate($caught['position'], $config, $context);
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
foreach ($caught as $value) {
|
||||
if ($value === false) {
|
||||
continue;
|
||||
}
|
||||
$ret[] = $value;
|
||||
}
|
||||
|
||||
if (empty($ret)) {
|
||||
return false;
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+157
-157
@@ -1,157 +1,157 @@
|
||||
<?php
|
||||
|
||||
/* W3C says:
|
||||
[ // adjective and number must be in correct order, even if
|
||||
// you could switch them without introducing ambiguity.
|
||||
// some browsers support that syntax
|
||||
[
|
||||
<percentage> | <length> | left | center | right
|
||||
]
|
||||
[
|
||||
<percentage> | <length> | top | center | bottom
|
||||
]?
|
||||
] |
|
||||
[ // this signifies that the vertical and horizontal adjectives
|
||||
// can be arbitrarily ordered, however, there can only be two,
|
||||
// one of each, or none at all
|
||||
[
|
||||
left | center | right
|
||||
] ||
|
||||
[
|
||||
top | center | bottom
|
||||
]
|
||||
]
|
||||
top, left = 0%
|
||||
center, (none) = 50%
|
||||
bottom, right = 100%
|
||||
*/
|
||||
|
||||
/* QuirksMode says:
|
||||
keyword + length/percentage must be ordered correctly, as per W3C
|
||||
|
||||
Internet Explorer and Opera, however, support arbitrary ordering. We
|
||||
should fix it up.
|
||||
|
||||
Minor issue though, not strictly necessary.
|
||||
*/
|
||||
|
||||
// control freaks may appreciate the ability to convert these to
|
||||
// percentages or something, but it's not necessary
|
||||
|
||||
/**
|
||||
* Validates the value of background-position.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_Length
|
||||
*/
|
||||
protected $length;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_Percentage
|
||||
*/
|
||||
protected $percentage;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->length = new HTMLPurifier_AttrDef_CSS_Length();
|
||||
$this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->parseCDATA($string);
|
||||
$bits = explode(' ', $string);
|
||||
|
||||
$keywords = array();
|
||||
$keywords['h'] = false; // left, right
|
||||
$keywords['v'] = false; // top, bottom
|
||||
$keywords['ch'] = false; // center (first word)
|
||||
$keywords['cv'] = false; // center (second word)
|
||||
$measures = array();
|
||||
|
||||
$i = 0;
|
||||
|
||||
$lookup = array(
|
||||
'top' => 'v',
|
||||
'bottom' => 'v',
|
||||
'left' => 'h',
|
||||
'right' => 'h',
|
||||
'center' => 'c'
|
||||
);
|
||||
|
||||
foreach ($bits as $bit) {
|
||||
if ($bit === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// test for keyword
|
||||
$lbit = ctype_lower($bit) ? $bit : strtolower($bit);
|
||||
if (isset($lookup[$lbit])) {
|
||||
$status = $lookup[$lbit];
|
||||
if ($status == 'c') {
|
||||
if ($i == 0) {
|
||||
$status = 'ch';
|
||||
} else {
|
||||
$status = 'cv';
|
||||
}
|
||||
}
|
||||
$keywords[$status] = $lbit;
|
||||
$i++;
|
||||
}
|
||||
|
||||
// test for length
|
||||
$r = $this->length->validate($bit, $config, $context);
|
||||
if ($r !== false) {
|
||||
$measures[] = $r;
|
||||
$i++;
|
||||
}
|
||||
|
||||
// test for percentage
|
||||
$r = $this->percentage->validate($bit, $config, $context);
|
||||
if ($r !== false) {
|
||||
$measures[] = $r;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) {
|
||||
return false;
|
||||
} // no valid values were caught
|
||||
|
||||
$ret = array();
|
||||
|
||||
// first keyword
|
||||
if ($keywords['h']) {
|
||||
$ret[] = $keywords['h'];
|
||||
} elseif ($keywords['ch']) {
|
||||
$ret[] = $keywords['ch'];
|
||||
$keywords['cv'] = false; // prevent re-use: center = center center
|
||||
} elseif (count($measures)) {
|
||||
$ret[] = array_shift($measures);
|
||||
}
|
||||
|
||||
if ($keywords['v']) {
|
||||
$ret[] = $keywords['v'];
|
||||
} elseif ($keywords['cv']) {
|
||||
$ret[] = $keywords['cv'];
|
||||
} elseif (count($measures)) {
|
||||
$ret[] = array_shift($measures);
|
||||
}
|
||||
|
||||
if (empty($ret)) {
|
||||
return false;
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/* W3C says:
|
||||
[ // adjective and number must be in correct order, even if
|
||||
// you could switch them without introducing ambiguity.
|
||||
// some browsers support that syntax
|
||||
[
|
||||
<percentage> | <length> | left | center | right
|
||||
]
|
||||
[
|
||||
<percentage> | <length> | top | center | bottom
|
||||
]?
|
||||
] |
|
||||
[ // this signifies that the vertical and horizontal adjectives
|
||||
// can be arbitrarily ordered, however, there can only be two,
|
||||
// one of each, or none at all
|
||||
[
|
||||
left | center | right
|
||||
] ||
|
||||
[
|
||||
top | center | bottom
|
||||
]
|
||||
]
|
||||
top, left = 0%
|
||||
center, (none) = 50%
|
||||
bottom, right = 100%
|
||||
*/
|
||||
|
||||
/* QuirksMode says:
|
||||
keyword + length/percentage must be ordered correctly, as per W3C
|
||||
|
||||
Internet Explorer and Opera, however, support arbitrary ordering. We
|
||||
should fix it up.
|
||||
|
||||
Minor issue though, not strictly necessary.
|
||||
*/
|
||||
|
||||
// control freaks may appreciate the ability to convert these to
|
||||
// percentages or something, but it's not necessary
|
||||
|
||||
/**
|
||||
* Validates the value of background-position.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_Length
|
||||
*/
|
||||
protected $length;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_Percentage
|
||||
*/
|
||||
protected $percentage;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->length = new HTMLPurifier_AttrDef_CSS_Length();
|
||||
$this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->parseCDATA($string);
|
||||
$bits = explode(' ', $string);
|
||||
|
||||
$keywords = array();
|
||||
$keywords['h'] = false; // left, right
|
||||
$keywords['v'] = false; // top, bottom
|
||||
$keywords['ch'] = false; // center (first word)
|
||||
$keywords['cv'] = false; // center (second word)
|
||||
$measures = array();
|
||||
|
||||
$i = 0;
|
||||
|
||||
$lookup = array(
|
||||
'top' => 'v',
|
||||
'bottom' => 'v',
|
||||
'left' => 'h',
|
||||
'right' => 'h',
|
||||
'center' => 'c'
|
||||
);
|
||||
|
||||
foreach ($bits as $bit) {
|
||||
if ($bit === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// test for keyword
|
||||
$lbit = ctype_lower($bit) ? $bit : strtolower($bit);
|
||||
if (isset($lookup[$lbit])) {
|
||||
$status = $lookup[$lbit];
|
||||
if ($status == 'c') {
|
||||
if ($i == 0) {
|
||||
$status = 'ch';
|
||||
} else {
|
||||
$status = 'cv';
|
||||
}
|
||||
}
|
||||
$keywords[$status] = $lbit;
|
||||
$i++;
|
||||
}
|
||||
|
||||
// test for length
|
||||
$r = $this->length->validate($bit, $config, $context);
|
||||
if ($r !== false) {
|
||||
$measures[] = $r;
|
||||
$i++;
|
||||
}
|
||||
|
||||
// test for percentage
|
||||
$r = $this->percentage->validate($bit, $config, $context);
|
||||
if ($r !== false) {
|
||||
$measures[] = $r;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) {
|
||||
return false;
|
||||
} // no valid values were caught
|
||||
|
||||
$ret = array();
|
||||
|
||||
// first keyword
|
||||
if ($keywords['h']) {
|
||||
$ret[] = $keywords['h'];
|
||||
} elseif ($keywords['ch']) {
|
||||
$ret[] = $keywords['ch'];
|
||||
$keywords['cv'] = false; // prevent re-use: center = center center
|
||||
} elseif (count($measures)) {
|
||||
$ret[] = array_shift($measures);
|
||||
}
|
||||
|
||||
if ($keywords['v']) {
|
||||
$ret[] = $keywords['v'];
|
||||
} elseif ($keywords['cv']) {
|
||||
$ret[] = $keywords['cv'];
|
||||
} elseif (count($measures)) {
|
||||
$ret[] = array_shift($measures);
|
||||
}
|
||||
|
||||
if (empty($ret)) {
|
||||
return false;
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,56 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates the border property as defined by CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Local copy of properties this property is shorthand for.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
*/
|
||||
protected $info = array();
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['border-width'] = $def->info['border-width'];
|
||||
$this->info['border-style'] = $def->info['border-style'];
|
||||
$this->info['border-top-color'] = $def->info['border-top-color'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->parseCDATA($string);
|
||||
$string = $this->mungeRgb($string);
|
||||
$bits = explode(' ', $string);
|
||||
$done = array(); // segments we've finished
|
||||
$ret = ''; // return value
|
||||
foreach ($bits as $bit) {
|
||||
foreach ($this->info as $propname => $validator) {
|
||||
if (isset($done[$propname])) {
|
||||
continue;
|
||||
}
|
||||
$r = $validator->validate($bit, $config, $context);
|
||||
if ($r !== false) {
|
||||
$ret .= $r . ' ';
|
||||
$done[$propname] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rtrim($ret);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates the border property as defined by CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Local copy of properties this property is shorthand for.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
*/
|
||||
protected $info = array();
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['border-width'] = $def->info['border-width'];
|
||||
$this->info['border-style'] = $def->info['border-style'];
|
||||
$this->info['border-top-color'] = $def->info['border-top-color'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->parseCDATA($string);
|
||||
$string = $this->mungeRgb($string);
|
||||
$bits = explode(' ', $string);
|
||||
$done = array(); // segments we've finished
|
||||
$ret = ''; // return value
|
||||
foreach ($bits as $bit) {
|
||||
foreach ($this->info as $propname => $validator) {
|
||||
if (isset($done[$propname])) {
|
||||
continue;
|
||||
}
|
||||
$r = $validator->validate($bit, $config, $context);
|
||||
if ($r !== false) {
|
||||
$ret .= $r . ' ';
|
||||
$done[$propname] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rtrim($ret);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+161
-161
@@ -1,161 +1,161 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates Color as defined by CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_AlphaValue
|
||||
*/
|
||||
protected $alpha;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $color
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($color, $config, $context)
|
||||
{
|
||||
static $colors = null;
|
||||
if ($colors === null) {
|
||||
$colors = $config->get('Core.ColorKeywords');
|
||||
}
|
||||
|
||||
$color = trim($color);
|
||||
if ($color === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lower = strtolower($color);
|
||||
if (isset($colors[$lower])) {
|
||||
return $colors[$lower];
|
||||
}
|
||||
|
||||
if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
|
||||
$length = strlen($color);
|
||||
if (strpos($color, ')') !== $length - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get used function : rgb, rgba, hsl or hsla
|
||||
$function = $matches[1];
|
||||
|
||||
$parameters_size = 3;
|
||||
$alpha_channel = false;
|
||||
if (substr($function, -1) === 'a') {
|
||||
$parameters_size = 4;
|
||||
$alpha_channel = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allowed types for values :
|
||||
* parameter_position => [type => max_value]
|
||||
*/
|
||||
$allowed_types = array(
|
||||
1 => array('percentage' => 100, 'integer' => 255),
|
||||
2 => array('percentage' => 100, 'integer' => 255),
|
||||
3 => array('percentage' => 100, 'integer' => 255),
|
||||
);
|
||||
$allow_different_types = false;
|
||||
|
||||
if (strpos($function, 'hsl') !== false) {
|
||||
$allowed_types = array(
|
||||
1 => array('integer' => 360),
|
||||
2 => array('percentage' => 100),
|
||||
3 => array('percentage' => 100),
|
||||
);
|
||||
$allow_different_types = true;
|
||||
}
|
||||
|
||||
$values = trim(str_replace($function, '', $color), ' ()');
|
||||
|
||||
$parts = explode(',', $values);
|
||||
if (count($parts) !== $parameters_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$type = false;
|
||||
$new_parts = array();
|
||||
$i = 0;
|
||||
|
||||
foreach ($parts as $part) {
|
||||
$i++;
|
||||
$part = trim($part);
|
||||
|
||||
if ($part === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// different check for alpha channel
|
||||
if ($alpha_channel === true && $i === count($parts)) {
|
||||
$result = $this->alpha->validate($part, $config, $context);
|
||||
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$new_parts[] = (string)$result;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (substr($part, -1) === '%') {
|
||||
$current_type = 'percentage';
|
||||
} else {
|
||||
$current_type = 'integer';
|
||||
}
|
||||
|
||||
if (!array_key_exists($current_type, $allowed_types[$i])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$type) {
|
||||
$type = $current_type;
|
||||
}
|
||||
|
||||
if ($allow_different_types === false && $type != $current_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$max_value = $allowed_types[$i][$current_type];
|
||||
|
||||
if ($current_type == 'integer') {
|
||||
// Return value between range 0 -> $max_value
|
||||
$new_parts[] = (int)max(min($part, $max_value), 0);
|
||||
} elseif ($current_type == 'percentage') {
|
||||
$new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%';
|
||||
}
|
||||
}
|
||||
|
||||
$new_values = implode(',', $new_parts);
|
||||
|
||||
$color = $function . '(' . $new_values . ')';
|
||||
} else {
|
||||
// hexadecimal handling
|
||||
if ($color[0] === '#') {
|
||||
$hex = substr($color, 1);
|
||||
} else {
|
||||
$hex = $color;
|
||||
$color = '#' . $color;
|
||||
}
|
||||
$length = strlen($hex);
|
||||
if ($length !== 3 && $length !== 6) {
|
||||
return false;
|
||||
}
|
||||
if (!ctype_xdigit($hex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates Color as defined by CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_AlphaValue
|
||||
*/
|
||||
protected $alpha;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $color
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($color, $config, $context)
|
||||
{
|
||||
static $colors = null;
|
||||
if ($colors === null) {
|
||||
$colors = $config->get('Core.ColorKeywords');
|
||||
}
|
||||
|
||||
$color = trim($color);
|
||||
if ($color === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lower = strtolower($color);
|
||||
if (isset($colors[$lower])) {
|
||||
return $colors[$lower];
|
||||
}
|
||||
|
||||
if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
|
||||
$length = strlen($color);
|
||||
if (strpos($color, ')') !== $length - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get used function : rgb, rgba, hsl or hsla
|
||||
$function = $matches[1];
|
||||
|
||||
$parameters_size = 3;
|
||||
$alpha_channel = false;
|
||||
if (substr($function, -1) === 'a') {
|
||||
$parameters_size = 4;
|
||||
$alpha_channel = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allowed types for values :
|
||||
* parameter_position => [type => max_value]
|
||||
*/
|
||||
$allowed_types = array(
|
||||
1 => array('percentage' => 100, 'integer' => 255),
|
||||
2 => array('percentage' => 100, 'integer' => 255),
|
||||
3 => array('percentage' => 100, 'integer' => 255),
|
||||
);
|
||||
$allow_different_types = false;
|
||||
|
||||
if (strpos($function, 'hsl') !== false) {
|
||||
$allowed_types = array(
|
||||
1 => array('integer' => 360),
|
||||
2 => array('percentage' => 100),
|
||||
3 => array('percentage' => 100),
|
||||
);
|
||||
$allow_different_types = true;
|
||||
}
|
||||
|
||||
$values = trim(str_replace($function, '', $color), ' ()');
|
||||
|
||||
$parts = explode(',', $values);
|
||||
if (count($parts) !== $parameters_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$type = false;
|
||||
$new_parts = array();
|
||||
$i = 0;
|
||||
|
||||
foreach ($parts as $part) {
|
||||
$i++;
|
||||
$part = trim($part);
|
||||
|
||||
if ($part === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// different check for alpha channel
|
||||
if ($alpha_channel === true && $i === count($parts)) {
|
||||
$result = $this->alpha->validate($part, $config, $context);
|
||||
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$new_parts[] = (string)$result;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (substr($part, -1) === '%') {
|
||||
$current_type = 'percentage';
|
||||
} else {
|
||||
$current_type = 'integer';
|
||||
}
|
||||
|
||||
if (!array_key_exists($current_type, $allowed_types[$i])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$type) {
|
||||
$type = $current_type;
|
||||
}
|
||||
|
||||
if ($allow_different_types === false && $type != $current_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$max_value = $allowed_types[$i][$current_type];
|
||||
|
||||
if ($current_type == 'integer') {
|
||||
// Return value between range 0 -> $max_value
|
||||
$new_parts[] = (int)max(min($part, $max_value), 0);
|
||||
} elseif ($current_type == 'percentage') {
|
||||
$new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%';
|
||||
}
|
||||
}
|
||||
|
||||
$new_values = implode(',', $new_parts);
|
||||
|
||||
$color = $function . '(' . $new_values . ')';
|
||||
} else {
|
||||
// hexadecimal handling
|
||||
if ($color[0] === '#') {
|
||||
$hex = substr($color, 1);
|
||||
} else {
|
||||
$hex = $color;
|
||||
$color = '#' . $color;
|
||||
}
|
||||
$length = strlen($hex);
|
||||
if ($length !== 3 && $length !== 6) {
|
||||
return false;
|
||||
}
|
||||
if (!ctype_xdigit($hex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,48 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Allows multiple validators to attempt to validate attribute.
|
||||
*
|
||||
* Composite is just what it sounds like: a composite of many validators.
|
||||
* This means that multiple HTMLPurifier_AttrDef objects will have a whack
|
||||
* at the string. If one of them passes, that's what is returned. This is
|
||||
* especially useful for CSS values, which often are a choice between
|
||||
* an enumerated set of predefined values or a flexible data type.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* List of objects that may process strings.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $defs;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef[] $defs List of HTMLPurifier_AttrDef objects
|
||||
*/
|
||||
public function __construct($defs)
|
||||
{
|
||||
$this->defs = $defs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
foreach ($this->defs as $i => $def) {
|
||||
$result = $this->defs[$i]->validate($string, $config, $context);
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Allows multiple validators to attempt to validate attribute.
|
||||
*
|
||||
* Composite is just what it sounds like: a composite of many validators.
|
||||
* This means that multiple HTMLPurifier_AttrDef objects will have a whack
|
||||
* at the string. If one of them passes, that's what is returned. This is
|
||||
* especially useful for CSS values, which often are a choice between
|
||||
* an enumerated set of predefined values or a flexible data type.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* List of objects that may process strings.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $defs;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef[] $defs List of HTMLPurifier_AttrDef objects
|
||||
*/
|
||||
public function __construct($defs)
|
||||
{
|
||||
$this->defs = $defs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
foreach ($this->defs as $i => $def) {
|
||||
$result = $this->defs[$i]->validate($string, $config, $context);
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+44
-44
@@ -1,44 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Decorator which enables CSS properties to be disabled for specific elements.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
public $def;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
public $element;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $def Definition to wrap
|
||||
* @param string $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
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Decorator which enables CSS properties to be disabled for specific elements.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
public $def;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
public $element;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $def Definition to wrap
|
||||
* @param string $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
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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,77 +1,77 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Microsoft's proprietary filter: CSS property
|
||||
* @note Currently supports the alpha filter. In the future, this will
|
||||
* probably need an extensible framework
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_Integer
|
||||
*/
|
||||
protected $intValidator;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->intValidator = new HTMLPurifier_AttrDef_Integer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($value, $config, $context)
|
||||
{
|
||||
$value = $this->parseCDATA($value);
|
||||
if ($value === 'none') {
|
||||
return $value;
|
||||
}
|
||||
// if we looped this we could support multiple filters
|
||||
$function_length = strcspn($value, '(');
|
||||
$function = trim(substr($value, 0, $function_length));
|
||||
if ($function !== 'alpha' &&
|
||||
$function !== 'Alpha' &&
|
||||
$function !== 'progid:DXImageTransform.Microsoft.Alpha'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$cursor = $function_length + 1;
|
||||
$parameters_length = strcspn($value, ')', $cursor);
|
||||
$parameters = substr($value, $cursor, $parameters_length);
|
||||
$params = explode(',', $parameters);
|
||||
$ret_params = array();
|
||||
$lookup = array();
|
||||
foreach ($params as $param) {
|
||||
list($key, $value) = explode('=', $param);
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
if (isset($lookup[$key])) {
|
||||
continue;
|
||||
}
|
||||
if ($key !== 'opacity') {
|
||||
continue;
|
||||
}
|
||||
$value = $this->intValidator->validate($value, $config, $context);
|
||||
if ($value === false) {
|
||||
continue;
|
||||
}
|
||||
$int = (int)$value;
|
||||
if ($int > 100) {
|
||||
$value = '100';
|
||||
}
|
||||
if ($int < 0) {
|
||||
$value = '0';
|
||||
}
|
||||
$ret_params[] = "$key=$value";
|
||||
$lookup[$key] = true;
|
||||
}
|
||||
$ret_parameters = implode(',', $ret_params);
|
||||
$ret_function = "$function($ret_parameters)";
|
||||
return $ret_function;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Microsoft's proprietary filter: CSS property
|
||||
* @note Currently supports the alpha filter. In the future, this will
|
||||
* probably need an extensible framework
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_Integer
|
||||
*/
|
||||
protected $intValidator;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->intValidator = new HTMLPurifier_AttrDef_Integer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($value, $config, $context)
|
||||
{
|
||||
$value = $this->parseCDATA($value);
|
||||
if ($value === 'none') {
|
||||
return $value;
|
||||
}
|
||||
// if we looped this we could support multiple filters
|
||||
$function_length = strcspn($value, '(');
|
||||
$function = trim(substr($value, 0, $function_length));
|
||||
if ($function !== 'alpha' &&
|
||||
$function !== 'Alpha' &&
|
||||
$function !== 'progid:DXImageTransform.Microsoft.Alpha'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$cursor = $function_length + 1;
|
||||
$parameters_length = strcspn($value, ')', $cursor);
|
||||
$parameters = substr($value, $cursor, $parameters_length);
|
||||
$params = explode(',', $parameters);
|
||||
$ret_params = array();
|
||||
$lookup = array();
|
||||
foreach ($params as $param) {
|
||||
list($key, $value) = explode('=', $param);
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
if (isset($lookup[$key])) {
|
||||
continue;
|
||||
}
|
||||
if ($key !== 'opacity') {
|
||||
continue;
|
||||
}
|
||||
$value = $this->intValidator->validate($value, $config, $context);
|
||||
if ($value === false) {
|
||||
continue;
|
||||
}
|
||||
$int = (int)$value;
|
||||
if ($int > 100) {
|
||||
$value = '100';
|
||||
}
|
||||
if ($int < 0) {
|
||||
$value = '0';
|
||||
}
|
||||
$ret_params[] = "$key=$value";
|
||||
$lookup[$key] = true;
|
||||
}
|
||||
$ret_parameters = implode(',', $ret_params);
|
||||
$ret_function = "$function($ret_parameters)";
|
||||
return $ret_function;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+176
-176
@@ -1,176 +1,176 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates shorthand CSS property font.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Local copy of validators
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note If we moved specific CSS property definitions to their own
|
||||
* classes instead of having them be assembled at run time by
|
||||
* CSSDefinition, this wouldn't be necessary. We'd instantiate
|
||||
* our own copies.
|
||||
*/
|
||||
protected $info = array();
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['font-style'] = $def->info['font-style'];
|
||||
$this->info['font-variant'] = $def->info['font-variant'];
|
||||
$this->info['font-weight'] = $def->info['font-weight'];
|
||||
$this->info['font-size'] = $def->info['font-size'];
|
||||
$this->info['line-height'] = $def->info['line-height'];
|
||||
$this->info['font-family'] = $def->info['font-family'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $system_fonts = array(
|
||||
'caption' => true,
|
||||
'icon' => true,
|
||||
'menu' => true,
|
||||
'message-box' => true,
|
||||
'small-caption' => true,
|
||||
'status-bar' => true
|
||||
);
|
||||
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if it's one of the keywords
|
||||
$lowercase_string = strtolower($string);
|
||||
if (isset($system_fonts[$lowercase_string])) {
|
||||
return $lowercase_string;
|
||||
}
|
||||
|
||||
$bits = explode(' ', $string); // bits to process
|
||||
$stage = 0; // this indicates what we're looking for
|
||||
$caught = array(); // which stage 0 properties have we caught?
|
||||
$stage_1 = array('font-style', 'font-variant', 'font-weight');
|
||||
$final = ''; // output
|
||||
|
||||
for ($i = 0, $size = count($bits); $i < $size; $i++) {
|
||||
if ($bits[$i] === '') {
|
||||
continue;
|
||||
}
|
||||
switch ($stage) {
|
||||
case 0: // attempting to catch font-style, font-variant or font-weight
|
||||
foreach ($stage_1 as $validator_name) {
|
||||
if (isset($caught[$validator_name])) {
|
||||
continue;
|
||||
}
|
||||
$r = $this->info[$validator_name]->validate(
|
||||
$bits[$i],
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r . ' ';
|
||||
$caught[$validator_name] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// all three caught, continue on
|
||||
if (count($caught) >= 3) {
|
||||
$stage = 1;
|
||||
}
|
||||
if ($r !== false) {
|
||||
break;
|
||||
}
|
||||
case 1: // attempting to catch font-size and perhaps line-height
|
||||
$found_slash = false;
|
||||
if (strpos($bits[$i], '/') !== false) {
|
||||
list($font_size, $line_height) =
|
||||
explode('/', $bits[$i]);
|
||||
if ($line_height === '') {
|
||||
// ooh, there's a space after the slash!
|
||||
$line_height = false;
|
||||
$found_slash = true;
|
||||
}
|
||||
} else {
|
||||
$font_size = $bits[$i];
|
||||
$line_height = false;
|
||||
}
|
||||
$r = $this->info['font-size']->validate(
|
||||
$font_size,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r;
|
||||
// attempt to catch line-height
|
||||
if ($line_height === false) {
|
||||
// we need to scroll forward
|
||||
for ($j = $i + 1; $j < $size; $j++) {
|
||||
if ($bits[$j] === '') {
|
||||
continue;
|
||||
}
|
||||
if ($bits[$j] === '/') {
|
||||
if ($found_slash) {
|
||||
return false;
|
||||
} else {
|
||||
$found_slash = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$line_height = $bits[$j];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// slash already found
|
||||
$found_slash = true;
|
||||
$j = $i;
|
||||
}
|
||||
if ($found_slash) {
|
||||
$i = $j;
|
||||
$r = $this->info['line-height']->validate(
|
||||
$line_height,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= '/' . $r;
|
||||
}
|
||||
}
|
||||
$final .= ' ';
|
||||
$stage = 2;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
case 2: // attempting to catch font-family
|
||||
$font_family =
|
||||
implode(' ', array_slice($bits, $i, $size - $i));
|
||||
$r = $this->info['font-family']->validate(
|
||||
$font_family,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r . ' ';
|
||||
// processing completed successfully
|
||||
return rtrim($final);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates shorthand CSS property font.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Local copy of validators
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note If we moved specific CSS property definitions to their own
|
||||
* classes instead of having them be assembled at run time by
|
||||
* CSSDefinition, this wouldn't be necessary. We'd instantiate
|
||||
* our own copies.
|
||||
*/
|
||||
protected $info = array();
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['font-style'] = $def->info['font-style'];
|
||||
$this->info['font-variant'] = $def->info['font-variant'];
|
||||
$this->info['font-weight'] = $def->info['font-weight'];
|
||||
$this->info['font-size'] = $def->info['font-size'];
|
||||
$this->info['line-height'] = $def->info['line-height'];
|
||||
$this->info['font-family'] = $def->info['font-family'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $system_fonts = array(
|
||||
'caption' => true,
|
||||
'icon' => true,
|
||||
'menu' => true,
|
||||
'message-box' => true,
|
||||
'small-caption' => true,
|
||||
'status-bar' => true
|
||||
);
|
||||
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if it's one of the keywords
|
||||
$lowercase_string = strtolower($string);
|
||||
if (isset($system_fonts[$lowercase_string])) {
|
||||
return $lowercase_string;
|
||||
}
|
||||
|
||||
$bits = explode(' ', $string); // bits to process
|
||||
$stage = 0; // this indicates what we're looking for
|
||||
$caught = array(); // which stage 0 properties have we caught?
|
||||
$stage_1 = array('font-style', 'font-variant', 'font-weight');
|
||||
$final = ''; // output
|
||||
|
||||
for ($i = 0, $size = count($bits); $i < $size; $i++) {
|
||||
if ($bits[$i] === '') {
|
||||
continue;
|
||||
}
|
||||
switch ($stage) {
|
||||
case 0: // attempting to catch font-style, font-variant or font-weight
|
||||
foreach ($stage_1 as $validator_name) {
|
||||
if (isset($caught[$validator_name])) {
|
||||
continue;
|
||||
}
|
||||
$r = $this->info[$validator_name]->validate(
|
||||
$bits[$i],
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r . ' ';
|
||||
$caught[$validator_name] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// all three caught, continue on
|
||||
if (count($caught) >= 3) {
|
||||
$stage = 1;
|
||||
}
|
||||
if ($r !== false) {
|
||||
break;
|
||||
}
|
||||
case 1: // attempting to catch font-size and perhaps line-height
|
||||
$found_slash = false;
|
||||
if (strpos($bits[$i], '/') !== false) {
|
||||
list($font_size, $line_height) =
|
||||
explode('/', $bits[$i]);
|
||||
if ($line_height === '') {
|
||||
// ooh, there's a space after the slash!
|
||||
$line_height = false;
|
||||
$found_slash = true;
|
||||
}
|
||||
} else {
|
||||
$font_size = $bits[$i];
|
||||
$line_height = false;
|
||||
}
|
||||
$r = $this->info['font-size']->validate(
|
||||
$font_size,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r;
|
||||
// attempt to catch line-height
|
||||
if ($line_height === false) {
|
||||
// we need to scroll forward
|
||||
for ($j = $i + 1; $j < $size; $j++) {
|
||||
if ($bits[$j] === '') {
|
||||
continue;
|
||||
}
|
||||
if ($bits[$j] === '/') {
|
||||
if ($found_slash) {
|
||||
return false;
|
||||
} else {
|
||||
$found_slash = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$line_height = $bits[$j];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// slash already found
|
||||
$found_slash = true;
|
||||
$j = $i;
|
||||
}
|
||||
if ($found_slash) {
|
||||
$i = $j;
|
||||
$r = $this->info['line-height']->validate(
|
||||
$line_height,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= '/' . $r;
|
||||
}
|
||||
}
|
||||
$final .= ' ';
|
||||
$stage = 2;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
case 2: // attempting to catch font-family
|
||||
$font_family =
|
||||
implode(' ', array_slice($bits, $i, $size - $i));
|
||||
$r = $this->info['font-family']->validate(
|
||||
$font_family,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r . ' ';
|
||||
// processing completed successfully
|
||||
return rtrim($final);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+217
-217
@@ -1,217 +1,217 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a font family list according to CSS spec
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
protected $mask = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Lowercase letters
|
||||
$l = range('a', 'z');
|
||||
// Uppercase letters
|
||||
$u = range('A', 'Z');
|
||||
// Digits
|
||||
$d = range('0', '9');
|
||||
// Special bytes used by UTF-8
|
||||
$b = array_map('chr', range(0x80, 0xFF));
|
||||
// All valid characters for the mask
|
||||
$c = array_merge($l, $u, $d, $b);
|
||||
// Concatenate all valid characters into a string
|
||||
// Use '_- ' as an initial value
|
||||
$this->mask = array_reduce($c, function ($carry, $value) {
|
||||
return $carry . $value;
|
||||
}, '_- ');
|
||||
|
||||
/*
|
||||
PHP's internal strcspn implementation is
|
||||
O(length of string * length of mask), making it inefficient
|
||||
for large masks. However, it's still faster than
|
||||
preg_match 8)
|
||||
for (p = s1;;) {
|
||||
spanp = s2;
|
||||
do {
|
||||
if (*spanp == c || p == s1_end) {
|
||||
return p - s1;
|
||||
}
|
||||
} while (spanp++ < (s2_end - 1));
|
||||
c = *++p;
|
||||
}
|
||||
*/
|
||||
// possible optimization: invert the mask.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $generic_names = array(
|
||||
'serif' => true,
|
||||
'sans-serif' => true,
|
||||
'monospace' => true,
|
||||
'fantasy' => true,
|
||||
'cursive' => true
|
||||
);
|
||||
$allowed_fonts = $config->get('CSS.AllowedFonts');
|
||||
|
||||
// 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])) {
|
||||
if ($allowed_fonts === null || isset($allowed_fonts[$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 ($allowed_fonts !== null && !isset($allowed_fonts[$font])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Here, there are various classes of characters which need
|
||||
// to be treated differently:
|
||||
// - Alphanumeric characters are essentially safe. We
|
||||
// handled these above.
|
||||
// - Spaces require quoting, though most parsers will do
|
||||
// the right thing if there aren't any characters that
|
||||
// can be misinterpreted
|
||||
// - Dashes rarely occur, but they fairly unproblematic
|
||||
// for parsing/rendering purposes.
|
||||
// The above characters cover the majority of Western font
|
||||
// names.
|
||||
// - Arbitrary Unicode characters not in ASCII. Because
|
||||
// most parsers give little thought to Unicode, treatment
|
||||
// of these codepoints is basically uniform, even for
|
||||
// punctuation-like codepoints. These characters can
|
||||
// show up in non-Western pages and are supported by most
|
||||
// major browsers, for example: "MS 明朝" is a
|
||||
// legitimate font-name
|
||||
// <http://ja.wikipedia.org/wiki/MS_明朝>. See
|
||||
// the CSS3 spec for more examples:
|
||||
// <http://www.w3.org/TR/2011/WD-css3-fonts-20110324/localizedfamilynames.png>
|
||||
// You can see live samples of these on the Internet:
|
||||
// <http://www.google.co.jp/search?q=font-family+MS+明朝|ゴシック>
|
||||
// However, most of these fonts have ASCII equivalents:
|
||||
// for example, 'MS Mincho', and it's considered
|
||||
// professional to use ASCII font names instead of
|
||||
// Unicode font names. Thanks Takeshi Terada for
|
||||
// providing this information.
|
||||
// The following characters, to my knowledge, have not been
|
||||
// used to name font names.
|
||||
// - Single quote. While theoretically you might find a
|
||||
// font name that has a single quote in its name (serving
|
||||
// as an apostrophe, e.g. Dave's Scribble), I haven't
|
||||
// been able to find any actual examples of this.
|
||||
// Internet Explorer's cssText translation (which I
|
||||
// believe is invoked by innerHTML) normalizes any
|
||||
// quoting to single quotes, and fails to escape single
|
||||
// quotes. (Note that this is not IE's behavior for all
|
||||
// CSS properties, just some sort of special casing for
|
||||
// font-family). So a single quote *cannot* be used
|
||||
// safely in the font-family context if there will be an
|
||||
// innerHTML/cssText translation. Note that Firefox 3.x
|
||||
// does this too.
|
||||
// - Double quote. In IE, these get normalized to
|
||||
// single-quotes, no matter what the encoding. (Fun
|
||||
// fact, in IE8, the 'content' CSS property gained
|
||||
// support, where they special cased to preserve encoded
|
||||
// double quotes, but still translate unadorned double
|
||||
// quotes into single quotes.) So, because their
|
||||
// fixpoint behavior is identical to single quotes, they
|
||||
// cannot be allowed either. Firefox 3.x displays
|
||||
// single-quote style behavior.
|
||||
// - Backslashes are reduced by one (so \\ -> \) every
|
||||
// iteration, so they cannot be used safely. This shows
|
||||
// up in IE7, IE8 and FF3
|
||||
// - Semicolons, commas and backticks are handled properly.
|
||||
// - The rest of the ASCII punctuation is handled properly.
|
||||
// We haven't checked what browsers do to unadorned
|
||||
// versions, but this is not important as long as the
|
||||
// browser doesn't /remove/ surrounding quotes (as IE does
|
||||
// for HTML).
|
||||
//
|
||||
// With these results in hand, we conclude that there are
|
||||
// various levels of safety:
|
||||
// - Paranoid: alphanumeric, spaces and dashes(?)
|
||||
// - International: Paranoid + non-ASCII Unicode
|
||||
// - Edgy: Everything except quotes, backslashes
|
||||
// - NoJS: Standards compliance, e.g. sod IE. Note that
|
||||
// with some judicious character escaping (since certain
|
||||
// types of escaping doesn't work) this is theoretically
|
||||
// OK as long as innerHTML/cssText is not called.
|
||||
// We believe that international is a reasonable default
|
||||
// (that we will implement now), and once we do more
|
||||
// extensive research, we may feel comfortable with dropping
|
||||
// it down to edgy.
|
||||
|
||||
// Edgy: alphanumeric, spaces, dashes, underscores and Unicode. Use of
|
||||
// str(c)spn assumes that the string was already well formed
|
||||
// Unicode (which of course it is).
|
||||
if (strspn($font, $this->mask) !== strlen($font)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Historical:
|
||||
// In the absence of innerHTML/cssText, these ugly
|
||||
// transforms don't pose a security risk (as \\ and \"
|
||||
// might--these escapes are not supported by most browsers).
|
||||
// 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. (NOTE: you can reduce the amount
|
||||
// of escapes by one depending on what quoting style you use)
|
||||
// $font = str_replace('\\', '\\5C ', $font);
|
||||
// $font = str_replace('"', '\\22 ', $font);
|
||||
// $font = str_replace("'", '\\27 ', $font);
|
||||
|
||||
// font possibly with spaces, requires quoting
|
||||
$final .= "'$font', ";
|
||||
}
|
||||
$final = rtrim($final, ', ');
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return $final;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a font family list according to CSS spec
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
protected $mask = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Lowercase letters
|
||||
$l = range('a', 'z');
|
||||
// Uppercase letters
|
||||
$u = range('A', 'Z');
|
||||
// Digits
|
||||
$d = range('0', '9');
|
||||
// Special bytes used by UTF-8
|
||||
$b = array_map('chr', range(0x80, 0xFF));
|
||||
// All valid characters for the mask
|
||||
$c = array_merge($l, $u, $d, $b);
|
||||
// Concatenate all valid characters into a string
|
||||
// Use '_- ' as an initial value
|
||||
$this->mask = array_reduce($c, function ($carry, $value) {
|
||||
return $carry . $value;
|
||||
}, '_- ');
|
||||
|
||||
/*
|
||||
PHP's internal strcspn implementation is
|
||||
O(length of string * length of mask), making it inefficient
|
||||
for large masks. However, it's still faster than
|
||||
preg_match 8)
|
||||
for (p = s1;;) {
|
||||
spanp = s2;
|
||||
do {
|
||||
if (*spanp == c || p == s1_end) {
|
||||
return p - s1;
|
||||
}
|
||||
} while (spanp++ < (s2_end - 1));
|
||||
c = *++p;
|
||||
}
|
||||
*/
|
||||
// possible optimization: invert the mask.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $generic_names = array(
|
||||
'serif' => true,
|
||||
'sans-serif' => true,
|
||||
'monospace' => true,
|
||||
'fantasy' => true,
|
||||
'cursive' => true
|
||||
);
|
||||
$allowed_fonts = $config->get('CSS.AllowedFonts');
|
||||
|
||||
// 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])) {
|
||||
if ($allowed_fonts === null || isset($allowed_fonts[$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 ($allowed_fonts !== null && !isset($allowed_fonts[$font])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Here, there are various classes of characters which need
|
||||
// to be treated differently:
|
||||
// - Alphanumeric characters are essentially safe. We
|
||||
// handled these above.
|
||||
// - Spaces require quoting, though most parsers will do
|
||||
// the right thing if there aren't any characters that
|
||||
// can be misinterpreted
|
||||
// - Dashes rarely occur, but they fairly unproblematic
|
||||
// for parsing/rendering purposes.
|
||||
// The above characters cover the majority of Western font
|
||||
// names.
|
||||
// - Arbitrary Unicode characters not in ASCII. Because
|
||||
// most parsers give little thought to Unicode, treatment
|
||||
// of these codepoints is basically uniform, even for
|
||||
// punctuation-like codepoints. These characters can
|
||||
// show up in non-Western pages and are supported by most
|
||||
// major browsers, for example: "MS 明朝" is a
|
||||
// legitimate font-name
|
||||
// <http://ja.wikipedia.org/wiki/MS_明朝>. See
|
||||
// the CSS3 spec for more examples:
|
||||
// <http://www.w3.org/TR/2011/WD-css3-fonts-20110324/localizedfamilynames.png>
|
||||
// You can see live samples of these on the Internet:
|
||||
// <http://www.google.co.jp/search?q=font-family+MS+明朝|ゴシック>
|
||||
// However, most of these fonts have ASCII equivalents:
|
||||
// for example, 'MS Mincho', and it's considered
|
||||
// professional to use ASCII font names instead of
|
||||
// Unicode font names. Thanks Takeshi Terada for
|
||||
// providing this information.
|
||||
// The following characters, to my knowledge, have not been
|
||||
// used to name font names.
|
||||
// - Single quote. While theoretically you might find a
|
||||
// font name that has a single quote in its name (serving
|
||||
// as an apostrophe, e.g. Dave's Scribble), I haven't
|
||||
// been able to find any actual examples of this.
|
||||
// Internet Explorer's cssText translation (which I
|
||||
// believe is invoked by innerHTML) normalizes any
|
||||
// quoting to single quotes, and fails to escape single
|
||||
// quotes. (Note that this is not IE's behavior for all
|
||||
// CSS properties, just some sort of special casing for
|
||||
// font-family). So a single quote *cannot* be used
|
||||
// safely in the font-family context if there will be an
|
||||
// innerHTML/cssText translation. Note that Firefox 3.x
|
||||
// does this too.
|
||||
// - Double quote. In IE, these get normalized to
|
||||
// single-quotes, no matter what the encoding. (Fun
|
||||
// fact, in IE8, the 'content' CSS property gained
|
||||
// support, where they special cased to preserve encoded
|
||||
// double quotes, but still translate unadorned double
|
||||
// quotes into single quotes.) So, because their
|
||||
// fixpoint behavior is identical to single quotes, they
|
||||
// cannot be allowed either. Firefox 3.x displays
|
||||
// single-quote style behavior.
|
||||
// - Backslashes are reduced by one (so \\ -> \) every
|
||||
// iteration, so they cannot be used safely. This shows
|
||||
// up in IE7, IE8 and FF3
|
||||
// - Semicolons, commas and backticks are handled properly.
|
||||
// - The rest of the ASCII punctuation is handled properly.
|
||||
// We haven't checked what browsers do to unadorned
|
||||
// versions, but this is not important as long as the
|
||||
// browser doesn't /remove/ surrounding quotes (as IE does
|
||||
// for HTML).
|
||||
//
|
||||
// With these results in hand, we conclude that there are
|
||||
// various levels of safety:
|
||||
// - Paranoid: alphanumeric, spaces and dashes(?)
|
||||
// - International: Paranoid + non-ASCII Unicode
|
||||
// - Edgy: Everything except quotes, backslashes
|
||||
// - NoJS: Standards compliance, e.g. sod IE. Note that
|
||||
// with some judicious character escaping (since certain
|
||||
// types of escaping doesn't work) this is theoretically
|
||||
// OK as long as innerHTML/cssText is not called.
|
||||
// We believe that international is a reasonable default
|
||||
// (that we will implement now), and once we do more
|
||||
// extensive research, we may feel comfortable with dropping
|
||||
// it down to edgy.
|
||||
|
||||
// Edgy: alphanumeric, spaces, dashes, underscores and Unicode. Use of
|
||||
// str(c)spn assumes that the string was already well formed
|
||||
// Unicode (which of course it is).
|
||||
if (strspn($font, $this->mask) !== strlen($font)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Historical:
|
||||
// In the absence of innerHTML/cssText, these ugly
|
||||
// transforms don't pose a security risk (as \\ and \"
|
||||
// might--these escapes are not supported by most browsers).
|
||||
// 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. (NOTE: you can reduce the amount
|
||||
// of escapes by one depending on what quoting style you use)
|
||||
// $font = str_replace('\\', '\\5C ', $font);
|
||||
// $font = str_replace('"', '\\22 ', $font);
|
||||
// $font = str_replace("'", '\\27 ', $font);
|
||||
|
||||
// font possibly with spaces, requires quoting
|
||||
$final .= "'$font', ";
|
||||
}
|
||||
$final = rtrim($final, ', ');
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return $final;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,32 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates based on {ident} CSS grammar production
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
|
||||
// early abort: '' and '0' (strings that convert to false) are invalid
|
||||
if (!$string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
|
||||
if (!preg_match($pattern, $string)) {
|
||||
return false;
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates based on {ident} CSS grammar production
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
|
||||
// early abort: '' and '0' (strings that convert to false) are invalid
|
||||
if (!$string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
|
||||
if (!preg_match($pattern, $string)) {
|
||||
return false;
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+56
-56
@@ -1,56 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Decorator which enables !important to be used in CSS values.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
public $def;
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
public $allow;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $def Definition to wrap
|
||||
* @param bool $allow Whether or not to allow !important
|
||||
*/
|
||||
public function __construct($def, $allow = false)
|
||||
{
|
||||
$this->def = $def;
|
||||
$this->allow = $allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts and removes !important if necessary
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
// test for ! and important tokens
|
||||
$string = trim($string);
|
||||
$is_important = false;
|
||||
// :TODO: optimization: test directly for !important and ! important
|
||||
if (strlen($string) >= 9 && substr($string, -9) === 'important') {
|
||||
$temp = rtrim(substr($string, 0, -9));
|
||||
// use a temp, because we might want to restore important
|
||||
if (strlen($temp) >= 1 && substr($temp, -1) === '!') {
|
||||
$string = rtrim(substr($temp, 0, -1));
|
||||
$is_important = true;
|
||||
}
|
||||
}
|
||||
$string = $this->def->validate($string, $config, $context);
|
||||
if ($this->allow && $is_important) {
|
||||
$string .= ' !important';
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Decorator which enables !important to be used in CSS values.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
public $def;
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
public $allow;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $def Definition to wrap
|
||||
* @param bool $allow Whether or not to allow !important
|
||||
*/
|
||||
public function __construct($def, $allow = false)
|
||||
{
|
||||
$this->def = $def;
|
||||
$this->allow = $allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts and removes !important if necessary
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
// test for ! and important tokens
|
||||
$string = trim($string);
|
||||
$is_important = false;
|
||||
// :TODO: optimization: test directly for !important and ! important
|
||||
if (strlen($string) >= 9 && substr($string, -9) === 'important') {
|
||||
$temp = rtrim(substr($string, 0, -9));
|
||||
// use a temp, because we might want to restore important
|
||||
if (strlen($temp) >= 1 && substr($temp, -1) === '!') {
|
||||
$string = rtrim(substr($temp, 0, -1));
|
||||
$is_important = true;
|
||||
}
|
||||
}
|
||||
$string = $this->def->validate($string, $config, $context);
|
||||
if ($this->allow && $is_important) {
|
||||
$string .= ' !important';
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,77 +1,77 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Represents a Length as defined by CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Length|string
|
||||
*/
|
||||
protected $min;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Length|string
|
||||
*/
|
||||
protected $max;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Length|string $min Minimum length, or null for no bound. String is also acceptable.
|
||||
* @param HTMLPurifier_Length|string $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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Represents a Length as defined by CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Length|string
|
||||
*/
|
||||
protected $min;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Length|string
|
||||
*/
|
||||
protected $max;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Length|string $min Minimum length, or null for no bound. String is also acceptable.
|
||||
* @param HTMLPurifier_Length|string $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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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
|
||||
+112
-112
@@ -1,112 +1,112 @@
|
||||
<?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 validators.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
|
||||
*/
|
||||
protected $info;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
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'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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
|
||||
<?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 validators.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
|
||||
*/
|
||||
protected $info;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
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'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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,71 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Framework class for strings that involve multiple values.
|
||||
*
|
||||
* Certain CSS properties such as border-width and margin allow multiple
|
||||
* lengths to be specified. This class can take a vanilla border-width
|
||||
* definition and multiply it, usually into a max of four.
|
||||
*
|
||||
* @note Even though the CSS specification isn't clear about it, inherit
|
||||
* can only be used alone: it will never manifest as part of a multi
|
||||
* shorthand declaration. Thus, this class does not allow inherit.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* Instance of component definition to defer validation to.
|
||||
* @type HTMLPurifier_AttrDef
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $single;
|
||||
|
||||
/**
|
||||
* Max number of values allowed.
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $max;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $single HTMLPurifier_AttrDef to multiply
|
||||
* @param int $max Max number of values allowed (usually four)
|
||||
*/
|
||||
public function __construct($single, $max = 4)
|
||||
{
|
||||
$this->single = $single;
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->mungeRgb($this->parseCDATA($string));
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
$parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
|
||||
$length = count($parts);
|
||||
$final = '';
|
||||
for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) {
|
||||
if (ctype_space($parts[$i])) {
|
||||
continue;
|
||||
}
|
||||
$result = $this->single->validate($parts[$i], $config, $context);
|
||||
if ($result !== false) {
|
||||
$final .= $result . ' ';
|
||||
$num++;
|
||||
}
|
||||
}
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return rtrim($final);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Framework class for strings that involve multiple values.
|
||||
*
|
||||
* Certain CSS properties such as border-width and margin allow multiple
|
||||
* lengths to be specified. This class can take a vanilla border-width
|
||||
* definition and multiply it, usually into a max of four.
|
||||
*
|
||||
* @note Even though the CSS specification isn't clear about it, inherit
|
||||
* can only be used alone: it will never manifest as part of a multi
|
||||
* shorthand declaration. Thus, this class does not allow inherit.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* Instance of component definition to defer validation to.
|
||||
* @type HTMLPurifier_AttrDef
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $single;
|
||||
|
||||
/**
|
||||
* Max number of values allowed.
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $max;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $single HTMLPurifier_AttrDef to multiply
|
||||
* @param int $max Max number of values allowed (usually four)
|
||||
*/
|
||||
public function __construct($single, $max = 4)
|
||||
{
|
||||
$this->single = $single;
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->mungeRgb($this->parseCDATA($string));
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
$parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
|
||||
$length = count($parts);
|
||||
$final = '';
|
||||
for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) {
|
||||
if (ctype_space($parts[$i])) {
|
||||
continue;
|
||||
}
|
||||
$result = $this->single->validate($parts[$i], $config, $context);
|
||||
if ($result !== false) {
|
||||
$final .= $result . ' ';
|
||||
$num++;
|
||||
}
|
||||
}
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return rtrim($final);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,90 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a number as defined by the CSS spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Indicates whether or not only positive values are allowed.
|
||||
* @type bool
|
||||
*/
|
||||
protected $non_negative = false;
|
||||
|
||||
/**
|
||||
* @param bool $non_negative indicates whether negatives are forbidden
|
||||
*/
|
||||
public function __construct($non_negative = false)
|
||||
{
|
||||
$this->non_negative = $non_negative;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return string|bool
|
||||
* @warning Some contexts do not pass $config, $context. These
|
||||
* variables should not be used without checking HTMLPurifier_Length
|
||||
*/
|
||||
public function validate($number, $config, $context)
|
||||
{
|
||||
$number = $this->parseCDATA($number);
|
||||
|
||||
if ($number === '') {
|
||||
return false;
|
||||
}
|
||||
if ($number === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$sign = '';
|
||||
switch ($number[0]) {
|
||||
case '-':
|
||||
if ($this->non_negative) {
|
||||
return false;
|
||||
}
|
||||
$sign = '-';
|
||||
case '+':
|
||||
$number = substr($number, 1);
|
||||
}
|
||||
|
||||
if (ctype_digit($number)) {
|
||||
$number = ltrim($number, '0');
|
||||
return $number ? $sign . $number : '0';
|
||||
}
|
||||
|
||||
// Period is the only non-numeric character allowed
|
||||
if (strpos($number, '.') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
list($left, $right) = explode('.', $number, 2);
|
||||
|
||||
if ($left === '' && $right === '') {
|
||||
return false;
|
||||
}
|
||||
if ($left !== '' && !ctype_digit($left)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove leading zeros until positive number or a zero stays left
|
||||
if (ltrim($left, '0') != '') {
|
||||
$left = ltrim($left, '0');
|
||||
} else {
|
||||
$left = '0';
|
||||
}
|
||||
|
||||
$right = rtrim($right, '0');
|
||||
|
||||
if ($right === '') {
|
||||
return $left ? $sign . $left : '0';
|
||||
} elseif (!ctype_digit($right)) {
|
||||
return false;
|
||||
}
|
||||
return $sign . $left . '.' . $right;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a number as defined by the CSS spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Indicates whether or not only positive values are allowed.
|
||||
* @type bool
|
||||
*/
|
||||
protected $non_negative = false;
|
||||
|
||||
/**
|
||||
* @param bool $non_negative indicates whether negatives are forbidden
|
||||
*/
|
||||
public function __construct($non_negative = false)
|
||||
{
|
||||
$this->non_negative = $non_negative;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return string|bool
|
||||
* @warning Some contexts do not pass $config, $context. These
|
||||
* variables should not be used without checking HTMLPurifier_Length
|
||||
*/
|
||||
public function validate($number, $config, $context)
|
||||
{
|
||||
$number = $this->parseCDATA($number);
|
||||
|
||||
if ($number === '') {
|
||||
return false;
|
||||
}
|
||||
if ($number === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$sign = '';
|
||||
switch ($number[0]) {
|
||||
case '-':
|
||||
if ($this->non_negative) {
|
||||
return false;
|
||||
}
|
||||
$sign = '-';
|
||||
case '+':
|
||||
$number = substr($number, 1);
|
||||
}
|
||||
|
||||
if (ctype_digit($number)) {
|
||||
$number = ltrim($number, '0');
|
||||
return $number ? $sign . $number : '0';
|
||||
}
|
||||
|
||||
// Period is the only non-numeric character allowed
|
||||
if (strpos($number, '.') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
list($left, $right) = explode('.', $number, 2);
|
||||
|
||||
if ($left === '' && $right === '') {
|
||||
return false;
|
||||
}
|
||||
if ($left !== '' && !ctype_digit($left)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove leading zeros until positive number or a zero stays left
|
||||
if (ltrim($left, '0') != '') {
|
||||
$left = ltrim($left, '0');
|
||||
} else {
|
||||
$left = '0';
|
||||
}
|
||||
|
||||
$right = rtrim($right, '0');
|
||||
|
||||
if ($right === '') {
|
||||
return $left ? $sign . $left : '0';
|
||||
} elseif (!ctype_digit($right)) {
|
||||
return false;
|
||||
}
|
||||
return $sign . $left . '.' . $right;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,54 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a Percentage as defined by the CSS spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance to defer number validation to.
|
||||
* @type HTMLPurifier_AttrDef_CSS_Number
|
||||
*/
|
||||
protected $number_def;
|
||||
|
||||
/**
|
||||
* @param bool $non_negative Whether to forbid negative values
|
||||
*/
|
||||
public function __construct($non_negative = false)
|
||||
{
|
||||
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a Percentage as defined by the CSS spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance to defer number validation to.
|
||||
* @type HTMLPurifier_AttrDef_CSS_Number
|
||||
*/
|
||||
protected $number_def;
|
||||
|
||||
/**
|
||||
* @param bool $non_negative Whether to forbid negative values
|
||||
*/
|
||||
public function __construct($non_negative = false)
|
||||
{
|
||||
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a ratio as defined by the CSS spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Ratio extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* @param string $ratio Ratio to validate
|
||||
* @param HTMLPurifier_Config $config Configuration options
|
||||
* @param HTMLPurifier_Context $context Context
|
||||
*
|
||||
* @return string|boolean
|
||||
*
|
||||
* @warning Some contexts do not pass $config, $context. These
|
||||
* variables should not be used without checking HTMLPurifier_Length
|
||||
*/
|
||||
public function validate($ratio, $config, $context)
|
||||
{
|
||||
$ratio = $this->parseCDATA($ratio);
|
||||
|
||||
$parts = explode('/', $ratio, 2);
|
||||
$length = count($parts);
|
||||
|
||||
if ($length < 1 || $length > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$num = new \HTMLPurifier_AttrDef_CSS_Number();
|
||||
|
||||
if ($length === 1) {
|
||||
return $num->validate($parts[0], $config, $context);
|
||||
}
|
||||
|
||||
$num1 = $num->validate($parts[0], $config, $context);
|
||||
$num2 = $num->validate($parts[1], $config, $context);
|
||||
|
||||
if ($num1 === false || $num2 === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $num1 . '/' . $num2;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+46
-46
@@ -1,46 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates the value for the CSS property text-decoration
|
||||
* @note This class could be generalized into a version that acts sort of
|
||||
* like Enum except you can compound the allowed values.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $allowed_values = array(
|
||||
'line-through' => true,
|
||||
'overline' => true,
|
||||
'underline' => true,
|
||||
);
|
||||
|
||||
$string = strtolower($this->parseCDATA($string));
|
||||
|
||||
if ($string === 'none') {
|
||||
return $string;
|
||||
}
|
||||
|
||||
$parts = explode(' ', $string);
|
||||
$final = '';
|
||||
foreach ($parts as $part) {
|
||||
if (isset($allowed_values[$part])) {
|
||||
$final .= $part . ' ';
|
||||
}
|
||||
}
|
||||
$final = rtrim($final);
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return $final;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates the value for the CSS property text-decoration
|
||||
* @note This class could be generalized into a version that acts sort of
|
||||
* like Enum except you can compound the allowed values.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $allowed_values = array(
|
||||
'line-through' => true,
|
||||
'overline' => true,
|
||||
'underline' => true,
|
||||
);
|
||||
|
||||
$string = strtolower($this->parseCDATA($string));
|
||||
|
||||
if ($string === 'none') {
|
||||
return $string;
|
||||
}
|
||||
|
||||
$parts = explode(' ', $string);
|
||||
$final = '';
|
||||
foreach ($parts as $part) {
|
||||
if (isset($allowed_values[$part])) {
|
||||
$final .= $part . ' ';
|
||||
}
|
||||
}
|
||||
$final = rtrim($final);
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return $final;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+77
-77
@@ -1,77 +1,77 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a URI in CSS syntax, which uses url('http://example.com')
|
||||
* @note While theoretically speaking a URI in a CSS document could
|
||||
* be non-embedded, as of CSS2 there is no such usage so we're
|
||||
* generalizing it. This may need to be changed in the future.
|
||||
* @warning Since HTMLPurifier_AttrDef_CSS blindly uses semicolons as
|
||||
* the separator, you cannot put a literal semicolon in
|
||||
* in the URI. Try percent encoding it, in that case.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(true); // always embedded
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri_string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($uri_string, $config, $context)
|
||||
{
|
||||
// parse the URI out of the string and then pass it onto
|
||||
// the parent object
|
||||
|
||||
$uri_string = $this->parseCDATA($uri_string);
|
||||
if (strpos($uri_string, 'url(') !== 0) {
|
||||
return false;
|
||||
}
|
||||
$uri_string = substr($uri_string, 4);
|
||||
if (strlen($uri_string) == 0) {
|
||||
return false;
|
||||
}
|
||||
$new_length = strlen($uri_string) - 1;
|
||||
if ($uri_string[$new_length] != ')') {
|
||||
return false;
|
||||
}
|
||||
$uri = trim(substr($uri_string, 0, $new_length));
|
||||
|
||||
if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) {
|
||||
$quote = $uri[0];
|
||||
$new_length = strlen($uri) - 1;
|
||||
if ($uri[$new_length] !== $quote) {
|
||||
return false;
|
||||
}
|
||||
$uri = substr($uri, 1, $new_length - 1);
|
||||
}
|
||||
|
||||
$uri = $this->expandCSSEscape($uri);
|
||||
|
||||
$result = parent::validate($uri, $config, $context);
|
||||
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// extra sanity check; should have been done by URI
|
||||
$result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
|
||||
|
||||
// suspicious characters are ()'; we're going to percent encode
|
||||
// them for safety.
|
||||
$result = str_replace(array('(', ')', "'"), array('%28', '%29', '%27'), $result);
|
||||
|
||||
// there's an extra bug where ampersands lose their escaping on
|
||||
// an innerHTML cycle, so a very unlucky query parameter could
|
||||
// then change the meaning of the URL. Unfortunately, there's
|
||||
// not much we can do about that...
|
||||
return "url(\"$result\")";
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a URI in CSS syntax, which uses url('http://example.com')
|
||||
* @note While theoretically speaking a URI in a CSS document could
|
||||
* be non-embedded, as of CSS2 there is no such usage so we're
|
||||
* generalizing it. This may need to be changed in the future.
|
||||
* @warning Since HTMLPurifier_AttrDef_CSS blindly uses semicolons as
|
||||
* the separator, you cannot put a literal semicolon in
|
||||
* in the URI. Try percent encoding it, in that case.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(true); // always embedded
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri_string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($uri_string, $config, $context)
|
||||
{
|
||||
// parse the URI out of the string and then pass it onto
|
||||
// the parent object
|
||||
|
||||
$uri_string = $this->parseCDATA($uri_string);
|
||||
if (strpos($uri_string, 'url(') !== 0) {
|
||||
return false;
|
||||
}
|
||||
$uri_string = substr($uri_string, 4);
|
||||
if (strlen($uri_string) == 0) {
|
||||
return false;
|
||||
}
|
||||
$new_length = strlen($uri_string) - 1;
|
||||
if ($uri_string[$new_length] != ')') {
|
||||
return false;
|
||||
}
|
||||
$uri = trim(substr($uri_string, 0, $new_length));
|
||||
|
||||
if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) {
|
||||
$quote = $uri[0];
|
||||
$new_length = strlen($uri) - 1;
|
||||
if ($uri[$new_length] !== $quote) {
|
||||
return false;
|
||||
}
|
||||
$uri = substr($uri, 1, $new_length - 1);
|
||||
}
|
||||
|
||||
$uri = $this->expandCSSEscape($uri);
|
||||
|
||||
$result = parent::validate($uri, $config, $context);
|
||||
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// extra sanity check; should have been done by URI
|
||||
$result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
|
||||
|
||||
// suspicious characters are ()'; we're going to percent encode
|
||||
// them for safety.
|
||||
$result = str_replace(array('(', ')', "'"), array('%28', '%29', '%27'), $result);
|
||||
|
||||
// there's an extra bug where ampersands lose their escaping on
|
||||
// an innerHTML cycle, so a very unlucky query parameter could
|
||||
// then change the meaning of the URL. Unfortunately, there's
|
||||
// not much we can do about that...
|
||||
return "url(\"$result\")";
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+44
-44
@@ -1,44 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dummy AttrDef that mimics another AttrDef, BUT it generates clones
|
||||
* with make.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* What we're cloning.
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
protected $clone;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $clone
|
||||
*/
|
||||
public function __construct($clone)
|
||||
{
|
||||
$this->clone = $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $v
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($v, $config, $context)
|
||||
{
|
||||
return $this->clone->validate($v, $config, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return HTMLPurifier_AttrDef
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
return clone $this->clone;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dummy AttrDef that mimics another AttrDef, BUT it generates clones
|
||||
* with make.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* What we're cloning.
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
protected $clone;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $clone
|
||||
*/
|
||||
public function __construct($clone)
|
||||
{
|
||||
$this->clone = $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $v
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($v, $config, $context)
|
||||
{
|
||||
return $this->clone->validate($v, $config, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return HTMLPurifier_AttrDef
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
return clone $this->clone;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
+73
-73
@@ -1,73 +1,73 @@
|
||||
<?php
|
||||
|
||||
// Enum = Enumerated
|
||||
/**
|
||||
* Validates a keyword against a list of valid values.
|
||||
* @warning The case-insensitive compare of this function uses PHP's
|
||||
* built-in strtolower and ctype_lower functions, which may
|
||||
* cause problems with international comparisons
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Lookup table of valid values.
|
||||
* @type array
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $valid_values = array();
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not enumeration is case sensitive.
|
||||
* @note In general this is always case insensitive.
|
||||
*/
|
||||
protected $case_sensitive = false; // values according to W3C spec
|
||||
|
||||
/**
|
||||
* @param array $valid_values List of valid values
|
||||
* @param bool $case_sensitive Whether or not case sensitive
|
||||
*/
|
||||
public function __construct($valid_values = array(), $case_sensitive = false)
|
||||
{
|
||||
$this->valid_values = array_flip($valid_values);
|
||||
$this->case_sensitive = $case_sensitive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
if (!$this->case_sensitive) {
|
||||
// we may want to do full case-insensitive libraries
|
||||
$string = ctype_lower($string) ? $string : strtolower($string);
|
||||
}
|
||||
$result = isset($this->valid_values[$string]);
|
||||
|
||||
return $result ? $string : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string In form of comma-delimited list of case-insensitive
|
||||
* valid values. Example: "foo,bar,baz". Prepend "s:" to make
|
||||
* case sensitive
|
||||
* @return HTMLPurifier_AttrDef_Enum
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') {
|
||||
$string = substr($string, 2);
|
||||
$sensitive = true;
|
||||
} else {
|
||||
$sensitive = false;
|
||||
}
|
||||
$values = explode(',', $string);
|
||||
return new HTMLPurifier_AttrDef_Enum($values, $sensitive);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
// Enum = Enumerated
|
||||
/**
|
||||
* Validates a keyword against a list of valid values.
|
||||
* @warning The case-insensitive compare of this function uses PHP's
|
||||
* built-in strtolower and ctype_lower functions, which may
|
||||
* cause problems with international comparisons
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Lookup table of valid values.
|
||||
* @type array
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $valid_values = array();
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not enumeration is case sensitive.
|
||||
* @note In general this is always case insensitive.
|
||||
*/
|
||||
protected $case_sensitive = false; // values according to W3C spec
|
||||
|
||||
/**
|
||||
* @param array $valid_values List of valid values
|
||||
* @param bool $case_sensitive Whether or not case sensitive
|
||||
*/
|
||||
public function __construct($valid_values = array(), $case_sensitive = false)
|
||||
{
|
||||
$this->valid_values = array_flip($valid_values);
|
||||
$this->case_sensitive = $case_sensitive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
if (!$this->case_sensitive) {
|
||||
// we may want to do full case-insensitive libraries
|
||||
$string = ctype_lower($string) ? $string : strtolower($string);
|
||||
}
|
||||
$result = isset($this->valid_values[$string]);
|
||||
|
||||
return $result ? $string : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string In form of comma-delimited list of case-insensitive
|
||||
* valid values. Example: "foo,bar,baz". Prepend "s:" to make
|
||||
* case sensitive
|
||||
* @return HTMLPurifier_AttrDef_Enum
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') {
|
||||
$string = substr($string, 2);
|
||||
$sensitive = true;
|
||||
} else {
|
||||
$sensitive = false;
|
||||
}
|
||||
$values = explode(',', $string);
|
||||
return new HTMLPurifier_AttrDef_Enum($values, $sensitive);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,48 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a boolean attribute
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
public $minimized = true;
|
||||
|
||||
/**
|
||||
* @param bool|string $name
|
||||
*/
|
||||
public function __construct($name = false)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string Name of attribute
|
||||
* @return HTMLPurifier_AttrDef_HTML_Bool
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
return new HTMLPurifier_AttrDef_HTML_Bool($string);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a boolean attribute
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
public $minimized = true;
|
||||
|
||||
/**
|
||||
* @param bool|string $name
|
||||
*/
|
||||
public function __construct($name = false)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string Name of attribute
|
||||
* @return HTMLPurifier_AttrDef_HTML_Bool
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
return new HTMLPurifier_AttrDef_HTML_Bool($string);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
@@ -1,48 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements special behavior for class attribute (normally NMTOKENS)
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
|
||||
{
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function split($string, $config, $context)
|
||||
{
|
||||
// really, this twiddle should be lazy loaded
|
||||
$name = $config->getDefinition('HTML')->doctype->name;
|
||||
if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
|
||||
return parent::split($string, $config, $context);
|
||||
} else {
|
||||
return preg_split('/\s+/', $string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tokens
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
protected function filter($tokens, $config, $context)
|
||||
{
|
||||
$allowed = $config->get('Attr.AllowedClasses');
|
||||
$forbidden = $config->get('Attr.ForbiddenClasses');
|
||||
$ret = array();
|
||||
foreach ($tokens as $token) {
|
||||
if (($allowed === null || isset($allowed[$token])) &&
|
||||
!isset($forbidden[$token]) &&
|
||||
// We need this O(n) check because of PHP's array
|
||||
// implementation that casts -0 to 0.
|
||||
!in_array($token, $ret, true)
|
||||
) {
|
||||
$ret[] = $token;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements special behavior for class attribute (normally NMTOKENS)
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
|
||||
{
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function split($string, $config, $context)
|
||||
{
|
||||
// really, this twiddle should be lazy loaded
|
||||
$name = $config->getDefinition('HTML')->doctype->name;
|
||||
if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
|
||||
return parent::split($string, $config, $context);
|
||||
} else {
|
||||
return preg_split('/\s+/', $string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tokens
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
protected function filter($tokens, $config, $context)
|
||||
{
|
||||
$allowed = $config->get('Attr.AllowedClasses');
|
||||
$forbidden = $config->get('Attr.ForbiddenClasses');
|
||||
$ret = array();
|
||||
foreach ($tokens as $token) {
|
||||
if (($allowed === null || isset($allowed[$token])) &&
|
||||
!isset($forbidden[$token]) &&
|
||||
// We need this O(n) check because of PHP's array
|
||||
// implementation that casts -0 to 0.
|
||||
!in_array($token, $ret, true)
|
||||
) {
|
||||
$ret[] = $token;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a color according to the HTML spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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;
|
||||
}
|
||||
$lower = strtolower($string);
|
||||
if (isset($colors[$lower])) {
|
||||
return $colors[$lower];
|
||||
}
|
||||
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
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates a color according to the HTML spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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;
|
||||
}
|
||||
$lower = strtolower($string);
|
||||
if (isset($colors[$lower])) {
|
||||
return $colors[$lower];
|
||||
}
|
||||
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,38 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Special-case enum attribute definition that lazy loads allowed frame targets
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
|
||||
{
|
||||
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
public $valid_values = false; // uninitialized value
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
protected $case_sensitive = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Special-case enum attribute definition that lazy loads allowed frame targets
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
|
||||
{
|
||||
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
public $valid_values = false; // uninitialized value
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
protected $case_sensitive = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
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
|
||||
Loaded 100 of 6736 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user