| [ Index ] |
|
Code source de LifeType 1.2.4 |
1 <?php 2 /** 3 * \ingroup Data 4 * 5 * This is a fork of a slick piece of procedural code called 'kses' written by Ulf Harnhammar 6 * The entire set of functions was wrapped in a PHP object with some internal modifications 7 * by Richard Vasquez (http://www.chaos.org/) 7/25/2003 8 * 9 * The pLog project has made a few improvements to the code, for example including a mode where 10 * the filter can convert invalid XHTML code into valid markup, as well as a more aggressive 11 * filtering mode. 12 * 13 * The original (procedural) version of the code can be found at: 14 * http://sourceforge.net/projects/kses/ 15 * 16 * [kses strips evil scripts!] 17 * 18 * ========================================================================================== 19 * 20 * class.kses.php 0.0.2 - PHP class that filters HTML/XHTML only allowing some elements and 21 * attributes to be passed through. 22 * 23 * Copyright (C) 2003 Richard R. Vasquez, Jr. 24 * 25 * Derived from kses 0.2.1 - HTML/XHTML filter that only allows some elements and attributes 26 * Copyright (C) 2002, 2003 Ulf Harnhammar 27 * 28 * ========================================================================================== 29 * 30 * This program is free software and open source software; you can redistribute 31 * it and/or modify it under the terms of the GNU General Public License as 32 * published by the Free Software Foundation; either version 2 of the License, 33 * or (at your option) any later version. 34 * 35 * This program is distributed in the hope that it will be useful, but WITHOUT 36 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 37 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 38 * more details. 39 * 40 * You should have received a copy of the GNU General Public License along 41 * with this program; if not, write to the Free Software Foundation, Inc., 42 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or visit 43 * http://www.gnu.org/licenses/gpl.html 44 * 45 * ========================================================================================== 46 * CONTACT INFORMATION: 47 * 48 * Email: View current valid email address at http://www.chaos.org/contact/ 49 */ 50 class kses 51 { 52 var $allowed_protocols = array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'gopher', 'mailto', 'irc', 'mms' ); 53 var $allowed_html = array(); 54 55 // 56 // whether we're only using this class to convert to xhtml or 57 // also to filter some markup 58 // 59 var $xhtmlConverterOnly; 60 var $aggresiveMode; 61 62 /** 63 * constructor 64 * 65 * @param xhtmlConverterOnly Whether we're using the class for converting only to 66 * xhtml instead of for filtering out markup. When using this mode, the "addHTML" method 67 * @param aggressiveMode When the xhtml mode is enabled, it will try to be more aggressive as to 68 * what to convert... but bear in mind that it might make more mistakes!! 69 * does not do anything 70 */ 71 function kses( $xhtmlConverterOnly = false, $aggressiveMode = false ) 72 { 73 $this->xhtmlConverterOnly = $xhtmlConverterOnly; 74 $this->aggressiveMode = $aggressiveMode; 75 } 76 77 function Parse($string = "") 78 { 79 if (get_magic_quotes_gpc()) 80 { 81 $string = stripslashes($string); 82 } 83 $string = $this->_no_null($string); 84 $string = $this->_js_entities($string); 85 $string = $this->_normalize_entities($string); 86 $string = $this->_hook($string); 87 $string = $this->_split($string); 88 89 if( $this->xhtmlConverterOnly ) { 90 // and also xhtmlize a few more tags... 91 $string = str_replace( "<br>", "<br />", $string ); 92 $string = str_replace( "<hr>", "<hr />", $string ); 93 } 94 95 return $string; 96 } 97 98 function Protocols() 99 { 100 $c_args = func_num_args(); 101 if($c_args != 1) 102 { 103 return false; 104 } 105 106 $protocol_data = func_get_arg(0); 107 108 if(is_array($protocol_data)) 109 { 110 foreach($protocol_data as $protocol) 111 { 112 $this->AddProtocol($protocol); 113 } 114 } 115 elseif(is_string($protocol_data)) 116 { 117 $this->AddProtocol($protocol_data); 118 return true; 119 } 120 else 121 { 122 trigger_error("kses::Protocols() did not receive a string or an array.", E_USER_WARNING); 123 return false; 124 } 125 } 126 127 function AddProtocol($protocol = "") 128 { 129 if(!is_string($protocol)) 130 { 131 trigger_error("kses::AddProtocol() requires a string.", E_USER_WARNING); 132 return false; 133 } 134 135 $protocol = strtolower(trim($protocol)); 136 if($protocol == "") 137 { 138 trigger_error("kses::AddProtocol() tried to add an empty/NULL protocol.", E_USER_WARNING); 139 return false; 140 } 141 142 // Remove any inadvertent ':' at the end of the protocol. 143 if(substr($protocol, strlen($protocol) - 1, 1) == ":") 144 { 145 $protocol = substr($protocol, 0, strlen($protocol) - 1); 146 } 147 148 if(!in_array($protocol, $this->allowed_protocols)) 149 { 150 array_push($this->allowed_protocols, $protocol); 151 sort($this->allowed_protocols); 152 } 153 return true; 154 } 155 156 function AddHTML($tag = "", $attribs = array()) 157 { 158 if(!is_string($tag)) 159 { 160 trigger_error("kses::AddHTML() requires the tag to be a string", E_USER_WARNING); 161 return false; 162 } 163 164 $tag = strtolower(trim($tag)); 165 if($tag == "") 166 { 167 trigger_error("kses::AddHTML() tried to add an empty/NULL tag", E_USER_WARNING); 168 return false; 169 } 170 171 if(!is_array($attribs)) 172 { 173 trigger_error("kses::AddHTML() requires an array (even an empty one) of attributes for '$tag'", E_USER_WARNING); 174 return false; 175 } 176 177 $new_attribs = array(); 178 foreach($attribs as $idx1 => $val1) 179 { 180 $new_idx1 = strtolower($idx1); 181 $new_val1 = $attribs[$idx1]; 182 183 if(is_array($new_val1)) 184 { 185 $tmp_val = array(); 186 foreach($new_val1 as $idx2 => $val2) 187 { 188 $new_idx2 = strtolower($idx2); 189 $tmp_val[$new_idx2] = $val2; 190 } 191 $new_val1 = $tmp_val; 192 } 193 194 $new_attribs[$new_idx1] = $new_val1; 195 } 196 197 $this->allowed_html[$tag] = $new_attribs; 198 return true; 199 } 200 201 ############################################################################### 202 # This function removes any NULL or chr(173) characters in $string. 203 ############################################################################### 204 function _no_null($string) 205 { 206 $string = preg_replace('/\0+/', '', $string); 207 $string = preg_replace('/(\\\\0)+/', '', $string); 208 // 209 // NOTE TO SELF: this was apparently messing up utf-8 texts!!! Removed for now... 210 // 211 //$string = preg_replace('/\xad+/', '', $string); # deals with Opera "feature" 212 return $string; 213 } # function _no_null 214 215 ############################################################################### 216 # This function removes the HTML JavaScript entities found in early versions of 217 # Netscape 4. 218 ############################################################################### 219 function _js_entities($string) 220 { 221 return preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string); 222 } # function _js_entities 223 224 225 ############################################################################### 226 # This function normalizes HTML entities. It will convert "AT&T" to the correct 227 # "AT&T", ":" to ":", "&#XYZZY;" to "&#XYZZY;" and so on. 228 ############################################################################### 229 function _normalize_entities($string) 230 { 231 # Disarm all entities by converting & to & 232 $string = str_replace('&', '&', $string); 233 234 # Change back the allowed entities in our entity white list 235 236 $string = preg_replace('/&([A-Za-z][A-Za-z0-9]{0,19});/', '&\\1;', $string); 237 $string = preg_replace('/&#0*([0-9]{1,5});/e', '\$this->_normalize_entities2("\\1")', $string); 238 $string = preg_replace('/&#([Xx])0*(([0-9A-Fa-f]{2}){1,2});/', '&#\\1\\2;', $string); 239 240 if( $this->xhtmlConverterOnly && $this->aggressiveMode ) { 241 // take care of the '>' and '<' that don't belong to any tag 242 $string = preg_replace("/(\s+)(<)(\s+)/", "\\1<\\3", $string ); 243 $string = preg_replace("/(\[^A-Za-z]+)(<)([^A-Za-z]+)/", "\\1<\\3", $string ); 244 $string = preg_replace("/(\s+)(>)(\s+)/", "\\1>\\3", $string ); 245 246 // also, normalize whatever is within <code>...</code> tags but only in the "xhtml converter" mode 247 $string = preg_replace("/(.*<code>)(.*)(<\/code>.*)/e", '"\\1".$this->_tmp("\\2")."\\3"', $string ); 248 } 249 250 return $string; 251 } # function _normalize_entities 252 253 function _tmp($string) 254 { 255 $string = htmlspecialchars($string); 256 $string = preg_replace('/&([A-Za-z][A-Za-z0-9]{0,19});/', '&\\1;', $string); 257 $string = preg_replace('/&#0*([0-9]{1,5});/e', '\$this->_normalize_entities2("\\1")', $string); 258 $string = preg_replace('/&#([Xx])0*(([0-9A-Fa-f]{2}){1,2});/', '&#\\1\\2;', $string); 259 260 return $string; 261 } 262 263 ############################################################################### 264 # This function helps _normalize_entities() to only accept 16 bit values 265 # and nothing more for &#number; entities. 266 ############################################################################### 267 function _normalize_entities2($i) 268 { 269 return (($i > 65535) ? "&#$i;" : "&#$i;"); 270 } # function _normalize_entities2 271 272 ############################################################################### 273 # You add any kses hooks here. 274 ############################################################################### 275 function _hook($string) 276 { 277 return $string; 278 } # function _hook 279 280 ############################################################################### 281 # This function goes through an array, and changes the keys to all lower case. 282 ############################################################################### 283 function _array_lc($inarray) 284 { 285 $outarray = array(); 286 287 foreach ($inarray as $inkey => $inval) 288 { 289 $outkey = strtolower($inkey); 290 $outarray[$outkey] = array(); 291 292 foreach ($inval as $inkey2 => $inval2) 293 { 294 $outkey2 = strtolower($inkey2); 295 $outarray[$outkey][$outkey2] = $inval2; 296 } # foreach $inval 297 } # foreach $inarray 298 299 return $outarray; 300 } # function _array_lc 301 302 ############################################################################### 303 # This function searches for HTML tags, no matter how malformed. It also 304 # matches stray ">" characters. 305 ############################################################################### 306 function _split($string) 307 { 308 return preg_replace( 309 '%(<'. # EITHER: < 310 '[^>]*'. # things that aren't > 311 '>'. # must > 312 '|>)%e', # OR: just a > 313 "\$this->_split2('\\1')", 314 $string); 315 } # function _split 316 317 function _split2($string) 318 ############################################################################### 319 # This function does a lot of work. It rejects some very malformed things 320 # like <:::>. It returns an empty string, if the element isn't allowed (look 321 # ma, no strip_tags()!). Otherwise it splits the tag into an element and an 322 # attribute list. 323 ############################################################################### 324 { 325 $string = $this->_stripslashes($string); 326 327 if (substr($string, 0, 1) != '<') 328 { 329 # It matched a ">" character 330 return '>'; 331 } 332 333 if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches)) 334 { 335 # It's seriously malformed 336 return ''; 337 } 338 339 $slash = trim($matches[1]); 340 $elem = $matches[2]; 341 $attrlist = $matches[3]; 342 343 if( !$this->xhtmlConverterOnly ) { 344 if (!is_array($this->allowed_html[strtolower($elem)])) 345 { 346 # They are using a not allowed HTML element 347 return ''; 348 } 349 } 350 351 return $this->_attr("$slash$elem", $attrlist); 352 } # function _split2 353 354 ############################################################################### 355 # This function removes all attributes, if none are allowed for this element. 356 # If some are allowed it calls s_hair() to split them further, and then it 357 # builds up new HTML code from the data that _hair() returns. It also 358 # removes "<" and ">" characters, if there are any left. One more thing it 359 # does is to check if the tag has a closing XHTML slash, and if it does, 360 # it puts one in the returned code as well. 361 ############################################################################### 362 function _attr($element, $attr) 363 { 364 # Is there a closing XHTML slash at the end of the attributes? 365 $xhtml_slash = ''; 366 if (preg_match('%\s/\s*$%', $attr)) 367 { 368 $xhtml_slash = ' /'; 369 } 370 371 # Are any attributes allowed at all for this element? 372 if( !$this->xhtmlConverterOnly ) { 373 if (count($this->allowed_html[strtolower($element)]) == 0) 374 { 375 return "<$element$xhtml_slash>"; 376 } 377 } 378 379 # Split it 380 $attrarr = $this->_hair($attr); 381 382 # Go through $attrarr, and save the allowed attributes for this element 383 # in $attr2 384 $attr2 = ''; 385 foreach ($attrarr as $arreach) 386 { 387 if ( isset($this->allowed_html[strtolower($element)][strtolower($arreach['name'])]) ) 388 $current = $this->allowed_html[strtolower($element)][strtolower($arreach['name'])]; 389 else 390 $current = ''; 391 392 if( !$this->xhtmlConverterOnly ) { 393 if ($current == '') 394 { 395 # the attribute is not allowed 396 continue; 397 } 398 } 399 400 if (!is_array($current)) 401 { 402 # there are no checks 403 $attr2 .= ' '.$arreach['whole']; 404 } 405 else 406 { 407 # there are some checks 408 $ok = true; 409 foreach ($current as $currkey => $currval) 410 { 411 if (!$this->_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval)) 412 { 413 $ok = false; 414 break; 415 } 416 } 417 418 if ($ok) 419 { 420 # it passed them 421 $attr2 .= ' '.$arreach['whole']; 422 } 423 } # if !is_array($current) 424 } # foreach 425 426 # Remove any "<" or ">" characters 427 $attr2 = preg_replace('/[<>]/', '', $attr2); 428 return "<$element$attr2$xhtml_slash>"; 429 } # function _attr 430 431 ############################################################################### 432 # This function does a lot of work. It parses an attribute list into an array 433 # with attribute data, and tries to do the right thing even if it gets weird 434 # input. It will add quotes around attribute values that don't have any quotes 435 # or apostrophes around them, to make it easier to produce HTML code that will 436 # conform to W3C's HTML specification. It will also remove bad URL protocols 437 # from attribute values. 438 ############################################################################### 439 function _hair($attr) 440 { 441 $attrarr = array(); 442 $mode = 0; 443 $attrname = ''; 444 445 # Loop through the whole attribute list 446 447 while (strlen($attr) != 0) 448 { 449 # Was the last operation successful? 450 $working = 0; 451 switch ($mode) 452 { 453 case 0: # attribute name, href for instance 454 if (preg_match('/^([-a-zA-Z]+)/', $attr, $match)) 455 { 456 $attrname = strtolower($match[1]); 457 $working = $mode = 1; 458 $attr = preg_replace('/^[-a-zA-Z]+/', '', $attr); 459 } 460 break; 461 case 1: # equals sign or valueless ("selected") 462 if (preg_match('/^\s*=\s*/', $attr)) # equals sign 463 { 464 $working = 1; 465 $mode = 2; 466 $attr = preg_replace('/^\s*=\s*/', '', $attr); 467 break; 468 } 469 if (preg_match('/^\s+/', $attr)) # valueless 470 { 471 $working = 1; 472 $mode = 0; 473 $attrarr[] = array( 474 'name' => strtolower($attrname), 475 'value' => '', 476 'whole' => $attrname, 477 'vless' => 'y' 478 ); 479 $attr = preg_replace('/^\s+/', '', $attr); 480 } 481 break; 482 case 2: # attribute value, a URL after href= for instance 483 if (preg_match('/^"([^"]*)"(\s+|$)/', $attr, $match)) # "value" 484 { 485 $thisval = $this->_bad_protocol($match[1]); 486 $attrarr[] = array( 487 'name' => strtolower($attrname), 488 'value' => $thisval, 489 'whole' => "$attrname=\"$thisval\"", 490 'vless' => 'n' 491 ); 492 $working = 1; 493 $mode = 0; 494 $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr); 495 break; 496 } 497 if (preg_match("/^'([^']*)'(\s+|$)/", $attr, $match)) # 'value' 498 { 499 $thisval = $this->_bad_protocol($match[1]); 500 $attrarr[] = array( 501 'name' => strtolower($attrname), 502 'value' => $thisval, 503 'whole' => "$attrname='$thisval'", 504 'vless' => 'n' 505 ); 506 $working = 1; 507 $mode = 0; 508 $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr); 509 break; 510 } 511 if (preg_match("%^([^\s\"']+)(\s+|$)%", $attr, $match)) # value 512 { 513 $thisval = $this->_bad_protocol($match[1]); 514 $attrarr[] = array( 515 'name' => strtolower($attrname), 516 'value' => $thisval, 517 'whole' => "$attrname=\"$thisval\"", 518 'vless' => 'n' 519 ); 520 # We add quotes to conform to W3C's HTML spec. 521 $working = 1; 522 $mode = 0; 523 $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr); 524 } 525 if( $this->xhtmlConverterOnly ) { 526 if (preg_match("%^([^\s\"']+)(\s+|\"$)%", $attr, $match)) # value" 527 { 528 $thisval = $this->_bad_protocol($match[1]); 529 $attrarr[] = array( 530 'name' => strtolower($attrname), 531 'value' => $thisval, 532 'whole' => "$attrname=\"$thisval\"", 533 'vless' => 'n' 534 ); 535 # We add quotes to conform to W3C's HTML spec. 536 $working = 1; 537 $mode = 0; 538 $attr = preg_replace("%^[^\s\"']+(\s+|\"$)%", '', $attr); 539 } 540 if (preg_match("%^\"(.*)$%", $attr, $match)) # "value 541 { 542 $thisval = $this->_bad_protocol($match[1]); 543 $attrarr[] = array( 544 'name' => strtolower($attrname), 545 'value' => $thisval, 546 'whole' => "$attrname=\"$thisval\"", 547 'vless' => 'n' 548 ); 549 # We add quotes to conform to W3C's HTML spec. 550 $working = 1; 551 $mode = 0; 552 $attr = preg_replace("%^\"(.*)$%", '', $attr); 553 } 554 } 555 556 break; 557 } # switch 558 559 if ($working == 0) # not well formed, remove and try again 560 { 561 $attr = $this->_html_error($attr); 562 $mode = 0; 563 } 564 } # while 565 566 # special case, for when the attribute list ends with a valueless 567 # attribute like "selected" 568 if ($mode == 1) 569 { 570 $attrarr[] = array( 571 'name' => $attrname, 572 'value' => '', 573 'whole' => $attrname, 574 'vless' => 'y' 575 ); 576 } 577 578 return $attrarr; 579 } # function _hair 580 581 ############################################################################### 582 # This function removes all non-allowed protocols from the beginning of 583 # $string. It ignores whitespace and the case of the letters, and it does 584 # understand HTML entities. It does its work in a while loop, so it won't be 585 # fooled by a string like "javascript:javascript:alert(57)". 586 ############################################################################### 587 function _bad_protocol($string) 588 { 589 $string = $this->_no_null($string); 590 $string2 = $string.'a'; 591 592 while ($string != $string2) 593 { 594 $string2 = $string; 595 $string = $this->_bad_protocol_once($string); 596 } # while 597 return $string; 598 } # function _bad_protocol 599 600 ############################################################################### 601 # This function searches for URL protocols at the beginning of $string, while 602 # handling whitespace and HTML entities. 603 ############################################################################### 604 function _bad_protocol_once($string) 605 { 606 return preg_replace( 607 '/^((&[^;]*;|[\sA-Za-z0-9])*)'. 608 '(:|:|&#[Xx]3[Aa];)(\/|/|&#[Xx]2[Ff];)(\/|/|&#[Xx]2[Ff];)\s*/e', 609 '\$this->_bad_protocol_once2("\\1")', 610 $string 611 ); 612 } # function _bad_protocol_once 613 614 615 ############################################################################### 616 # This function processes URL protocols, checks to see if they're in the white- 617 # list or not, and returns different data depending on the answer. 618 ############################################################################### 619 function _bad_protocol_once2($string) 620 { 621 $string2 = $this->_decode_entities($string); 622 $string2 = preg_replace('/\s/', '', $string2); 623 $string2 = $this->_no_null($string2); 624 $string2 = strtolower($string2); 625 626 $allowed = false; 627 foreach ($this->allowed_protocols as $one_protocol) 628 { 629 if (strtolower($one_protocol) == $string2) 630 { 631 $allowed = true; 632 break; 633 } 634 } 635 636 if ($allowed) 637 { 638 return "$string2://"; 639 } 640 else 641 { 642 return ''; 643 } 644 } # function _bad_protocol_once2 645 646 ############################################################################### 647 # This function performs different checks for attribute values. The currently 648 # implemented checks are "maxlen", "minlen", "maxval", "minval" and "valueless" 649 # with even more checks to come soon. 650 ############################################################################### 651 function _check_attr_val($value, $vless, $checkname, $checkvalue) 652 { 653 $ok = true; 654 655 switch (strtolower($checkname)) 656 { 657 # The maxlen check makes sure that the attribute value has a length not 658 # greater than the given value. This can be used to avoid Buffer Overflows 659 # in WWW clients and various Internet servers. 660 case 'maxlen': 661 if (strlen($value) > $checkvalue) 662 { 663 $ok = false; 664 } 665 break; 666 667 # The minlen check makes sure that the attribute value has a length not 668 # smaller than the given value. 669 case 'minlen': 670 if (strlen($value) < $checkvalue) 671 { 672 $ok = false; 673 } 674 break; 675 676 # The maxval check does two things: it checks that the attribute value is 677 # an integer from 0 and up, without an excessive amount of zeroes or 678 # whitespace (to avoid Buffer Overflows). It also checks that the attribute 679 # value is not greater than the given value. 680 # This check can be used to avoid Denial of Service attacks. 681 case 'maxval': 682 if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value)) 683 { 684 $ok = false; 685 } 686 if ($value > $checkvalue) 687 { 688 $ok = false; 689 } 690 break; 691 692 # The minval check checks that the attribute value is a positive integer, 693 # and that it is not smaller than the given value. 694 case 'minval': 695 if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value)) 696 { 697 $ok = false; 698 } 699 if ($value < $checkvalue) 700 { 701 $ok = false; 702 } 703 break; 704 705 # The valueless check checks if the attribute has a value 706 # (like <a href="blah">) or not (<option selected>). If the given value 707 # is a "y" or a "Y", the attribute must not have a value. 708 # If the given value is an "n" or an "N", the attribute must have one. 709 case 'valueless': 710 if (strtolower($checkvalue) != $vless) 711 { 712 $ok = false; 713 } 714 break; 715 716 } # switch 717 718 return $ok; 719 } # function _check_attr_val 720 721 ############################################################################### 722 # This function changes the character sequence \" to just " 723 # It leaves all other slashes alone. It's really weird, but the quoting from 724 # preg_replace(//e) seems to require this. 725 ############################################################################### 726 function _stripslashes($string) 727 { 728 return preg_replace('%\\\\"%', '"', $string); 729 } # function _stripslashes 730 731 ############################################################################### 732 # This function deals with parsing errors in _hair(). The general plan is 733 # to remove everything to and including some whitespace, but it deals with 734 # quotes and apostrophes as well. 735 ############################################################################### 736 function _html_error($string) 737 { 738 $result = preg_replace('/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string); 739 return $result; 740 } # function _html_error 741 742 ############################################################################### 743 # This function decodes numeric HTML entities (A and A). It doesn't 744 # do anything with other entities like ä, but we don't need them in the 745 # URL protocol white listing system anyway. 746 ############################################################################### 747 function _decode_entities($string) 748 { 749 $string = preg_replace('/&#([0-9]+);/e', 'chr("\\1")', $string); 750 $string = preg_replace('/&#[Xx]([0-9A-Fa-f]+);/e', 'chr(hexdec("\\1"))', $string); 751 return $string; 752 } # function _decode_entities 753 754 ############################################################################### 755 # This function returns kses' version number. 756 ############################################################################### 757 function _version() 758 { 759 return '0.0.2 (OOP fork of kses 0.2.1)'; 760 } # function _version 761 } 762 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Mon Nov 26 21:04:15 2007 | par Balluche grâce à PHPXref 0.7 |
|