purify

repository·master·Indexed 19 days ago

https://github.com/stevebauman/purify

A Laravel wrapper for HTMLPurifier used to sanitize HTML input and prevent XSS attacks. It supports cleaning strings and arrays, provides dynamic and named configurations, and integrates with Eloquent models via custom casts like PurifyHtmlOnGet and PurifyHtmlOnSet. The package includes support for custom HTML and CSS definitions, a cache clearing Artisan command, and a facade for easy access to the purification engine.

Tokens
4K
Snippets
19
Records
19
Agent score
68%

What's inside purify

  1. Manage HTMLPurifier cache

    master

    HTMLPurifier auto-caches serialized definitions to improve performance.

    Clearing the Cache

    If you update your definitions configuration, you must clear the cache using the Artisan command:

    php artisan purify:clear

    Warning: This command will issue a Cache::clear() if using CacheDefinitionCache, or clear the configured directory if using FilesystemDefinitionCache.

    Disabling Caching

    To disable caching (useful for debugging), set the serializer option to null in config/purify.php:

    'serializer' => null,

    Note: Caching is highly recommended for production environments.

  2. Install Purify

    master

    To install Purify in your Laravel project, run the following composer command:

    composer require stevebauman/purify

    After installation, publish the configuration file using the Artisan command:

    php artisan vendor:publish --provider="Stevebauman\Purify\PurifyServiceProvider"

    Requirements:

    • PHP >= 7.4
    • Laravel >= 7.0
    composer require stevebauman/purify
    php artisan vendor:publish --provider="Stevebauman\Purify\PurifyServiceProvider"
  3. Create custom CSS definitions

    master

    To customize allowed inline styles, properties, or values (e.g., adding start and end to text-align), implement the CssDefinition interface.

    1. Create a class implementing Stevebauman\Purify\Definitions\CssDefinition.
    2. In the apply method, modify the $definition->info array.
    3. Register the class in config/purify.php under the css-definitions key.
    namespace App;
    
    use HTMLPurifier_CSSDefinition;
    use Stevebauman\Purify\Definitions\CssDefinition;
    
    class CustomCssDefinition implements CssDefinition
    {
        public static function apply(HTMLPurifier_CSSDefinition $definition)
        {
            $definition->info['text-align'] = new \HTMLPurifier_AttrDef_Enum(
                ['right', 'left', 'center', 'start', 'end'],
                false,
            );
        }
    }
    
    // In config/purify.php
    'css-definitions' => \App\CustomCssDefinition::class,
  4. Upgrade from v5 to v6

    master

    In v6, the serializer configuration was updated to support Laravel Vapor by allowing storage in Redis or an external filesystem.

    To upgrade, update your config/purify.php to use the new array-based serializer syntax.

    Option 1: Filesystem storage

    'serializer' => [
       'disk' => env('FILESYSTEM_DISK', 'local'),
       'path' => 'purify',
       'cache' => \Stevebauman\Purify\Cache\FilesystemDefinitionCache::class,
    ],

    Option 2: Cache driver (e.g., Redis) storage

    'serializer' => [
       'driver' => env('CACHE_DRIVER', 'file'),
       'cache' => \Stevebauman\Purify\Cache\CacheDefinitionCache::class,
    ],
    // Example v6 serializer config for filesystem
    'serializer' => [
       'disk' => env('FILESYSTEM_DISK', 'local'),
       'path' => 'purify',
       'cache' => \Stevebauman\Purify\Cache\FilesystemDefinitionCache::class,
    ],
  5. Create custom HTML definitions

    master

    To support custom elements or attributes (e.g., <foo>), implement the Definition interface and create an apply method.

    You can extend the built-in Html5Definition to ensure you keep standard HTML5 support while adding your own rules.

    1. Create a class implementing Stevebauman\Purify\Definitions\Definition.
    2. In the apply method, use the provided HTMLPurifier_HTMLDefinition instance to add elements or attributes.
    3. Register the class in config/purify.php under the definitions key.
    namespace App;
    
    use HTMLPurifier_HTMLDefinition;
    use Stevebauman\Purify\Definitions\Definition;
    use Stevebauman\Purify\Definitions\Html5Definition;
    
    class CustomDefinition implements Definition
    {
        public static function apply(HTMLPurifier_HTMLDefinition $definition)
        {
            // Extend standard HTML5 support
            Html5Definition::apply($definition);
            
            // Add custom element
            $definition->addElement('foo', 'Block', 'Flow', 'Common');
            // Add custom attribute
            $definition->addAttribute('foo', 'bar', 'Text');
        }
    }
    
    // In config/purify.php
    'definitions' => \App\CustomDefinition::class,
  6. Sanitize HTML on model retrieval (Best Practice)

    master

    It is recommended to sanitize HTML on the way out (when reading from the database) rather than on the way in. This allows you to change sanitization rules later without losing data.

    Using Eloquent Casts

    You can use the PurifyHtmlOnGet cast class on your model.

    For Laravel 11.x and newer:

    use Stevebauman\Purify\Casts\PurifyHtmlOnGet;
    
    protected function casts(): array
    {
        return [
            'content' => PurifyHtmlOnGet::class,
        ];
    }

    For Laravel <= 10.x:

    protected $casts = [
        'content' => PurifyHtmlOnGet::class,
    ];

    Using Named Casts

    You can specify a named configuration for the cast by appending it with a colon:

    // Laravel 11.x
    protected function casts(): array
    {
        return [
            'content' => PurifyHtmlOnGet::class . ':other',
        ];
    }

    (This assumes a configuration named other exists in config/purify.php).

    Using Mutators

    Alternatively, you can implement a manual attribute mutator:

    public function getContentAttribute($value)
    {
        return Purify::clean($value);
    }
    use Stevebauman\Purify\Casts\PurifyHtmlOnGet;
    
    class Post extends Model
    {
        protected function casts(): array
        {
            return [
                'content' => PurifyHtmlOnGet::class,
            ];
        }
    }
  7. Configure multiple Purify settings

    master

    In config/purify.php, you can define multiple named configuration sets within the configs array. This allows different parts of your application (e.g., a comment system vs. a blog post editor) to use different sanitization rules.

    Example structure in config/purify.php:

    'configs' => [
        'comments' => [
            // HTMLPurifier settings here
        ],
    ],

    For a full list of available HTMLPurifier configuration options, refer to the HTMLPurifier documentation.

    // config/purify.php
    
    'configs' => [
        'comments' => [
            'HTML.Allowed' => 'p,b,i',
        ],
    ]
  8. Clean a string or array with Purify

    master

    Use the Purify::clean() method to sanitize HTML input. It accepts either a single string or an array of strings.

    • String input: Returns a single cleaned string.
    • Array input: Returns an array of cleaned strings.
    use Stevebauman\
    Purify\
    \"Facades\";
    \"Purify\";
    
    // Cleaning a string
    $input = '<script>alert("Harmful");</script> <p>Test</p>';
    $cleaned = Purify::clean($input);
    // Returns '<p>Test</p>'
    
    // Cleaning an array
    $array = ['<script>...</script> <p>Test 1</p>', '<p>Test 2</p>'];
    $cleaned = Purify::clean($array);
    // Returns ['<p>Test 1</p>', '<p>Test 2</p>']
  9. Use dynamic or named configurations

    master

    You can apply specific configurations to a single input without changing the global defaults.

    1. Dynamic Configuration: Pass an associative array of HTMLPurifier settings directly to the config() method. Note that this configuration is not merged with your default configuration; it replaces it for that call.
    2. Named Configurations: Define multiple configuration sets in config/purify.php under the configs key. You can then access them by name using Purify::config('name')->clean($input).
    use Stevebauman\Purify\Facades\Purify;
    
    // 1. Dynamic configuration (replaces defaults for this call)
    $config = ['HTML.Allowed' => 'div,b,a[href]'];
    $cleaned = Purify::config($config)->clean($input);
    
    // 2. Using a named configuration from config/purify.php
    $cleanedContent = Purify::config('comments')->clean($input);
  10. Configure Purify via the Facade

    master

    Use Purify::config() to interact with the Purify configuration. You can pass a driver name or an array of configuration settings to retrieve or set the configuration state.

    use Stevebauman//Purify//Facades//Purify;
    
    // Get the current configuration
    $config = Purify::config();
    
    // Set configuration for a specific driver
    Purify::config(['some_key' => 'some_value']);
  11. Access the underlying HTMLPurifier instance

    master

    If you need to access the raw HTMLPurifier object to perform advanced configuration or use specific HTMLPurifier methods not exposed by the Purify wrapper, use Purify::getPurifier().

    use Stevebauman//Purify//Facades//Purify;
    
    $purifier = Purify::getPurifier();
    // $purifier is an instance of \HTMLPurifier