444 'cap', 'cup', 'int', 'sim', 'cong', 'asymp', |
486 'cap', 'cup', 'int', 'sim', 'cong', 'asymp', |
445 'ne', 'equiv', 'le', 'ge', 'sub', 'sup', |
487 'ne', 'equiv', 'le', 'ge', 'sub', 'sup', |
446 'nsub', 'sube', 'supe', 'oplus', 'otimes', 'perp', |
488 'nsub', 'sube', 'supe', 'oplus', 'otimes', 'perp', |
447 'sdot', 'lceil', 'rceil', 'lfloor', 'rfloor', 'lang', |
489 'sdot', 'lceil', 'rceil', 'lfloor', 'rfloor', 'lang', |
448 'rang', 'loz', 'spades', 'clubs', 'hearts', 'diams', |
490 'rang', 'loz', 'spades', 'clubs', 'hearts', 'diams', |
|
491 'sup1', 'sup2', 'sup3', 'frac14', 'frac12', 'frac34', |
|
492 'there4', |
449 ); |
493 ); |
450 |
494 |
451 $allowedposttags = array_map( '_wp_add_global_attributes', $allowedposttags ); |
495 $allowedposttags = array_map( '_wp_add_global_attributes', $allowedposttags ); |
452 } else { |
496 } else { |
453 $allowedtags = wp_kses_array_lc( $allowedtags ); |
497 $allowedtags = wp_kses_array_lc( $allowedtags ); |
494 * @return array List of allowed tags and their allowed attributes. |
538 * @return array List of allowed tags and their allowed attributes. |
495 */ |
539 */ |
496 function wp_kses_allowed_html( $context = '' ) { |
540 function wp_kses_allowed_html( $context = '' ) { |
497 global $allowedposttags, $allowedtags, $allowedentitynames; |
541 global $allowedposttags, $allowedtags, $allowedentitynames; |
498 |
542 |
499 if ( is_array( $context ) ) |
543 if ( is_array( $context ) ) { |
|
544 /** |
|
545 * Filter HTML elements allowed for a given context. |
|
546 * |
|
547 * @since 3.5.0 |
|
548 * |
|
549 * @param string $tags Allowed tags, attributes, and/or entities. |
|
550 * @param string $context Context to judge allowed tags by. Allowed values are 'post', |
|
551 * 'data', 'strip', 'entities', 'explicit', or the name of a filter. |
|
552 */ |
500 return apply_filters( 'wp_kses_allowed_html', $context, 'explicit' ); |
553 return apply_filters( 'wp_kses_allowed_html', $context, 'explicit' ); |
|
554 } |
501 |
555 |
502 switch ( $context ) { |
556 switch ( $context ) { |
503 case 'post': |
557 case 'post': |
|
558 /** This filter is documented in wp-includes/kses.php */ |
504 return apply_filters( 'wp_kses_allowed_html', $allowedposttags, $context ); |
559 return apply_filters( 'wp_kses_allowed_html', $allowedposttags, $context ); |
505 break; |
560 |
506 case 'user_description': |
561 case 'user_description': |
507 case 'pre_user_description': |
562 case 'pre_user_description': |
508 $tags = $allowedtags; |
563 $tags = $allowedtags; |
509 $tags['a']['rel'] = true; |
564 $tags['a']['rel'] = true; |
|
565 /** This filter is documented in wp-includes/kses.php */ |
510 return apply_filters( 'wp_kses_allowed_html', $tags, $context ); |
566 return apply_filters( 'wp_kses_allowed_html', $tags, $context ); |
511 break; |
567 |
512 case 'strip': |
568 case 'strip': |
|
569 /** This filter is documented in wp-includes/kses.php */ |
513 return apply_filters( 'wp_kses_allowed_html', array(), $context ); |
570 return apply_filters( 'wp_kses_allowed_html', array(), $context ); |
514 break; |
571 |
515 case 'entities': |
572 case 'entities': |
|
573 /** This filter is documented in wp-includes/kses.php */ |
516 return apply_filters( 'wp_kses_allowed_html', $allowedentitynames, $context); |
574 return apply_filters( 'wp_kses_allowed_html', $allowedentitynames, $context); |
517 break; |
575 |
518 case 'data': |
576 case 'data': |
519 default: |
577 default: |
|
578 /** This filter is documented in wp-includes/kses.php */ |
520 return apply_filters( 'wp_kses_allowed_html', $allowedtags, $context ); |
579 return apply_filters( 'wp_kses_allowed_html', $allowedtags, $context ); |
521 } |
580 } |
522 } |
581 } |
523 |
582 |
524 /** |
583 /** |
533 * @param array $allowed_html List of allowed HTML elements |
592 * @param array $allowed_html List of allowed HTML elements |
534 * @param array $allowed_protocols Allowed protocol in links |
593 * @param array $allowed_protocols Allowed protocol in links |
535 * @return string Filtered content through 'pre_kses' hook |
594 * @return string Filtered content through 'pre_kses' hook |
536 */ |
595 */ |
537 function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) { |
596 function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) { |
538 $string = apply_filters('pre_kses', $string, $allowed_html, $allowed_protocols); |
597 /** |
|
598 * Filter content to be run through kses. |
|
599 * |
|
600 * @since 2.3.0 |
|
601 * |
|
602 * @param string $string Content to run through kses. |
|
603 * @param array $allowed_html Allowed HTML elements. |
|
604 * @param array $allowed_protocols Allowed protocol in links. |
|
605 */ |
|
606 $string = apply_filters( 'pre_kses', $string, $allowed_html, $allowed_protocols ); |
539 return $string; |
607 return $string; |
540 } |
608 } |
541 |
609 |
542 /** |
610 /** |
543 * This function returns kses' version number. |
611 * This function returns kses' version number. |
592 * through another filter which will remove illegal attributes and once that is |
660 * through another filter which will remove illegal attributes and once that is |
593 * completed, will be returned. |
661 * completed, will be returned. |
594 * |
662 * |
595 * @access private |
663 * @access private |
596 * @since 1.0.0 |
664 * @since 1.0.0 |
597 * @uses wp_kses_attr() |
|
598 * |
665 * |
599 * @param string $string Content to filter |
666 * @param string $string Content to filter |
600 * @param array $allowed_html Allowed HTML elements |
667 * @param array $allowed_html Allowed HTML elements |
601 * @param array $allowed_protocols Allowed protocols to keep |
668 * @param array $allowed_protocols Allowed protocols to keep |
602 * @return string Fixed HTML element |
669 * @return string Fixed HTML element |
604 function wp_kses_split2($string, $allowed_html, $allowed_protocols) { |
671 function wp_kses_split2($string, $allowed_html, $allowed_protocols) { |
605 $string = wp_kses_stripslashes($string); |
672 $string = wp_kses_stripslashes($string); |
606 |
673 |
607 if (substr($string, 0, 1) != '<') |
674 if (substr($string, 0, 1) != '<') |
608 return '>'; |
675 return '>'; |
609 # It matched a ">" character |
676 // It matched a ">" character |
610 |
677 |
611 if ( '<!--' == substr( $string, 0, 4 ) ) { |
678 if ( '<!--' == substr( $string, 0, 4 ) ) { |
612 $string = str_replace( array('<!--', '-->'), '', $string ); |
679 $string = str_replace( array('<!--', '-->'), '', $string ); |
613 while ( $string != ($newstring = wp_kses($string, $allowed_html, $allowed_protocols)) ) |
680 while ( $string != ($newstring = wp_kses($string, $allowed_html, $allowed_protocols)) ) |
614 $string = $newstring; |
681 $string = $newstring; |
618 $string = preg_replace('/--+/', '-', $string); |
685 $string = preg_replace('/--+/', '-', $string); |
619 // prevent three dashes closing a comment |
686 // prevent three dashes closing a comment |
620 $string = preg_replace('/-$/', '', $string); |
687 $string = preg_replace('/-$/', '', $string); |
621 return "<!--{$string}-->"; |
688 return "<!--{$string}-->"; |
622 } |
689 } |
623 # Allow HTML comments |
690 // Allow HTML comments |
624 |
691 |
625 if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches)) |
692 if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches)) |
626 return ''; |
693 return ''; |
627 # It's seriously malformed |
694 // It's seriously malformed |
628 |
695 |
629 $slash = trim($matches[1]); |
696 $slash = trim($matches[1]); |
630 $elem = $matches[2]; |
697 $elem = $matches[2]; |
631 $attrlist = $matches[3]; |
698 $attrlist = $matches[3]; |
632 |
699 |
633 if ( ! is_array( $allowed_html ) ) |
700 if ( ! is_array( $allowed_html ) ) |
634 $allowed_html = wp_kses_allowed_html( $allowed_html ); |
701 $allowed_html = wp_kses_allowed_html( $allowed_html ); |
635 |
702 |
636 if ( ! isset($allowed_html[strtolower($elem)]) ) |
703 if ( ! isset($allowed_html[strtolower($elem)]) ) |
637 return ''; |
704 return ''; |
638 # They are using a not allowed HTML element |
705 // They are using a not allowed HTML element |
639 |
706 |
640 if ($slash != '') |
707 if ($slash != '') |
641 return "</$elem>"; |
708 return "</$elem>"; |
642 # No attributes are allowed for closing elements |
709 // No attributes are allowed for closing elements |
643 |
710 |
644 return wp_kses_attr( $elem, $attrlist, $allowed_html, $allowed_protocols ); |
711 return wp_kses_attr( $elem, $attrlist, $allowed_html, $allowed_protocols ); |
645 } |
712 } |
646 |
713 |
647 /** |
714 /** |
660 * @param array $allowed_html Allowed HTML elements |
727 * @param array $allowed_html Allowed HTML elements |
661 * @param array $allowed_protocols Allowed protocols to keep |
728 * @param array $allowed_protocols Allowed protocols to keep |
662 * @return string Sanitized HTML element |
729 * @return string Sanitized HTML element |
663 */ |
730 */ |
664 function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) { |
731 function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) { |
665 # Is there a closing XHTML slash at the end of the attributes? |
732 // Is there a closing XHTML slash at the end of the attributes? |
666 |
733 |
667 if ( ! is_array( $allowed_html ) ) |
734 if ( ! is_array( $allowed_html ) ) |
668 $allowed_html = wp_kses_allowed_html( $allowed_html ); |
735 $allowed_html = wp_kses_allowed_html( $allowed_html ); |
669 |
736 |
670 $xhtml_slash = ''; |
737 $xhtml_slash = ''; |
671 if (preg_match('%\s*/\s*$%', $attr)) |
738 if (preg_match('%\s*/\s*$%', $attr)) |
672 $xhtml_slash = ' /'; |
739 $xhtml_slash = ' /'; |
673 |
740 |
674 # Are any attributes allowed at all for this element? |
741 // Are any attributes allowed at all for this element? |
675 if ( ! isset($allowed_html[strtolower($element)]) || count($allowed_html[strtolower($element)]) == 0 ) |
742 if ( ! isset($allowed_html[strtolower($element)]) || count($allowed_html[strtolower($element)]) == 0 ) |
676 return "<$element$xhtml_slash>"; |
743 return "<$element$xhtml_slash>"; |
677 |
744 |
678 # Split it |
745 // Split it |
679 $attrarr = wp_kses_hair($attr, $allowed_protocols); |
746 $attrarr = wp_kses_hair($attr, $allowed_protocols); |
680 |
747 |
681 # Go through $attrarr, and save the allowed attributes for this element |
748 // Go through $attrarr, and save the allowed attributes for this element |
682 # in $attr2 |
749 // in $attr2 |
683 $attr2 = ''; |
750 $attr2 = ''; |
684 |
751 |
685 $allowed_attr = $allowed_html[strtolower($element)]; |
752 $allowed_attr = $allowed_html[strtolower($element)]; |
686 foreach ($attrarr as $arreach) { |
753 foreach ($attrarr as $arreach) { |
687 if ( ! isset( $allowed_attr[strtolower($arreach['name'])] ) ) |
754 if ( ! isset( $allowed_attr[strtolower($arreach['name'])] ) ) |
688 continue; # the attribute is not allowed |
755 continue; // the attribute is not allowed |
689 |
756 |
690 $current = $allowed_attr[strtolower($arreach['name'])]; |
757 $current = $allowed_attr[strtolower($arreach['name'])]; |
691 if ( $current == '' ) |
758 if ( $current == '' ) |
692 continue; # the attribute is not allowed |
759 continue; // the attribute is not allowed |
693 |
760 |
694 if ( strtolower( $arreach['name'] ) == 'style' ) { |
761 if ( strtolower( $arreach['name'] ) == 'style' ) { |
695 $orig_value = $arreach['value']; |
762 $orig_value = $arreach['value']; |
696 $value = safecss_filter_attr( $orig_value ); |
763 $value = safecss_filter_attr( $orig_value ); |
697 |
764 |
702 $arreach['whole'] = str_replace( $orig_value, $value, $arreach['whole'] ); |
769 $arreach['whole'] = str_replace( $orig_value, $value, $arreach['whole'] ); |
703 } |
770 } |
704 |
771 |
705 if ( ! is_array($current) ) { |
772 if ( ! is_array($current) ) { |
706 $attr2 .= ' '.$arreach['whole']; |
773 $attr2 .= ' '.$arreach['whole']; |
707 # there are no checks |
774 // there are no checks |
708 |
775 |
709 } else { |
776 } else { |
710 # there are some checks |
777 // there are some checks |
711 $ok = true; |
778 $ok = true; |
712 foreach ($current as $currkey => $currval) { |
779 foreach ($current as $currkey => $currval) { |
713 if ( ! wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval) ) { |
780 if ( ! wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval) ) { |
714 $ok = false; |
781 $ok = false; |
715 break; |
782 break; |
716 } |
783 } |
717 } |
784 } |
718 |
785 |
719 if ( $ok ) |
786 if ( $ok ) |
720 $attr2 .= ' '.$arreach['whole']; # it passed them |
787 $attr2 .= ' '.$arreach['whole']; // it passed them |
721 } # if !is_array($current) |
788 } // if !is_array($current) |
722 } # foreach |
789 } // foreach |
723 |
790 |
724 # Remove any "<" or ">" characters |
791 // Remove any "<" or ">" characters |
725 $attr2 = preg_replace('/[<>]/', '', $attr2); |
792 $attr2 = preg_replace('/[<>]/', '', $attr2); |
726 |
793 |
727 return "<$element$attr2$xhtml_slash>"; |
794 return "<$element$attr2$xhtml_slash>"; |
728 } |
795 } |
729 |
796 |
748 $attrarr = array(); |
815 $attrarr = array(); |
749 $mode = 0; |
816 $mode = 0; |
750 $attrname = ''; |
817 $attrname = ''; |
751 $uris = array('xmlns', 'profile', 'href', 'src', 'cite', 'classid', 'codebase', 'data', 'usemap', 'longdesc', 'action'); |
818 $uris = array('xmlns', 'profile', 'href', 'src', 'cite', 'classid', 'codebase', 'data', 'usemap', 'longdesc', 'action'); |
752 |
819 |
753 # Loop through the whole attribute list |
820 // Loop through the whole attribute list |
754 |
821 |
755 while (strlen($attr) != 0) { |
822 while (strlen($attr) != 0) { |
756 $working = 0; # Was the last operation successful? |
823 $working = 0; // Was the last operation successful? |
757 |
824 |
758 switch ($mode) { |
825 switch ($mode) { |
759 case 0 : # attribute name, href for instance |
826 case 0 : // attribute name, href for instance |
760 |
827 |
761 if (preg_match('/^([-a-zA-Z]+)/', $attr, $match)) { |
828 if ( preg_match('/^([-a-zA-Z:]+)/', $attr, $match ) ) { |
762 $attrname = $match[1]; |
829 $attrname = $match[1]; |
763 $working = $mode = 1; |
830 $working = $mode = 1; |
764 $attr = preg_replace('/^[-a-zA-Z]+/', '', $attr); |
831 $attr = preg_replace( '/^[-a-zA-Z:]+/', '', $attr ); |
765 } |
832 } |
766 |
833 |
767 break; |
834 break; |
768 |
835 |
769 case 1 : # equals sign or valueless ("selected") |
836 case 1 : // equals sign or valueless ("selected") |
770 |
837 |
771 if (preg_match('/^\s*=\s*/', $attr)) # equals sign |
838 if (preg_match('/^\s*=\s*/', $attr)) // equals sign |
772 { |
839 { |
773 $working = 1; |
840 $working = 1; |
774 $mode = 2; |
841 $mode = 2; |
775 $attr = preg_replace('/^\s*=\s*/', '', $attr); |
842 $attr = preg_replace('/^\s*=\s*/', '', $attr); |
776 break; |
843 break; |
777 } |
844 } |
778 |
845 |
779 if (preg_match('/^\s+/', $attr)) # valueless |
846 if (preg_match('/^\s+/', $attr)) // valueless |
780 { |
847 { |
781 $working = 1; |
848 $working = 1; |
782 $mode = 0; |
849 $mode = 0; |
783 if(false === array_key_exists($attrname, $attrarr)) { |
850 if(false === array_key_exists($attrname, $attrarr)) { |
784 $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y'); |
851 $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y'); |
786 $attr = preg_replace('/^\s+/', '', $attr); |
853 $attr = preg_replace('/^\s+/', '', $attr); |
787 } |
854 } |
788 |
855 |
789 break; |
856 break; |
790 |
857 |
791 case 2 : # attribute value, a URL after href= for instance |
858 case 2 : // attribute value, a URL after href= for instance |
792 |
859 |
793 if (preg_match('%^"([^"]*)"(\s+|/?$)%', $attr, $match)) |
860 if (preg_match('%^"([^"]*)"(\s+|/?$)%', $attr, $match)) |
794 # "value" |
861 // "value" |
795 { |
862 { |
796 $thisval = $match[1]; |
863 $thisval = $match[1]; |
797 if ( in_array(strtolower($attrname), $uris) ) |
864 if ( in_array(strtolower($attrname), $uris) ) |
798 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); |
865 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); |
799 |
866 |
805 $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr); |
872 $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr); |
806 break; |
873 break; |
807 } |
874 } |
808 |
875 |
809 if (preg_match("%^'([^']*)'(\s+|/?$)%", $attr, $match)) |
876 if (preg_match("%^'([^']*)'(\s+|/?$)%", $attr, $match)) |
810 # 'value' |
877 // 'value' |
811 { |
878 { |
812 $thisval = $match[1]; |
879 $thisval = $match[1]; |
813 if ( in_array(strtolower($attrname), $uris) ) |
880 if ( in_array(strtolower($attrname), $uris) ) |
814 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); |
881 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); |
815 |
882 |
821 $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr); |
888 $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr); |
822 break; |
889 break; |
823 } |
890 } |
824 |
891 |
825 if (preg_match("%^([^\s\"']+)(\s+|/?$)%", $attr, $match)) |
892 if (preg_match("%^([^\s\"']+)(\s+|/?$)%", $attr, $match)) |
826 # value |
893 // value |
827 { |
894 { |
828 $thisval = $match[1]; |
895 $thisval = $match[1]; |
829 if ( in_array(strtolower($attrname), $uris) ) |
896 if ( in_array(strtolower($attrname), $uris) ) |
830 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); |
897 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); |
831 |
898 |
832 if(false === array_key_exists($attrname, $attrarr)) { |
899 if(false === array_key_exists($attrname, $attrarr)) { |
833 $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n'); |
900 $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n'); |
834 } |
901 } |
835 # We add quotes to conform to W3C's HTML spec. |
902 // We add quotes to conform to W3C's HTML spec. |
836 $working = 1; |
903 $working = 1; |
837 $mode = 0; |
904 $mode = 0; |
838 $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr); |
905 $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr); |
839 } |
906 } |
840 |
907 |
841 break; |
908 break; |
842 } # switch |
909 } // switch |
843 |
910 |
844 if ($working == 0) # not well formed, remove and try again |
911 if ($working == 0) // not well formed, remove and try again |
845 { |
912 { |
846 $attr = wp_kses_html_error($attr); |
913 $attr = wp_kses_html_error($attr); |
847 $mode = 0; |
914 $mode = 0; |
848 } |
915 } |
849 } # while |
916 } // while |
850 |
917 |
851 if ($mode == 1 && false === array_key_exists($attrname, $attrarr)) |
918 if ($mode == 1 && false === array_key_exists($attrname, $attrarr)) |
852 # special case, for when the attribute list ends with a valueless |
919 // special case, for when the attribute list ends with a valueless |
853 # attribute like "selected" |
920 // attribute like "selected" |
854 $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y'); |
921 $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y'); |
855 |
922 |
856 return $attrarr; |
923 return $attrarr; |
857 } |
924 } |
858 |
925 |
873 function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) { |
940 function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) { |
874 $ok = true; |
941 $ok = true; |
875 |
942 |
876 switch (strtolower($checkname)) { |
943 switch (strtolower($checkname)) { |
877 case 'maxlen' : |
944 case 'maxlen' : |
878 # The maxlen check makes sure that the attribute value has a length not |
945 // The maxlen check makes sure that the attribute value has a length not |
879 # greater than the given value. This can be used to avoid Buffer Overflows |
946 // greater than the given value. This can be used to avoid Buffer Overflows |
880 # in WWW clients and various Internet servers. |
947 // in WWW clients and various Internet servers. |
881 |
948 |
882 if (strlen($value) > $checkvalue) |
949 if (strlen($value) > $checkvalue) |
883 $ok = false; |
950 $ok = false; |
884 break; |
951 break; |
885 |
952 |
886 case 'minlen' : |
953 case 'minlen' : |
887 # The minlen check makes sure that the attribute value has a length not |
954 // The minlen check makes sure that the attribute value has a length not |
888 # smaller than the given value. |
955 // smaller than the given value. |
889 |
956 |
890 if (strlen($value) < $checkvalue) |
957 if (strlen($value) < $checkvalue) |
891 $ok = false; |
958 $ok = false; |
892 break; |
959 break; |
893 |
960 |
894 case 'maxval' : |
961 case 'maxval' : |
895 # The maxval check does two things: it checks that the attribute value is |
962 // The maxval check does two things: it checks that the attribute value is |
896 # an integer from 0 and up, without an excessive amount of zeroes or |
963 // an integer from 0 and up, without an excessive amount of zeroes or |
897 # whitespace (to avoid Buffer Overflows). It also checks that the attribute |
964 // whitespace (to avoid Buffer Overflows). It also checks that the attribute |
898 # value is not greater than the given value. |
965 // value is not greater than the given value. |
899 # This check can be used to avoid Denial of Service attacks. |
966 // This check can be used to avoid Denial of Service attacks. |
900 |
967 |
901 if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value)) |
968 if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value)) |
902 $ok = false; |
969 $ok = false; |
903 if ($value > $checkvalue) |
970 if ($value > $checkvalue) |
904 $ok = false; |
971 $ok = false; |
905 break; |
972 break; |
906 |
973 |
907 case 'minval' : |
974 case 'minval' : |
908 # The minval check makes sure that the attribute value is a positive integer, |
975 // The minval check makes sure that the attribute value is a positive integer, |
909 # and that it is not smaller than the given value. |
976 // and that it is not smaller than the given value. |
910 |
977 |
911 if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value)) |
978 if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value)) |
912 $ok = false; |
979 $ok = false; |
913 if ($value < $checkvalue) |
980 if ($value < $checkvalue) |
914 $ok = false; |
981 $ok = false; |
915 break; |
982 break; |
916 |
983 |
917 case 'valueless' : |
984 case 'valueless' : |
918 # The valueless check makes sure if the attribute has a value |
985 // The valueless check makes sure if the attribute has a value |
919 # (like <a href="blah">) or not (<option selected>). If the given value |
986 // (like <a href="blah">) or not (<option selected>). If the given value |
920 # is a "y" or a "Y", the attribute must not have a value. |
987 // is a "y" or a "Y", the attribute must not have a value. |
921 # If the given value is an "n" or an "N", the attribute must have one. |
988 // If the given value is an "n" or an "N", the attribute must have one. |
922 |
989 |
923 if (strtolower($checkvalue) != $vless) |
990 if (strtolower($checkvalue) != $vless) |
924 $ok = false; |
991 $ok = false; |
925 break; |
992 break; |
926 } # switch |
993 } // switch |
927 |
994 |
928 return $ok; |
995 return $ok; |
929 } |
996 } |
930 |
997 |
931 /** |
998 /** |
956 |
1023 |
957 return $string; |
1024 return $string; |
958 } |
1025 } |
959 |
1026 |
960 /** |
1027 /** |
961 * Removes any null characters in $string. |
1028 * Removes any invalid control characters in $string. |
|
1029 * |
|
1030 * Also removes any instance of the '\0' string. |
962 * |
1031 * |
963 * @since 1.0.0 |
1032 * @since 1.0.0 |
964 * |
1033 * |
965 * @param string $string |
1034 * @param string $string |
966 * @return string |
1035 * @return string |
967 */ |
1036 */ |
968 function wp_kses_no_null($string) { |
1037 function wp_kses_no_null($string) { |
969 $string = preg_replace('/\0+/', '', $string); |
1038 $string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string); |
970 $string = preg_replace('/(\\\\0)+/', '', $string); |
1039 $string = preg_replace('/(\\\\0)+/', '', $string); |
971 |
1040 |
972 return $string; |
1041 return $string; |
973 } |
1042 } |
974 |
1043 |
1102 } |
1171 } |
1103 |
1172 |
1104 /** |
1173 /** |
1105 * Converts and fixes HTML entities. |
1174 * Converts and fixes HTML entities. |
1106 * |
1175 * |
1107 * This function normalizes HTML entities. It will convert "AT&T" to the correct |
1176 * This function normalizes HTML entities. It will convert `AT&T` to the correct |
1108 * "AT&T", ":" to ":", "&#XYZZY;" to "&#XYZZY;" and so on. |
1177 * `AT&T`, `:` to `:`, `&#XYZZY;` to `&#XYZZY;` and so on. |
1109 * |
1178 * |
1110 * @since 1.0.0 |
1179 * @since 1.0.0 |
1111 * |
1180 * |
1112 * @param string $string Content to normalize entities |
1181 * @param string $string Content to normalize entities |
1113 * @return string Content with normalized entities |
1182 * @return string Content with normalized entities |
1114 */ |
1183 */ |
1115 function wp_kses_normalize_entities($string) { |
1184 function wp_kses_normalize_entities($string) { |
1116 # Disarm all entities by converting & to & |
1185 // Disarm all entities by converting & to & |
1117 |
1186 |
1118 $string = str_replace('&', '&', $string); |
1187 $string = str_replace('&', '&', $string); |
1119 |
1188 |
1120 # Change back the allowed entities in our entity whitelist |
1189 // Change back the allowed entities in our entity whitelist |
1121 |
1190 |
1122 $string = preg_replace_callback('/&([A-Za-z]{2,8});/', 'wp_kses_named_entities', $string); |
1191 $string = preg_replace_callback('/&([A-Za-z]{2,8}[0-9]{0,2});/', 'wp_kses_named_entities', $string); |
1123 $string = preg_replace_callback('/&#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $string); |
1192 $string = preg_replace_callback('/&#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $string); |
1124 $string = preg_replace_callback('/&#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $string); |
1193 $string = preg_replace_callback('/&#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $string); |
1125 |
1194 |
1126 return $string; |
1195 return $string; |
1127 } |
1196 } |
1207 } |
1276 } |
1208 |
1277 |
1209 /** |
1278 /** |
1210 * Convert all entities to their character counterparts. |
1279 * Convert all entities to their character counterparts. |
1211 * |
1280 * |
1212 * This function decodes numeric HTML entities (A and A). It doesn't do |
1281 * This function decodes numeric HTML entities (`A` and `A`). |
1213 * anything with other entities like ä, but we don't need them in the URL |
1282 * It doesn't do anything with other entities like ä, but we don't |
1214 * protocol whitelisting system anyway. |
1283 * need them in the URL protocol whitelisting system anyway. |
1215 * |
1284 * |
1216 * @since 1.0.0 |
1285 * @since 1.0.0 |
1217 * |
1286 * |
1218 * @param string $string Content to change entities |
1287 * @param string $string Content to change entities |
1219 * @return string Content after decoded entities |
1288 * @return string Content after decoded entities |
1376 * |
1442 * |
1377 * First removes all of the Kses filters in case the current user does not need |
1443 * First removes all of the Kses filters in case the current user does not need |
1378 * to have Kses filter the content. If the user does not have unfiltered_html |
1444 * to have Kses filter the content. If the user does not have unfiltered_html |
1379 * capability, then Kses filters are added. |
1445 * capability, then Kses filters are added. |
1380 * |
1446 * |
1381 * @uses kses_remove_filters() Removes the Kses filters |
|
1382 * @uses kses_init_filters() Adds the Kses filters back if the user |
|
1383 * does not have unfiltered HTML capability. |
|
1384 * @since 2.0.0 |
1447 * @since 2.0.0 |
1385 */ |
1448 */ |
1386 function kses_init() { |
1449 function kses_init() { |
1387 kses_remove_filters(); |
1450 kses_remove_filters(); |
1388 |
1451 |
1389 if (current_user_can('unfiltered_html') == false) |
1452 if (current_user_can('unfiltered_html') == false) |
1390 kses_init_filters(); |
1453 kses_init_filters(); |
1391 } |
1454 } |
1392 |
|
1393 add_action('init', 'kses_init'); |
|
1394 add_action('set_current_user', 'kses_init'); |
|
1395 |
1455 |
1396 /** |
1456 /** |
1397 * Inline CSS filter |
1457 * Inline CSS filter |
1398 * |
1458 * |
1399 * @since 2.8.1 |
1459 * @since 2.8.1 |
1403 _deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented |
1463 _deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented |
1404 |
1464 |
1405 $css = wp_kses_no_null($css); |
1465 $css = wp_kses_no_null($css); |
1406 $css = str_replace(array("\n","\r","\t"), '', $css); |
1466 $css = str_replace(array("\n","\r","\t"), '', $css); |
1407 |
1467 |
1408 if ( preg_match( '%[\\(&=}]|/\*%', $css ) ) // remove any inline css containing \ ( & } = or comments |
1468 if ( preg_match( '%[\\\\(&=}]|/\*%', $css ) ) // remove any inline css containing \ ( & } = or comments |
1409 return ''; |
1469 return ''; |
1410 |
1470 |
1411 $css_array = explode( ';', trim( $css ) ); |
1471 $css_array = explode( ';', trim( $css ) ); |
|
1472 |
|
1473 /** |
|
1474 * Filter list of allowed CSS attributes. |
|
1475 * |
|
1476 * @since 2.8.1 |
|
1477 * |
|
1478 * @param array $attr List of allowed CSS attributes. |
|
1479 */ |
1412 $allowed_attr = apply_filters( 'safe_style_css', array( 'text-align', 'margin', 'color', 'float', |
1480 $allowed_attr = apply_filters( 'safe_style_css', array( 'text-align', 'margin', 'color', 'float', |
1413 'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color', |
1481 'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color', |
1414 'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left', |
1482 'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left', |
1415 'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color', |
1483 'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color', |
1416 'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top', |
1484 'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top', |