/**
  * Retrieves an instance of global definition cache factory.
  */
 public static function instance($prototype = null)
 {
     static $instance;
     if ($prototype !== null) {
         $instance = $prototype;
     } elseif ($instance === null || $prototype === true) {
         $instance = new HTMLPurifier_DefinitionCacheFactory();
         $instance->setup();
     }
     return $instance;
 }
 /**
  * Retrieves a definition
  * @param $type Type of definition: HTML, CSS, etc
  * @param $raw  Whether or not definition should be returned raw
  */
 public function getDefinition($type, $raw = false)
 {
     if (!$this->finalized) {
         $this->autoFinalize();
     }
     // temporarily suspend locks, so we can handle recursive definition calls
     $lock = $this->lock;
     $this->lock = null;
     $factory = HTMLPurifier_DefinitionCacheFactory::instance();
     $cache = $factory->create($type, $this);
     $this->lock = $lock;
     if (!$raw) {
         // see if we can quickly supply a definition
         if (!empty($this->definitions[$type])) {
             if (!$this->definitions[$type]->setup) {
                 $this->definitions[$type]->setup($this);
                 $cache->set($this->definitions[$type], $this);
             }
             return $this->definitions[$type];
         }
         // memory check missed, try cache
         $this->definitions[$type] = $cache->get($this);
         if ($this->definitions[$type]) {
             // definition in cache, return it
             return $this->definitions[$type];
         }
     } elseif (!empty($this->definitions[$type]) && !$this->definitions[$type]->setup) {
         // raw requested, raw in memory, quick return
         return $this->definitions[$type];
     }
     // quick checks failed, let's create the object
     if ($type == 'HTML') {
         $this->definitions[$type] = new HTMLPurifier_HTMLDefinition();
     } elseif ($type == 'CSS') {
         $this->definitions[$type] = new HTMLPurifier_CSSDefinition();
     } elseif ($type == 'URI') {
         $this->definitions[$type] = new HTMLPurifier_URIDefinition();
     } else {
         throw new HTMLPurifier_Exception("Definition of {$type} type not supported");
     }
     // quick abort if raw
     if ($raw) {
         if (is_null($this->get($type . '.DefinitionID'))) {
             // fatally error out if definition ID not set
             throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %{$type}.DefinitionID");
         }
         return $this->definitions[$type];
     }
     // set it up
     $this->lock = $type;
     $this->definitions[$type]->setup($this);
     $this->lock = null;
     // save in cache
     $cache->set($this->definitions[$type], $this);
     return $this->definitions[$type];
 }
Exemple #3
0
 /**
  * Retrieves a definition
  * @param $type Type of definition: HTML, CSS, etc
  * @param $raw  Whether or not definition should be returned raw
  * @param $optimized Only has an effect when $raw is true.  Whether
  *        or not to return null if the result is already present in
  *        the cache.  This is off by default for backwards
  *        compatibility reasons, but you need to do things this
  *        way in order to ensure that caching is done properly.
  *        Check out enduser-customize.html for more details.
  *        We probably won't ever change this default, as much as the
  *        maybe semantics is the "right thing to do."
  */
 public function getDefinition($type, $raw = false, $optimized = false)
 {
     if ($optimized && !$raw) {
         throw new HTMLPurifier_Exception("Cannot set optimized = true when raw = false");
     }
     if (!$this->finalized) {
         $this->autoFinalize();
     }
     // temporarily suspend locks, so we can handle recursive definition calls
     $lock = $this->lock;
     $this->lock = null;
     $factory = HTMLPurifier_DefinitionCacheFactory::instance();
     $cache = $factory->create($type, $this);
     $this->lock = $lock;
     if (!$raw) {
         // full definition
         // ---------------
         // check if definition is in memory
         if (!empty($this->definitions[$type])) {
             $def = $this->definitions[$type];
             // check if the definition is setup
             if ($def->setup) {
                 return $def;
             } else {
                 $def->setup($this);
                 if ($def->optimized) {
                     $cache->add($def, $this);
                 }
                 return $def;
             }
         }
         // check if definition is in cache
         $def = $cache->get($this);
         if ($def) {
             // definition in cache, save to memory and return it
             $this->definitions[$type] = $def;
             return $def;
         }
         // initialize it
         $def = $this->initDefinition($type);
         // set it up
         $this->lock = $type;
         $def->setup($this);
         $this->lock = null;
         // save in cache
         $cache->add($def, $this);
         // return it
         return $def;
     } else {
         // raw definition
         // --------------
         // check preconditions
         $def = null;
         if ($optimized) {
             if (is_null($this->get($type . '.DefinitionID'))) {
                 // fatally error out if definition ID not set
                 throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %{$type}.DefinitionID");
             }
         }
         if (!empty($this->definitions[$type])) {
             $def = $this->definitions[$type];
             if ($def->setup && !$optimized) {
                 $extra = $this->chatty ? " (try moving this code block earlier in your initialization)" : "";
                 throw new HTMLPurifier_Exception("Cannot retrieve raw definition after it has already been setup" . $extra);
             }
             if ($def->optimized === null) {
                 $extra = $this->chatty ? " (try flushing your cache)" : "";
                 throw new HTMLPurifier_Exception("Optimization status of definition is unknown" . $extra);
             }
             if ($def->optimized !== $optimized) {
                 $msg = $optimized ? "optimized" : "unoptimized";
                 $extra = $this->chatty ? " (this backtrace is for the first inconsistent call, which was for a {$msg} raw definition)" : "";
                 throw new HTMLPurifier_Exception("Inconsistent use of optimized and unoptimized raw definition retrievals" . $extra);
             }
         }
         // check if definition was in memory
         if ($def) {
             if ($def->setup) {
                 // invariant: $optimized === true (checked above)
                 return null;
             } else {
                 return $def;
             }
         }
         // if optimized, check if definition was in cache
         // (because we do the memory check first, this formulation
         // is prone to cache slamming, but I think
         // guaranteeing that either /all/ of the raw
         // setup code or /none/ of it is run is more important.)
         if ($optimized) {
             // This code path only gets run once; once we put
             // something in $definitions (which is guaranteed by the
             // trailing code), we always short-circuit above.
             $def = $cache->get($this);
             if ($def) {
                 // save the full definition for later, but don't
                 // return it yet
                 $this->definitions[$type] = $def;
                 return null;
             }
         }
         // check invariants for creation
         if (!$optimized) {
             if (!is_null($this->get($type . '.DefinitionID'))) {
                 if ($this->chatty) {
                     $this->triggerError("Due to a documentation error in previous version of HTML Purifier, your definitions are not being cached.  If this is OK, you can remove the %{$type}.DefinitionRev and %{$type}.DefinitionID declaration.  Otherwise, modify your code to use maybeGetRawDefinition, and test if the returned value is null before making any edits (if it is null, that means that a cached version is available, and no raw operations are necessary).  See <a href='http://htmlpurifier.org/docs/enduser-customize.html#optimized'>Customize</a> for more details", E_USER_WARNING);
                 } else {
                     $this->triggerError("Useless DefinitionID declaration", E_USER_WARNING);
                 }
             }
         }
         // initialize it
         $def = $this->initDefinition($type);
         $def->optimized = $optimized;
         return $def;
     }
     throw new HTMLPurifier_Exception("The impossible happened!");
 }
Exemple #4
0
 protected function teardownCacheMock()
 {
     HTMLPurifier_DefinitionCacheFactory::instance($this->oldFactory);
 }
 public function tearDown()
 {
     HTMLPurifier_DefinitionCacheFactory::instance($this->oldFactory);
 }
Exemple #6
0
    }
    $reporter = new XmlReporter();
} elseif (SimpleReporter::inCli() || $AC['txt']) {
    if (!SimpleReporter::inCli()) {
        header('Content-Type: text/plain;charset=UTF-8');
    }
    $reporter = new HTMLPurifier_SimpleTest_TextReporter($AC);
} else {
    $reporter = new HTMLPurifier_SimpleTest_Reporter('UTF-8', $AC);
}
if ($AC['flush']) {
    htmlpurifier_flush($AC['php'], $reporter);
}
// Now, userland code begins to be executed
// setup special DefinitionCacheFactory decorator
$factory = HTMLPurifier_DefinitionCacheFactory::instance();
$factory->addDecorator('Memory');
// since we deal with a lot of config objects
if (!$AC['disable-phpt']) {
    $phpt = PHPT_Registry::getInstance();
    $phpt->php = $AC['php'];
}
// load tests
require 'test_files.php';
$FS = new FSTools();
// handle test dirs
foreach ($test_dirs as $dir) {
    $raw_files = $FS->globr($dir, '*Test.php');
    foreach ($raw_files as $file) {
        $file = str_replace('\\', '/', $file);
        if (isset($test_dirs_exclude[$file])) {
Exemple #7
0
 /**
  * Retrieves a definition
  * @param $type Type of definition: HTML, CSS, etc
  * @param $raw  Whether or not definition should be returned raw
  */
 function &getDefinition($type, $raw = false)
 {
     if (!$this->finalized && $this->autoFinalize) {
         $this->finalize();
     }
     $factory = HTMLPurifier_DefinitionCacheFactory::instance();
     $cache = $factory->create($type, $this);
     if (!$raw) {
         // see if we can quickly supply a definition
         if (!empty($this->definitions[$type])) {
             if (!$this->definitions[$type]->setup) {
                 $this->definitions[$type]->setup($this);
                 $cache->set($this->definitions[$type], $this);
             }
             return $this->definitions[$type];
         }
         // memory check missed, try cache
         $this->definitions[$type] = $cache->get($this);
         if ($this->definitions[$type]) {
             // definition in cache, return it
             return $this->definitions[$type];
         }
     } elseif (!empty($this->definitions[$type]) && !$this->definitions[$type]->setup) {
         // raw requested, raw in memory, quick return
         return $this->definitions[$type];
     }
     // quick checks failed, let's create the object
     if ($type == 'HTML') {
         $this->definitions[$type] = new HTMLPurifier_HTMLDefinition();
     } elseif ($type == 'CSS') {
         $this->definitions[$type] = new HTMLPurifier_CSSDefinition();
     } elseif ($type == 'URI') {
         $this->definitions[$type] = new HTMLPurifier_URIDefinition();
     } else {
         trigger_error("Definition of {$type} type not supported");
         $false = false;
         return $false;
     }
     // quick abort if raw
     if ($raw) {
         if (is_null($this->get($type, 'DefinitionID'))) {
             // fatally error out if definition ID not set
             trigger_error("Cannot retrieve raw version without specifying %{$type}.DefinitionID", E_USER_ERROR);
             $false = new HTMLPurifier_Error();
             return $false;
         }
         return $this->definitions[$type];
     }
     // set it up
     $this->definitions[$type]->setup($this);
     // save in cache
     $cache->set($this->definitions[$type], $this);
     return $this->definitions[$type];
 }
 function testURIDefinitionValidation()
 {
     $parser = new HTMLPurifier_URIParser();
     $uri = $parser->parse('http://example.com');
     $this->config->set('URI.DefinitionID', 'HTMLPurifier_AttrDef_URITest->testURIDefinitionValidation');
     generate_mock_once('HTMLPurifier_URIDefinition');
     $uri_def = new HTMLPurifier_URIDefinitionMock();
     $uri_def->expectOnce('filter', array($uri, '*', '*'));
     $uri_def->setReturnValue('filter', true, array($uri, '*', '*'));
     $uri_def->expectOnce('postFilter', array($uri, '*', '*'));
     $uri_def->setReturnValue('postFilter', true, array($uri, '*', '*'));
     $uri_def->setup = true;
     // Since definitions are no longer passed by reference, we need
     // to muck around with the cache to insert our mock. This is
     // technically a little bad, since the cache shouldn't change
     // behavior, but I don't feel too good about letting users
     // overload entire definitions.
     generate_mock_once('HTMLPurifier_DefinitionCache');
     $cache_mock = new HTMLPurifier_DefinitionCacheMock();
     $cache_mock->setReturnValue('get', $uri_def);
     generate_mock_once('HTMLPurifier_DefinitionCacheFactory');
     $factory_mock = new HTMLPurifier_DefinitionCacheFactoryMock();
     $old = HTMLPurifier_DefinitionCacheFactory::instance();
     HTMLPurifier_DefinitionCacheFactory::instance($factory_mock);
     $factory_mock->setReturnValue('create', $cache_mock);
     $this->assertDef('http://example.com');
     HTMLPurifier_DefinitionCacheFactory::instance($old);
 }