1<?php
2
3/**
4 * Registry for retrieving specific URI scheme validator objects.
5 */
6class HTMLPurifier_URISchemeRegistry
7{
8
9    /**
10     * Retrieve sole instance of the registry.
11     * @param HTMLPurifier_URISchemeRegistry $prototype Optional prototype to overload sole instance with,
12     *                   or bool true to reset to default registry.
13     * @return HTMLPurifier_URISchemeRegistry
14     * @note Pass a registry object $prototype with a compatible interface and
15     *       the function will copy it and return it all further times.
16     */
17    public static function instance($prototype = null)
18    {
19        static $instance = null;
20        if ($prototype !== null) {
21            $instance = $prototype;
22        } elseif ($instance === null || $prototype == true) {
23            $instance = new HTMLPurifier_URISchemeRegistry();
24        }
25        return $instance;
26    }
27
28    /**
29     * Cache of retrieved schemes.
30     * @type HTMLPurifier_URIScheme[]
31     */
32    protected $schemes = array();
33
34    /**
35     * Retrieves a scheme validator object
36     * @param string $scheme String scheme name like http or mailto
37     * @param HTMLPurifier_Config $config
38     * @param HTMLPurifier_Context $context
39     * @return HTMLPurifier_URIScheme
40     */
41    public function getScheme($scheme, $config, $context)
42    {
43        if (!$config) {
44            $config = HTMLPurifier_Config::createDefault();
45        }
46
47        // important, otherwise attacker could include arbitrary file
48        $allowed_schemes = $config->get('URI.AllowedSchemes');
49        if (!$config->get('URI.OverrideAllowedSchemes') &&
50            !isset($allowed_schemes[$scheme])
51        ) {
52            return;
53        }
54
55        if (isset($this->schemes[$scheme])) {
56            return $this->schemes[$scheme];
57        }
58        if (!isset($allowed_schemes[$scheme])) {
59            return;
60        }
61
62        $class = 'HTMLPurifier_URIScheme_' . $scheme;
63        if (!class_exists($class)) {
64            return;
65        }
66        $this->schemes[$scheme] = new $class();
67        return $this->schemes[$scheme];
68    }
69
70    /**
71     * Registers a custom scheme to the cache, bypassing reflection.
72     * @param string $scheme Scheme name
73     * @param HTMLPurifier_URIScheme $scheme_obj
74     */
75    public function register($scheme, $scheme_obj)
76    {
77        $this->schemes[$scheme] = $scheme_obj;
78    }
79}
80
81// vim: et sw=4 sts=4
82