1: | <?php
|
2: |
|
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | |
15: | |
16: |
|
17: | class HTMLPurifier_Config
|
18: | {
|
19: |
|
20: | |
21: | |
22: | |
23: |
|
24: | public $version = '4.15.0';
|
25: |
|
26: | |
27: | |
28: | |
29: | |
30: |
|
31: | public $autoFinalize = true;
|
32: |
|
33: |
|
34: |
|
35: | |
36: | |
37: | |
38: | |
39: |
|
40: | protected $serials = array();
|
41: |
|
42: | |
43: | |
44: | |
45: |
|
46: | protected $serial;
|
47: |
|
48: | |
49: | |
50: | |
51: |
|
52: | protected $parser = null;
|
53: |
|
54: | |
55: | |
56: | |
57: | |
58: | |
59: |
|
60: | public $def;
|
61: |
|
62: | |
63: | |
64: | |
65: |
|
66: | protected $definitions;
|
67: |
|
68: | |
69: | |
70: | |
71: |
|
72: | protected $finalized = false;
|
73: |
|
74: | |
75: | |
76: | |
77: |
|
78: | protected $plist;
|
79: |
|
80: | |
81: | |
82: | |
83: |
|
84: | private $aliasMode;
|
85: |
|
86: | |
87: | |
88: | |
89: | |
90: | |
91: |
|
92: | public $chatty = true;
|
93: |
|
94: | |
95: | |
96: | |
97: |
|
98: | private $lock;
|
99: |
|
100: | |
101: | |
102: | |
103: | |
104: | |
105: |
|
106: | public function __construct($definition, $parent = null)
|
107: | {
|
108: | $parent = $parent ? $parent : $definition->defaultPlist;
|
109: | $this->plist = new HTMLPurifier_PropertyList($parent);
|
110: | $this->def = $definition;
|
111: | $this->parser = new HTMLPurifier_VarParser_Flexible();
|
112: | }
|
113: |
|
114: | |
115: | |
116: | |
117: | |
118: | |
119: | |
120: | |
121: | |
122: |
|
123: | public static function create($config, $schema = null)
|
124: | {
|
125: | if ($config instanceof HTMLPurifier_Config) {
|
126: |
|
127: | return $config;
|
128: | }
|
129: | if (!$schema) {
|
130: | $ret = HTMLPurifier_Config::createDefault();
|
131: | } else {
|
132: | $ret = new HTMLPurifier_Config($schema);
|
133: | }
|
134: | if (is_string($config)) {
|
135: | $ret->loadIni($config);
|
136: | } elseif (is_array($config)) $ret->loadArray($config);
|
137: | return $ret;
|
138: | }
|
139: |
|
140: | |
141: | |
142: | |
143: | |
144: |
|
145: | public static function inherit(HTMLPurifier_Config $config)
|
146: | {
|
147: | return new HTMLPurifier_Config($config->def, $config->plist);
|
148: | }
|
149: |
|
150: | |
151: | |
152: | |
153: |
|
154: | public static function createDefault()
|
155: | {
|
156: | $definition = HTMLPurifier_ConfigSchema::instance();
|
157: | $config = new HTMLPurifier_Config($definition);
|
158: | return $config;
|
159: | }
|
160: |
|
161: | |
162: | |
163: | |
164: | |
165: | |
166: | |
167: | |
168: |
|
169: | public function get($key, $a = null)
|
170: | {
|
171: | if ($a !== null) {
|
172: | $this->triggerError(
|
173: | "Using deprecated API: use \$config->get('$key.$a') instead",
|
174: | E_USER_WARNING
|
175: | );
|
176: | $key = "$key.$a";
|
177: | }
|
178: | if (!$this->finalized) {
|
179: | $this->autoFinalize();
|
180: | }
|
181: | if (!isset($this->def->info[$key])) {
|
182: |
|
183: | $this->triggerError(
|
184: | 'Cannot retrieve value of undefined directive ' . htmlspecialchars($key),
|
185: | E_USER_WARNING
|
186: | );
|
187: | return;
|
188: | }
|
189: | if (isset($this->def->info[$key]->isAlias)) {
|
190: | $d = $this->def->info[$key];
|
191: | $this->triggerError(
|
192: | 'Cannot get value from aliased directive, use real name ' . $d->key,
|
193: | E_USER_ERROR
|
194: | );
|
195: | return;
|
196: | }
|
197: | if ($this->lock) {
|
198: | list($ns) = explode('.', $key);
|
199: | if ($ns !== $this->lock) {
|
200: | $this->triggerError(
|
201: | 'Cannot get value of namespace ' . $ns . ' when lock for ' .
|
202: | $this->lock .
|
203: | ' is active, this probably indicates a Definition setup method ' .
|
204: | 'is accessing directives that are not within its namespace',
|
205: | E_USER_ERROR
|
206: | );
|
207: | return;
|
208: | }
|
209: | }
|
210: | return $this->plist->get($key);
|
211: | }
|
212: |
|
213: | |
214: | |
215: | |
216: | |
217: | |
218: | |
219: |
|
220: | public function getBatch($namespace)
|
221: | {
|
222: | if (!$this->finalized) {
|
223: | $this->autoFinalize();
|
224: | }
|
225: | $full = $this->getAll();
|
226: | if (!isset($full[$namespace])) {
|
227: | $this->triggerError(
|
228: | 'Cannot retrieve undefined namespace ' .
|
229: | htmlspecialchars($namespace),
|
230: | E_USER_WARNING
|
231: | );
|
232: | return;
|
233: | }
|
234: | return $full[$namespace];
|
235: | }
|
236: |
|
237: | |
238: | |
239: | |
240: | |
241: | |
242: | |
243: | |
244: | |
245: | |
246: |
|
247: | public function getBatchSerial($namespace)
|
248: | {
|
249: | if (empty($this->serials[$namespace])) {
|
250: | $batch = $this->getBatch($namespace);
|
251: | unset($batch['DefinitionRev']);
|
252: | $this->serials[$namespace] = sha1(serialize($batch));
|
253: | }
|
254: | return $this->serials[$namespace];
|
255: | }
|
256: |
|
257: | |
258: | |
259: | |
260: | |
261: | |
262: |
|
263: | public function getSerial()
|
264: | {
|
265: | if (empty($this->serial)) {
|
266: | $this->serial = sha1(serialize($this->getAll()));
|
267: | }
|
268: | return $this->serial;
|
269: | }
|
270: |
|
271: | |
272: | |
273: | |
274: | |
275: |
|
276: | public function getAll()
|
277: | {
|
278: | if (!$this->finalized) {
|
279: | $this->autoFinalize();
|
280: | }
|
281: | $ret = array();
|
282: | foreach ($this->plist->squash() as $name => $value) {
|
283: | list($ns, $key) = explode('.', $name, 2);
|
284: | $ret[$ns][$key] = $value;
|
285: | }
|
286: | return $ret;
|
287: | }
|
288: |
|
289: | |
290: | |
291: | |
292: | |
293: | |
294: | |
295: |
|
296: | public function set($key, $value, $a = null)
|
297: | {
|
298: | if (strpos($key, '.') === false) {
|
299: | $namespace = $key;
|
300: | $directive = $value;
|
301: | $value = $a;
|
302: | $key = "$key.$directive";
|
303: | $this->triggerError("Using deprecated API: use \$config->set('$key', ...) instead", E_USER_NOTICE);
|
304: | } else {
|
305: | list($namespace) = explode('.', $key);
|
306: | }
|
307: | if ($this->isFinalized('Cannot set directive after finalization')) {
|
308: | return;
|
309: | }
|
310: | if (!isset($this->def->info[$key])) {
|
311: | $this->triggerError(
|
312: | 'Cannot set undefined directive ' . htmlspecialchars($key) . ' to value',
|
313: | E_USER_WARNING
|
314: | );
|
315: | return;
|
316: | }
|
317: | $def = $this->def->info[$key];
|
318: |
|
319: | if (isset($def->isAlias)) {
|
320: | if ($this->aliasMode) {
|
321: | $this->triggerError(
|
322: | 'Double-aliases not allowed, please fix '.
|
323: | 'ConfigSchema bug with' . $key,
|
324: | E_USER_ERROR
|
325: | );
|
326: | return;
|
327: | }
|
328: | $this->aliasMode = true;
|
329: | $this->set($def->key, $value);
|
330: | $this->aliasMode = false;
|
331: | $this->triggerError("$key is an alias, preferred directive name is {$def->key}", E_USER_NOTICE);
|
332: | return;
|
333: | }
|
334: |
|
335: |
|
336: |
|
337: | $rtype = is_int($def) ? $def : $def->type;
|
338: | if ($rtype < 0) {
|
339: | $type = -$rtype;
|
340: | $allow_null = true;
|
341: | } else {
|
342: | $type = $rtype;
|
343: | $allow_null = isset($def->allow_null);
|
344: | }
|
345: |
|
346: | try {
|
347: | $value = $this->parser->parse($value, $type, $allow_null);
|
348: | } catch (HTMLPurifier_VarParserException $e) {
|
349: | $this->triggerError(
|
350: | 'Value for ' . $key . ' is of invalid type, should be ' .
|
351: | HTMLPurifier_VarParser::getTypeName($type),
|
352: | E_USER_WARNING
|
353: | );
|
354: | return;
|
355: | }
|
356: | if (is_string($value) && is_object($def)) {
|
357: |
|
358: | if (isset($def->aliases[$value])) {
|
359: | $value = $def->aliases[$value];
|
360: | }
|
361: |
|
362: | if (isset($def->allowed) && !isset($def->allowed[$value])) {
|
363: | $this->triggerError(
|
364: | 'Value not supported, valid values are: ' .
|
365: | $this->_listify($def->allowed),
|
366: | E_USER_WARNING
|
367: | );
|
368: | return;
|
369: | }
|
370: | }
|
371: | $this->plist->set($key, $value);
|
372: |
|
373: |
|
374: |
|
375: |
|
376: | if ($namespace == 'HTML' || $namespace == 'CSS' || $namespace == 'URI') {
|
377: | $this->definitions[$namespace] = null;
|
378: | }
|
379: |
|
380: | $this->serials[$namespace] = false;
|
381: | }
|
382: |
|
383: | |
384: | |
385: | |
386: | |
387: | |
388: | |
389: |
|
390: | private function _listify($lookup)
|
391: | {
|
392: | $list = array();
|
393: | foreach ($lookup as $name => $b) {
|
394: | $list[] = $name;
|
395: | }
|
396: | return implode(', ', $list);
|
397: | }
|
398: |
|
399: | |
400: | |
401: | |
402: | |
403: | |
404: | |
405: | |
406: | |
407: | |
408: | |
409: | |
410: | |
411: | |
412: |
|
413: | public function getHTMLDefinition($raw = false, $optimized = false)
|
414: | {
|
415: | return $this->getDefinition('HTML', $raw, $optimized);
|
416: | }
|
417: |
|
418: | |
419: | |
420: | |
421: | |
422: | |
423: | |
424: | |
425: | |
426: | |
427: | |
428: | |
429: | |
430: | |
431: |
|
432: | public function getCSSDefinition($raw = false, $optimized = false)
|
433: | {
|
434: | return $this->getDefinition('CSS', $raw, $optimized);
|
435: | }
|
436: |
|
437: | |
438: | |
439: | |
440: | |
441: | |
442: | |
443: | |
444: | |
445: | |
446: | |
447: | |
448: | |
449: | |
450: |
|
451: | public function getURIDefinition($raw = false, $optimized = false)
|
452: | {
|
453: | return $this->getDefinition('URI', $raw, $optimized);
|
454: | }
|
455: |
|
456: | |
457: | |
458: | |
459: | |
460: | |
461: | |
462: | |
463: | |
464: | |
465: | |
466: | |
467: | |
468: | |
469: | |
470: | |
471: | |
472: |
|
473: | public function getDefinition($type, $raw = false, $optimized = false)
|
474: | {
|
475: | if ($optimized && !$raw) {
|
476: | throw new HTMLPurifier_Exception("Cannot set optimized = true when raw = false");
|
477: | }
|
478: | if (!$this->finalized) {
|
479: | $this->autoFinalize();
|
480: | }
|
481: |
|
482: | $lock = $this->lock;
|
483: | $this->lock = null;
|
484: | $factory = HTMLPurifier_DefinitionCacheFactory::instance();
|
485: | $cache = $factory->create($type, $this);
|
486: | $this->lock = $lock;
|
487: | if (!$raw) {
|
488: |
|
489: |
|
490: |
|
491: | if (!empty($this->definitions[$type])) {
|
492: | $def = $this->definitions[$type];
|
493: |
|
494: | if ($def->setup) {
|
495: | return $def;
|
496: | } else {
|
497: | $def->setup($this);
|
498: | if ($def->optimized) {
|
499: | $cache->add($def, $this);
|
500: | }
|
501: | return $def;
|
502: | }
|
503: | }
|
504: |
|
505: | $def = $cache->get($this);
|
506: | if ($def) {
|
507: |
|
508: | $this->definitions[$type] = $def;
|
509: | return $def;
|
510: | }
|
511: |
|
512: | $def = $this->initDefinition($type);
|
513: |
|
514: | $this->lock = $type;
|
515: | $def->setup($this);
|
516: | $this->lock = null;
|
517: |
|
518: | $cache->add($def, $this);
|
519: |
|
520: | return $def;
|
521: | } else {
|
522: |
|
523: |
|
524: |
|
525: | $def = null;
|
526: | if ($optimized) {
|
527: | if (is_null($this->get($type . '.DefinitionID'))) {
|
528: |
|
529: | throw new HTMLPurifier_Exception(
|
530: | "Cannot retrieve raw version without specifying %$type.DefinitionID"
|
531: | );
|
532: | }
|
533: | }
|
534: | if (!empty($this->definitions[$type])) {
|
535: | $def = $this->definitions[$type];
|
536: | if ($def->setup && !$optimized) {
|
537: | $extra = $this->chatty ?
|
538: | " (try moving this code block earlier in your initialization)" :
|
539: | "";
|
540: | throw new HTMLPurifier_Exception(
|
541: | "Cannot retrieve raw definition after it has already been setup" .
|
542: | $extra
|
543: | );
|
544: | }
|
545: | if ($def->optimized === null) {
|
546: | $extra = $this->chatty ? " (try flushing your cache)" : "";
|
547: | throw new HTMLPurifier_Exception(
|
548: | "Optimization status of definition is unknown" . $extra
|
549: | );
|
550: | }
|
551: | if ($def->optimized !== $optimized) {
|
552: | $msg = $optimized ? "optimized" : "unoptimized";
|
553: | $extra = $this->chatty ?
|
554: | " (this backtrace is for the first inconsistent call, which was for a $msg raw definition)"
|
555: | : "";
|
556: | throw new HTMLPurifier_Exception(
|
557: | "Inconsistent use of optimized and unoptimized raw definition retrievals" . $extra
|
558: | );
|
559: | }
|
560: | }
|
561: |
|
562: | if ($def) {
|
563: | if ($def->setup) {
|
564: |
|
565: | return null;
|
566: | } else {
|
567: | return $def;
|
568: | }
|
569: | }
|
570: |
|
571: |
|
572: |
|
573: |
|
574: |
|
575: | if ($optimized) {
|
576: |
|
577: |
|
578: |
|
579: | $def = $cache->get($this);
|
580: | if ($def) {
|
581: |
|
582: |
|
583: | $this->definitions[$type] = $def;
|
584: | return null;
|
585: | }
|
586: | }
|
587: |
|
588: | if (!$optimized) {
|
589: | if (!is_null($this->get($type . '.DefinitionID'))) {
|
590: | if ($this->chatty) {
|
591: | $this->triggerError(
|
592: | 'Due to a documentation error in previous version of HTML Purifier, your ' .
|
593: | 'definitions are not being cached. If this is OK, you can remove the ' .
|
594: | '%$type.DefinitionRev and %$type.DefinitionID declaration. Otherwise, ' .
|
595: | 'modify your code to use maybeGetRawDefinition, and test if the returned ' .
|
596: | 'value is null before making any edits (if it is null, that means that a ' .
|
597: | 'cached version is available, and no raw operations are necessary). See ' .
|
598: | '<a href="http://htmlpurifier.org/docs/enduser-customize.html#optimized">' .
|
599: | 'Customize</a> for more details',
|
600: | E_USER_WARNING
|
601: | );
|
602: | } else {
|
603: | $this->triggerError(
|
604: | "Useless DefinitionID declaration",
|
605: | E_USER_WARNING
|
606: | );
|
607: | }
|
608: | }
|
609: | }
|
610: |
|
611: | $def = $this->initDefinition($type);
|
612: | $def->optimized = $optimized;
|
613: | return $def;
|
614: | }
|
615: | throw new HTMLPurifier_Exception("The impossible happened!");
|
616: | }
|
617: |
|
618: | |
619: | |
620: | |
621: | |
622: | |
623: | |
624: | |
625: |
|
626: | private function initDefinition($type)
|
627: | {
|
628: |
|
629: | if ($type == 'HTML') {
|
630: | $def = new HTMLPurifier_HTMLDefinition();
|
631: | } elseif ($type == 'CSS') {
|
632: | $def = new HTMLPurifier_CSSDefinition();
|
633: | } elseif ($type == 'URI') {
|
634: | $def = new HTMLPurifier_URIDefinition();
|
635: | } else {
|
636: | throw new HTMLPurifier_Exception(
|
637: | "Definition of $type type not supported"
|
638: | );
|
639: | }
|
640: | $this->definitions[$type] = $def;
|
641: | return $def;
|
642: | }
|
643: |
|
644: | public function maybeGetRawDefinition($name)
|
645: | {
|
646: | return $this->getDefinition($name, true, true);
|
647: | }
|
648: |
|
649: | |
650: | |
651: |
|
652: | public function maybeGetRawHTMLDefinition()
|
653: | {
|
654: | return $this->getDefinition('HTML', true, true);
|
655: | }
|
656: |
|
657: | |
658: | |
659: |
|
660: | public function maybeGetRawCSSDefinition()
|
661: | {
|
662: | return $this->getDefinition('CSS', true, true);
|
663: | }
|
664: |
|
665: | |
666: | |
667: |
|
668: | public function maybeGetRawURIDefinition()
|
669: | {
|
670: | return $this->getDefinition('URI', true, true);
|
671: | }
|
672: |
|
673: | |
674: | |
675: | |
676: | |
677: | |
678: |
|
679: | public function loadArray($config_array)
|
680: | {
|
681: | if ($this->isFinalized('Cannot load directives after finalization')) {
|
682: | return;
|
683: | }
|
684: | foreach ($config_array as $key => $value) {
|
685: | $key = str_replace('_', '.', $key);
|
686: | if (strpos($key, '.') !== false) {
|
687: | $this->set($key, $value);
|
688: | } else {
|
689: | $namespace = $key;
|
690: | $namespace_values = $value;
|
691: | foreach ($namespace_values as $directive => $value2) {
|
692: | $this->set($namespace .'.'. $directive, $value2);
|
693: | }
|
694: | }
|
695: | }
|
696: | }
|
697: |
|
698: | |
699: | |
700: | |
701: | |
702: | |
703: | |
704: | |
705: | |
706: | |
707: |
|
708: | public static function getAllowedDirectivesForForm($allowed, $schema = null)
|
709: | {
|
710: | if (!$schema) {
|
711: | $schema = HTMLPurifier_ConfigSchema::instance();
|
712: | }
|
713: | if ($allowed !== true) {
|
714: | if (is_string($allowed)) {
|
715: | $allowed = array($allowed);
|
716: | }
|
717: | $allowed_ns = array();
|
718: | $allowed_directives = array();
|
719: | $blacklisted_directives = array();
|
720: | foreach ($allowed as $ns_or_directive) {
|
721: | if (strpos($ns_or_directive, '.') !== false) {
|
722: |
|
723: | if ($ns_or_directive[0] == '-') {
|
724: | $blacklisted_directives[substr($ns_or_directive, 1)] = true;
|
725: | } else {
|
726: | $allowed_directives[$ns_or_directive] = true;
|
727: | }
|
728: | } else {
|
729: |
|
730: | $allowed_ns[$ns_or_directive] = true;
|
731: | }
|
732: | }
|
733: | }
|
734: | $ret = array();
|
735: | foreach ($schema->info as $key => $def) {
|
736: | list($ns, $directive) = explode('.', $key, 2);
|
737: | if ($allowed !== true) {
|
738: | if (isset($blacklisted_directives["$ns.$directive"])) {
|
739: | continue;
|
740: | }
|
741: | if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) {
|
742: | continue;
|
743: | }
|
744: | }
|
745: | if (isset($def->isAlias)) {
|
746: | continue;
|
747: | }
|
748: | if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') {
|
749: | continue;
|
750: | }
|
751: | $ret[] = array($ns, $directive);
|
752: | }
|
753: | return $ret;
|
754: | }
|
755: |
|
756: | |
757: | |
758: | |
759: | |
760: | |
761: | |
762: | |
763: | |
764: | |
765: | |
766: | |
767: |
|
768: | public static function loadArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null)
|
769: | {
|
770: | $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema);
|
771: | $config = HTMLPurifier_Config::create($ret, $schema);
|
772: | return $config;
|
773: | }
|
774: |
|
775: | |
776: | |
777: | |
778: | |
779: | |
780: | |
781: | |
782: |
|
783: | public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true)
|
784: | {
|
785: | $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def);
|
786: | $this->loadArray($ret);
|
787: | }
|
788: |
|
789: | |
790: | |
791: | |
792: | |
793: | |
794: | |
795: | |
796: | |
797: | |
798: | |
799: | |
800: |
|
801: | public static function prepareArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null)
|
802: | {
|
803: | if ($index !== false) {
|
804: | $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
|
805: | }
|
806: | $mq = $mq_fix && version_compare(PHP_VERSION, '7.4.0', '<') && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc();
|
807: |
|
808: | $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema);
|
809: | $ret = array();
|
810: | foreach ($allowed as $key) {
|
811: | list($ns, $directive) = $key;
|
812: | $skey = "$ns.$directive";
|
813: | if (!empty($array["Null_$skey"])) {
|
814: | $ret[$ns][$directive] = null;
|
815: | continue;
|
816: | }
|
817: | if (!isset($array[$skey])) {
|
818: | continue;
|
819: | }
|
820: | $value = $mq ? stripslashes($array[$skey]) : $array[$skey];
|
821: | $ret[$ns][$directive] = $value;
|
822: | }
|
823: | return $ret;
|
824: | }
|
825: |
|
826: | |
827: | |
828: | |
829: | |
830: |
|
831: | public function loadIni($filename)
|
832: | {
|
833: | if ($this->isFinalized('Cannot load directives after finalization')) {
|
834: | return;
|
835: | }
|
836: | $array = parse_ini_file($filename, true);
|
837: | $this->loadArray($array);
|
838: | }
|
839: |
|
840: | |
841: | |
842: | |
843: | |
844: | |
845: | |
846: |
|
847: | public function isFinalized($error = false)
|
848: | {
|
849: | if ($this->finalized && $error) {
|
850: | $this->triggerError($error, E_USER_ERROR);
|
851: | }
|
852: | return $this->finalized;
|
853: | }
|
854: |
|
855: | |
856: | |
857: | |
858: |
|
859: | public function autoFinalize()
|
860: | {
|
861: | if ($this->autoFinalize) {
|
862: | $this->finalize();
|
863: | } else {
|
864: | $this->plist->squash(true);
|
865: | }
|
866: | }
|
867: |
|
868: | |
869: | |
870: |
|
871: | public function finalize()
|
872: | {
|
873: | $this->finalized = true;
|
874: | $this->parser = null;
|
875: | }
|
876: |
|
877: | |
878: | |
879: | |
880: | |
881: | |
882: | |
883: |
|
884: | protected function triggerError($msg, $no)
|
885: | {
|
886: |
|
887: | $extra = '';
|
888: | if ($this->chatty) {
|
889: | $trace = debug_backtrace();
|
890: |
|
891: | for ($i = 0, $c = count($trace); $i < $c - 1; $i++) {
|
892: |
|
893: | if (isset($trace[$i + 1]['class']) && $trace[$i + 1]['class'] === 'HTMLPurifier_Config') {
|
894: | continue;
|
895: | }
|
896: | $frame = $trace[$i];
|
897: | $extra = " invoked on line {$frame['line']} in file {$frame['file']}";
|
898: | break;
|
899: | }
|
900: | }
|
901: | trigger_error($msg . $extra, $no);
|
902: | }
|
903: |
|
904: | |
905: | |
906: | |
907: | |
908: | |
909: |
|
910: | public function serialize()
|
911: | {
|
912: | $this->getDefinition('HTML');
|
913: | $this->getDefinition('CSS');
|
914: | $this->getDefinition('URI');
|
915: | return serialize($this);
|
916: | }
|
917: |
|
918: | }
|
919: |
|
920: |
|
921: | |