]> git.immae.eu Git - github/wallabag/wallabag.git/blobdiff - inc/3rdparty/htmlpurifier/HTMLPurifier/ConfigSchema/Validator.php
[add] HTML Purifier added to clean code
[github/wallabag/wallabag.git] / inc / 3rdparty / htmlpurifier / HTMLPurifier / ConfigSchema / Validator.php
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/ConfigSchema/Validator.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/ConfigSchema/Validator.php
new file mode 100644 (file)
index 0000000..9f14444
--- /dev/null
@@ -0,0 +1,248 @@
+<?php\r
+\r
+/**\r
+ * Performs validations on HTMLPurifier_ConfigSchema_Interchange\r
+ *\r
+ * @note If you see '// handled by InterchangeBuilder', that means a\r
+ *       design decision in that class would prevent this validation from\r
+ *       ever being necessary. We have them anyway, however, for\r
+ *       redundancy.\r
+ */\r
+class HTMLPurifier_ConfigSchema_Validator\r
+{\r
+\r
+    /**\r
+     * @type HTMLPurifier_ConfigSchema_Interchange\r
+     */\r
+    protected $interchange;\r
+\r
+    /**\r
+     * @type array\r
+     */\r
+    protected $aliases;\r
+\r
+    /**\r
+     * Context-stack to provide easy to read error messages.\r
+     * @type array\r
+     */\r
+    protected $context = array();\r
+\r
+    /**\r
+     * to test default's type.\r
+     * @type HTMLPurifier_VarParser\r
+     */\r
+    protected $parser;\r
+\r
+    public function __construct()\r
+    {\r
+        $this->parser = new HTMLPurifier_VarParser();\r
+    }\r
+\r
+    /**\r
+     * Validates a fully-formed interchange object.\r
+     * @param HTMLPurifier_ConfigSchema_Interchange $interchange\r
+     * @return bool\r
+     */\r
+    public function validate($interchange)\r
+    {\r
+        $this->interchange = $interchange;\r
+        $this->aliases = array();\r
+        // PHP is a bit lax with integer <=> string conversions in\r
+        // arrays, so we don't use the identical !== comparison\r
+        foreach ($interchange->directives as $i => $directive) {\r
+            $id = $directive->id->toString();\r
+            if ($i != $id) {\r
+                $this->error(false, "Integrity violation: key '$i' does not match internal id '$id'");\r
+            }\r
+            $this->validateDirective($directive);\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Validates a HTMLPurifier_ConfigSchema_Interchange_Id object.\r
+     * @param HTMLPurifier_ConfigSchema_Interchange_Id $id\r
+     */\r
+    public function validateId($id)\r
+    {\r
+        $id_string = $id->toString();\r
+        $this->context[] = "id '$id_string'";\r
+        if (!$id instanceof HTMLPurifier_ConfigSchema_Interchange_Id) {\r
+            // handled by InterchangeBuilder\r
+            $this->error(false, 'is not an instance of HTMLPurifier_ConfigSchema_Interchange_Id');\r
+        }\r
+        // keys are now unconstrained (we might want to narrow down to A-Za-z0-9.)\r
+        // we probably should check that it has at least one namespace\r
+        $this->with($id, 'key')\r
+            ->assertNotEmpty()\r
+            ->assertIsString(); // implicit assertIsString handled by InterchangeBuilder\r
+        array_pop($this->context);\r
+    }\r
+\r
+    /**\r
+     * Validates a HTMLPurifier_ConfigSchema_Interchange_Directive object.\r
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d\r
+     */\r
+    public function validateDirective($d)\r
+    {\r
+        $id = $d->id->toString();\r
+        $this->context[] = "directive '$id'";\r
+        $this->validateId($d->id);\r
+\r
+        $this->with($d, 'description')\r
+            ->assertNotEmpty();\r
+\r
+        // BEGIN - handled by InterchangeBuilder\r
+        $this->with($d, 'type')\r
+            ->assertNotEmpty();\r
+        $this->with($d, 'typeAllowsNull')\r
+            ->assertIsBool();\r
+        try {\r
+            // This also tests validity of $d->type\r
+            $this->parser->parse($d->default, $d->type, $d->typeAllowsNull);\r
+        } catch (HTMLPurifier_VarParserException $e) {\r
+            $this->error('default', 'had error: ' . $e->getMessage());\r
+        }\r
+        // END - handled by InterchangeBuilder\r
+\r
+        if (!is_null($d->allowed) || !empty($d->valueAliases)) {\r
+            // allowed and valueAliases require that we be dealing with\r
+            // strings, so check for that early.\r
+            $d_int = HTMLPurifier_VarParser::$types[$d->type];\r
+            if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) {\r
+                $this->error('type', 'must be a string type when used with allowed or value aliases');\r
+            }\r
+        }\r
+\r
+        $this->validateDirectiveAllowed($d);\r
+        $this->validateDirectiveValueAliases($d);\r
+        $this->validateDirectiveAliases($d);\r
+\r
+        array_pop($this->context);\r
+    }\r
+\r
+    /**\r
+     * Extra validation if $allowed member variable of\r
+     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.\r
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d\r
+     */\r
+    public function validateDirectiveAllowed($d)\r
+    {\r
+        if (is_null($d->allowed)) {\r
+            return;\r
+        }\r
+        $this->with($d, 'allowed')\r
+            ->assertNotEmpty()\r
+            ->assertIsLookup(); // handled by InterchangeBuilder\r
+        if (is_string($d->default) && !isset($d->allowed[$d->default])) {\r
+            $this->error('default', 'must be an allowed value');\r
+        }\r
+        $this->context[] = 'allowed';\r
+        foreach ($d->allowed as $val => $x) {\r
+            if (!is_string($val)) {\r
+                $this->error("value $val", 'must be a string');\r
+            }\r
+        }\r
+        array_pop($this->context);\r
+    }\r
+\r
+    /**\r
+     * Extra validation if $valueAliases member variable of\r
+     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.\r
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d\r
+     */\r
+    public function validateDirectiveValueAliases($d)\r
+    {\r
+        if (is_null($d->valueAliases)) {\r
+            return;\r
+        }\r
+        $this->with($d, 'valueAliases')\r
+            ->assertIsArray(); // handled by InterchangeBuilder\r
+        $this->context[] = 'valueAliases';\r
+        foreach ($d->valueAliases as $alias => $real) {\r
+            if (!is_string($alias)) {\r
+                $this->error("alias $alias", 'must be a string');\r
+            }\r
+            if (!is_string($real)) {\r
+                $this->error("alias target $real from alias '$alias'", 'must be a string');\r
+            }\r
+            if ($alias === $real) {\r
+                $this->error("alias '$alias'", "must not be an alias to itself");\r
+            }\r
+        }\r
+        if (!is_null($d->allowed)) {\r
+            foreach ($d->valueAliases as $alias => $real) {\r
+                if (isset($d->allowed[$alias])) {\r
+                    $this->error("alias '$alias'", 'must not be an allowed value');\r
+                } elseif (!isset($d->allowed[$real])) {\r
+                    $this->error("alias '$alias'", 'must be an alias to an allowed value');\r
+                }\r
+            }\r
+        }\r
+        array_pop($this->context);\r
+    }\r
+\r
+    /**\r
+     * Extra validation if $aliases member variable of\r
+     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.\r
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d\r
+     */\r
+    public function validateDirectiveAliases($d)\r
+    {\r
+        $this->with($d, 'aliases')\r
+            ->assertIsArray(); // handled by InterchangeBuilder\r
+        $this->context[] = 'aliases';\r
+        foreach ($d->aliases as $alias) {\r
+            $this->validateId($alias);\r
+            $s = $alias->toString();\r
+            if (isset($this->interchange->directives[$s])) {\r
+                $this->error("alias '$s'", 'collides with another directive');\r
+            }\r
+            if (isset($this->aliases[$s])) {\r
+                $other_directive = $this->aliases[$s];\r
+                $this->error("alias '$s'", "collides with alias for directive '$other_directive'");\r
+            }\r
+            $this->aliases[$s] = $d->id->toString();\r
+        }\r
+        array_pop($this->context);\r
+    }\r
+\r
+    // protected helper functions\r
+\r
+    /**\r
+     * Convenience function for generating HTMLPurifier_ConfigSchema_ValidatorAtom\r
+     * for validating simple member variables of objects.\r
+     * @param $obj\r
+     * @param $member\r
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom\r
+     */\r
+    protected function with($obj, $member)\r
+    {\r
+        return new HTMLPurifier_ConfigSchema_ValidatorAtom($this->getFormattedContext(), $obj, $member);\r
+    }\r
+\r
+    /**\r
+     * Emits an error, providing helpful context.\r
+     * @throws HTMLPurifier_ConfigSchema_Exception\r
+     */\r
+    protected function error($target, $msg)\r
+    {\r
+        if ($target !== false) {\r
+            $prefix = ucfirst($target) . ' in ' . $this->getFormattedContext();\r
+        } else {\r
+            $prefix = ucfirst($this->getFormattedContext());\r
+        }\r
+        throw new HTMLPurifier_ConfigSchema_Exception(trim($prefix . ' ' . $msg));\r
+    }\r
+\r
+    /**\r
+     * Returns a formatted context string.\r
+     * @return string\r
+     */\r
+    protected function getFormattedContext()\r
+    {\r
+        return implode(' in ', array_reverse($this->context));\r
+    }\r
+}\r
+\r
+// vim: et sw=4 sts=4\r