WordPress.org

Make WordPress Core

Ticket #10683: 10683.patch

File 10683.patch, 19.0 KB (added by Simek, 6 years ago)
  • atomlib.php

     
    2121         * @var array 
    2222         * @access public 
    2323         */ 
    24     var $links = array(); 
    25     /** 
    26      * Stores Categories 
    27      * @var array 
    28      * @access public 
    29      */ 
    30     var $categories = array(); 
     24        var $links = array(); 
    3125        /** 
     26         * Stores Categories 
     27         * @var array 
     28         * @access public 
     29         */ 
     30        var $categories = array(); 
     31        /** 
    3232         * Stores Entries 
    3333         * 
    3434         * @var array 
    3535         * @access public 
    3636         */ 
    37     var $entries = array(); 
     37        var $entries = array(); 
    3838} 
    3939 
    4040/** 
     
    4848         * @var array 
    4949         * @access public 
    5050         */ 
    51     var $links = array(); 
    52     /** 
    53     * Stores Categories 
    54     * @var array 
     51        var $links = array(); 
     52        /** 
     53        * Stores Categories 
     54        * @var array 
    5555         * @access public 
    56     */ 
    57     var $categories = array(); 
     56        */ 
     57        var $categories = array(); 
    5858} 
    5959 
    6060/** 
     
    6464 */ 
    6565class AtomParser { 
    6666 
    67     var $NS = 'http://www.w3.org/2005/Atom'; 
    68     var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights'); 
    69     var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft'); 
     67        var $NS = 'http://www.w3.org/2005/Atom'; 
     68        var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights'); 
     69        var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft'); 
    7070 
    71     var $debug = false; 
     71        var $debug = false; 
    7272 
    73     var $depth = 0; 
    74     var $indent = 2; 
    75     var $in_content; 
    76     var $ns_contexts = array(); 
    77     var $ns_decls = array(); 
    78     var $content_ns_decls = array(); 
    79     var $content_ns_contexts = array(); 
    80     var $is_xhtml = false; 
    81     var $is_html = false; 
    82     var $is_text = true; 
    83     var $skipped_div = false; 
     73        var $depth = 0; 
     74        var $indent = 2; 
     75        var $in_content; 
     76        var $ns_contexts = array(); 
     77        var $ns_decls = array(); 
     78        var $content_ns_decls = array(); 
     79        var $content_ns_contexts = array(); 
     80        var $is_xhtml = false; 
     81        var $is_html = false; 
     82        var $is_text = true; 
     83        var $skipped_div = false; 
    8484 
    85     var $FILE = "php://input"; 
     85        var $FILE = "php://input"; 
    8686 
    87     var $feed; 
    88     var $current; 
     87        var $feed; 
     88        var $current; 
    8989 
    90     function AtomParser() { 
     90        function AtomParser() { 
     91                $this->feed = new AtomFeed(); 
     92                $this->current = null; 
     93                $this->map_attrs_func = create_function('$k,$v', 'return "$k=\"$v\"";'); 
     94                $this->map_xmlns_func = create_function('$p,$n', '$xd = "xmlns"; if(strlen($n[0])>0) $xd .= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";'); 
     95        } 
    9196 
    92         $this->feed = new AtomFeed(); 
    93         $this->current = null; 
    94         $this->map_attrs_func = create_function('$k,$v', 'return "$k=\"$v\"";'); 
    95         $this->map_xmlns_func = create_function('$p,$n', '$xd = "xmlns"; if(strlen($n[0])>0) $xd .= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";'); 
    96     } 
     97        function _p($msg) { 
     98                if($this->debug) print str_repeat(" ", $this->depth * $this->indent) . $msg ."\n"; 
     99        } 
    97100 
    98     function _p($msg) { 
    99         if($this->debug) { 
    100             print str_repeat(" ", $this->depth * $this->indent) . $msg ."\n"; 
    101         } 
    102     } 
     101        function error_handler($log_level, $log_text, $error_file, $error_line) { 
     102                $this->error = $log_text; 
     103        } 
    103104 
    104     function error_handler($log_level, $log_text, $error_file, $error_line) { 
    105         $this->error = $log_text; 
    106     } 
     105        function parse() { 
     106                set_error_handler(array(&$this, 'error_handler')); 
    107107 
    108     function parse() { 
     108                array_unshift($this->ns_contexts, array()); 
    109109 
    110         set_error_handler(array(&$this, 'error_handler')); 
     110                $parser = xml_parser_create_ns(); 
     111                xml_set_object($parser, $this); 
     112                xml_set_element_handler($parser, "start_element", "end_element"); 
     113                xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); 
     114                xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0); 
     115                xml_set_character_data_handler($parser, "cdata"); 
     116                xml_set_default_handler($parser, "_default"); 
     117                xml_set_start_namespace_decl_handler($parser, "start_ns"); 
     118                xml_set_end_namespace_decl_handler($parser, "end_ns"); 
    111119 
    112         array_unshift($this->ns_contexts, array()); 
     120                $this->content = ''; 
    113121 
    114         $parser = xml_parser_create_ns(); 
    115         xml_set_object($parser, $this); 
    116         xml_set_element_handler($parser, "start_element", "end_element"); 
    117         xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); 
    118         xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0); 
    119         xml_set_character_data_handler($parser, "cdata"); 
    120         xml_set_default_handler($parser, "_default"); 
    121         xml_set_start_namespace_decl_handler($parser, "start_ns"); 
    122         xml_set_end_namespace_decl_handler($parser, "end_ns"); 
     122                $ret = true; 
    123123 
    124         $this->content = ''; 
     124                $fp = fopen($this->FILE, "r"); 
     125                while ($data = fread($fp, 4096)) { 
     126                        if($this->debug) $this->content .= $data; 
    125127 
    126         $ret = true; 
     128                        if(!xml_parse($parser, $data, feof($fp))) { 
     129                                trigger_error(sprintf(__('XML error: %s at line %d')."\n", 
     130                                        xml_error_string(xml_get_error_code($xml_parser)), 
     131                                        xml_get_current_line_number($xml_parser))); 
     132                                $ret = false; 
     133                                break; 
     134                        } 
     135                } 
     136                fclose($fp); 
    127137 
    128         $fp = fopen($this->FILE, "r"); 
    129         while ($data = fread($fp, 4096)) { 
    130             if($this->debug) $this->content .= $data; 
     138                xml_parser_free($parser); 
    131139 
    132             if(!xml_parse($parser, $data, feof($fp))) { 
    133                 trigger_error(sprintf(__('XML error: %s at line %d')."\n", 
    134                     xml_error_string(xml_get_error_code($xml_parser)), 
    135                     xml_get_current_line_number($xml_parser))); 
    136                 $ret = false; 
    137                 break; 
    138             } 
    139         } 
    140         fclose($fp); 
     140                restore_error_handler(); 
    141141 
    142         xml_parser_free($parser); 
     142                return $ret; 
     143        } 
    143144 
    144         restore_error_handler(); 
     145        function start_element($parser, $name, $attrs) { 
     146                $tag = array_pop(split(":", $name)); 
    145147 
    146         return $ret; 
    147     } 
     148                switch($name) { 
     149                        case $this->NS . ':feed': 
     150                                $this->current = $this->feed; 
     151                                break; 
     152                        case $this->NS . ':entry': 
     153                                $this->current = new AtomEntry(); 
     154                                break; 
     155                }; 
    148156 
    149     function start_element($parser, $name, $attrs) { 
     157                $this->_p("start_element('$name')"); 
     158                #$this->_p(print_r($this->ns_contexts,true)); 
     159                #$this->_p('current(' . $this->current . ')'); 
    150160 
    151         $tag = array_pop(split(":", $name)); 
     161                array_unshift($this->ns_contexts, $this->ns_decls); 
    152162 
    153         switch($name) { 
    154             case $this->NS . ':feed': 
    155                 $this->current = $this->feed; 
    156                 break; 
    157             case $this->NS . ':entry': 
    158                 $this->current = new AtomEntry(); 
    159                 break; 
    160         }; 
     163                $this->depth++; 
    161164 
    162         $this->_p("start_element('$name')"); 
    163         #$this->_p(print_r($this->ns_contexts,true)); 
    164         #$this->_p('current(' . $this->current . ')'); 
     165                if(!empty($this->in_content)) { 
    165166 
    166         array_unshift($this->ns_contexts, $this->ns_decls); 
     167                        $this->content_ns_decls = array(); 
    167168 
    168         $this->depth++; 
     169                        if($this->is_html || $this->is_text) 
     170                                trigger_error("Invalid content in element found. Content must not be of type text or html if it contains markup."); 
    169171 
    170         if(!empty($this->in_content)) { 
     172                        $attrs_prefix = array(); 
    171173 
    172             $this->content_ns_decls = array(); 
     174                        // resolve prefixes for attributes 
     175                        foreach($attrs as $key => $value) { 
     176                                $with_prefix = $this->ns_to_prefix($key, true); 
     177                                $attrs_prefix[$with_prefix[1]] = $this->xml_escape($value); 
     178                        } 
    173179 
    174             if($this->is_html || $this->is_text) 
    175                 trigger_error("Invalid content in element found. Content must not be of type text or html if it contains markup."); 
     180                        $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix))); 
     181                        if(strlen($attrs_str) > 0) 
     182                                $attrs_str = " " . $attrs_str; 
    176183 
    177             $attrs_prefix = array(); 
     184                        $with_prefix = $this->ns_to_prefix($name); 
    178185 
    179             // resolve prefixes for attributes 
    180             foreach($attrs as $key => $value) { 
    181                 $with_prefix = $this->ns_to_prefix($key, true); 
    182                 $attrs_prefix[$with_prefix[1]] = $this->xml_escape($value); 
    183             } 
     186                        if(!$this->is_declared_content_ns($with_prefix[0])) 
     187                                array_push($this->content_ns_decls, $with_prefix[0]); 
    184188 
    185             $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix))); 
    186             if(strlen($attrs_str) > 0) { 
    187                 $attrs_str = " " . $attrs_str; 
    188             } 
     189                        $xmlns_str = ''; 
     190                        if(count($this->content_ns_decls) > 0) { 
     191                                array_unshift($this->content_ns_contexts, $this->content_ns_decls); 
     192                                $xmlns_str .= join(' ', array_map($this->map_xmlns_func, array_keys($this->content_ns_contexts[0]), array_values($this->content_ns_contexts[0]))); 
     193                                if(strlen($xmlns_str) > 0) 
     194                                        $xmlns_str = " " . $xmlns_str; 
     195                        } 
    189196 
    190             $with_prefix = $this->ns_to_prefix($name); 
     197                        array_push($this->in_content, array($tag, $this->depth, "<". $with_prefix[1] ."{$xmlns_str}{$attrs_str}" . ">")); 
    191198 
    192             if(!$this->is_declared_content_ns($with_prefix[0])) { 
    193                 array_push($this->content_ns_decls, $with_prefix[0]); 
    194             } 
     199                } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) { 
     200                        $this->in_content = array(); 
     201                        $this->is_xhtml = $attrs['type'] == 'xhtml'; 
     202                        $this->is_html = $attrs['type'] == 'html' || $attrs['type'] == 'text/html'; 
     203                        $this->is_text = !in_array('type',array_keys($attrs)) || $attrs['type'] == 'text'; 
     204                        $type = $this->is_xhtml ? 'XHTML' : ($this->is_html ? 'HTML' : ($this->is_text ? 'TEXT' : $attrs['type'])); 
    195205 
    196             $xmlns_str = ''; 
    197             if(count($this->content_ns_decls) > 0) { 
    198                 array_unshift($this->content_ns_contexts, $this->content_ns_decls); 
    199                 $xmlns_str .= join(' ', array_map($this->map_xmlns_func, array_keys($this->content_ns_contexts[0]), array_values($this->content_ns_contexts[0]))); 
    200                 if(strlen($xmlns_str) > 0) { 
    201                     $xmlns_str = " " . $xmlns_str; 
    202                 } 
    203             } 
     206                        if(in_array('src',array_keys($attrs))) 
     207                                $this->current->$tag = $attrs; 
     208                        else 
     209                                array_push($this->in_content, array($tag,$this->depth, $type)); 
    204210 
    205             array_push($this->in_content, array($tag, $this->depth, "<". $with_prefix[1] ."{$xmlns_str}{$attrs_str}" . ">")); 
     211                } else if($tag == 'link') { 
     212                        array_push($this->current->links, $attrs); 
     213                } else if($tag == 'category') { 
     214                        array_push($this->current->categories, $attrs); 
     215                } 
    206216 
    207         } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) { 
    208             $this->in_content = array(); 
    209             $this->is_xhtml = $attrs['type'] == 'xhtml'; 
    210             $this->is_html = $attrs['type'] == 'html' || $attrs['type'] == 'text/html'; 
    211             $this->is_text = !in_array('type',array_keys($attrs)) || $attrs['type'] == 'text'; 
    212             $type = $this->is_xhtml ? 'XHTML' : ($this->is_html ? 'HTML' : ($this->is_text ? 'TEXT' : $attrs['type'])); 
     217                $this->ns_decls = array(); 
     218        } 
    213219 
    214             if(in_array('src',array_keys($attrs))) { 
    215                 $this->current->$tag = $attrs; 
    216             } else { 
    217                 array_push($this->in_content, array($tag,$this->depth, $type)); 
    218             } 
    219         } else if($tag == 'link') { 
    220             array_push($this->current->links, $attrs); 
    221         } else if($tag == 'category') { 
    222             array_push($this->current->categories, $attrs); 
    223         } 
     220        function end_element($parser, $name) { 
    224221 
    225         $this->ns_decls = array(); 
    226     } 
     222                $tag = array_pop(split(":", $name)); 
    227223 
    228     function end_element($parser, $name) { 
     224                $ccount = count($this->in_content); 
    229225 
    230         $tag = array_pop(split(":", $name)); 
     226                # if we are *in* content, then let's proceed to serialize it 
     227                if(!empty($this->in_content)) { 
     228                        # if we are ending the original content element 
     229                        # then let's finalize the content 
     230                        if($this->in_content[0][0] == $tag && 
     231                                $this->in_content[0][1] == $this->depth) { 
     232                                $origtype = $this->in_content[0][2]; 
     233                                array_shift($this->in_content); 
     234                                $newcontent = array(); 
     235                                foreach($this->in_content as $c) { 
     236                                        if(count($c) == 3) { 
     237                                                array_push($newcontent, $c[2]); 
     238                                        } else { 
     239                                                if($this->is_xhtml || $this->is_text) 
     240                                                        array_push($newcontent, $this->xml_escape($c)); 
     241                                                else 
     242                                                        array_push($newcontent, $c); 
     243                                        } 
     244                                } 
     245                                if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS)) 
     246                                        $this->current->$tag = array($origtype, join('',$newcontent)); 
     247                                else 
     248                                        $this->current->$tag = join('',$newcontent); 
    231249 
    232         $ccount = count($this->in_content); 
     250                                $this->in_content = array(); 
     251                        } else if($this->in_content[$ccount-1][0] == $tag && 
     252                                $this->in_content[$ccount-1][1] == $this->depth) { 
     253                                $this->in_content[$ccount-1][2] = substr($this->in_content[$ccount-1][2],0,-1) . "/>"; 
     254                        } else { 
     255                                # else, just finalize the current element's content 
     256                                $endtag = $this->ns_to_prefix($name); 
     257                                array_push($this->in_content, array($tag, $this->depth, "</$endtag[1]>")); 
     258                        } 
     259                } 
    233260 
    234         # if we are *in* content, then let's proceed to serialize it 
    235         if(!empty($this->in_content)) { 
    236             # if we are ending the original content element 
    237             # then let's finalize the content 
    238             if($this->in_content[0][0] == $tag && 
    239                 $this->in_content[0][1] == $this->depth) { 
    240                 $origtype = $this->in_content[0][2]; 
    241                 array_shift($this->in_content); 
    242                 $newcontent = array(); 
    243                 foreach($this->in_content as $c) { 
    244                     if(count($c) == 3) { 
    245                         array_push($newcontent, $c[2]); 
    246                     } else { 
    247                         if($this->is_xhtml || $this->is_text) { 
    248                             array_push($newcontent, $this->xml_escape($c)); 
    249                         } else { 
    250                             array_push($newcontent, $c); 
    251                         } 
    252                     } 
    253                 } 
    254                 if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS)) { 
    255                     $this->current->$tag = array($origtype, join('',$newcontent)); 
    256                 } else { 
    257                     $this->current->$tag = join('',$newcontent); 
    258                 } 
    259                 $this->in_content = array(); 
    260             } else if($this->in_content[$ccount-1][0] == $tag && 
    261                 $this->in_content[$ccount-1][1] == $this->depth) { 
    262                 $this->in_content[$ccount-1][2] = substr($this->in_content[$ccount-1][2],0,-1) . "/>"; 
    263             } else { 
    264                 # else, just finalize the current element's content 
    265                 $endtag = $this->ns_to_prefix($name); 
    266                 array_push($this->in_content, array($tag, $this->depth, "</$endtag[1]>")); 
    267             } 
    268         } 
     261                array_shift($this->ns_contexts); 
    269262 
    270         array_shift($this->ns_contexts); 
     263                $this->depth--; 
    271264 
    272         $this->depth--; 
     265                if($name == ($this->NS . ':entry')) { 
     266                        array_push($this->feed->entries, $this->current); 
     267                        $this->current = null; 
     268                } 
    273269 
    274         if($name == ($this->NS . ':entry')) { 
    275             array_push($this->feed->entries, $this->current); 
    276             $this->current = null; 
    277         } 
     270                $this->_p("end_element('$name')"); 
     271        } 
    278272 
    279         $this->_p("end_element('$name')"); 
    280     } 
     273        function start_ns($parser, $prefix, $uri) { 
     274                $this->_p("starting: " . $prefix . ":" . $uri); 
     275                array_push($this->ns_decls, array($prefix,$uri)); 
     276        } 
    281277 
    282     function start_ns($parser, $prefix, $uri) { 
    283         $this->_p("starting: " . $prefix . ":" . $uri); 
    284         array_push($this->ns_decls, array($prefix,$uri)); 
    285     } 
     278        function end_ns($parser, $prefix) { 
     279                $this->_p("ending: #" . $prefix . "#"); 
     280        } 
    286281 
    287     function end_ns($parser, $prefix) { 
    288         $this->_p("ending: #" . $prefix . "#"); 
    289     } 
     282        function cdata($parser, $data) { 
     283                $this->_p("data: #" . str_replace(array("\n"), array("\\n"), trim($data)) . "#"); 
     284                if(!empty($this->in_content)) 
     285                        array_push($this->in_content, $data); 
     286        } 
    290287 
    291     function cdata($parser, $data) { 
    292         $this->_p("data: #" . str_replace(array("\n"), array("\\n"), trim($data)) . "#"); 
    293         if(!empty($this->in_content)) { 
    294             array_push($this->in_content, $data); 
    295         } 
    296     } 
     288        function _default($parser, $data) { 
     289                # when does this gets called? 
     290        } 
    297291 
    298     function _default($parser, $data) { 
    299         # when does this gets called? 
    300     } 
    301292 
     293        function ns_to_prefix($qname, $attr=false) { 
     294                # split 'http://www.w3.org/1999/xhtml:div' into ('http','//www.w3.org/1999/xhtml','div') 
     295                $components = split(":", $qname); 
    302296 
    303     function ns_to_prefix($qname, $attr=false) { 
    304         # split 'http://www.w3.org/1999/xhtml:div' into ('http','//www.w3.org/1999/xhtml','div') 
    305         $components = split(":", $qname); 
     297                # grab the last one (e.g 'div') 
     298                $name = array_pop($components); 
    306299 
    307         # grab the last one (e.g 'div') 
    308         $name = array_pop($components); 
     300                if(!empty($components)) { 
     301                        # re-join back the namespace component 
     302                        $ns = join(":",$components); 
     303                        foreach($this->ns_contexts as $context) { 
     304                                foreach($context as $mapping) { 
     305                                        if($mapping[1] == $ns && strlen($mapping[0]) > 0) 
     306                                                return array($mapping, "$mapping[0]:$name"); 
     307                                } 
     308                        } 
     309                } 
    309310 
    310         if(!empty($components)) { 
    311             # re-join back the namespace component 
    312             $ns = join(":",$components); 
    313             foreach($this->ns_contexts as $context) { 
    314                 foreach($context as $mapping) { 
    315                     if($mapping[1] == $ns && strlen($mapping[0]) > 0) { 
    316                         return array($mapping, "$mapping[0]:$name"); 
    317                     } 
    318                 } 
    319             } 
    320         } 
     311                if($attr) { 
     312                        return array(null, $name); 
     313                } else { 
     314                        foreach($this->ns_contexts as $context) { 
     315                                foreach($context as $mapping) { 
     316                                        if(strlen($mapping[0]) == 0) 
     317                                                return array($mapping, $name); 
     318                                } 
     319                        } 
     320                } 
     321        } 
    321322 
    322         if($attr) { 
    323             return array(null, $name); 
    324         } else { 
    325             foreach($this->ns_contexts as $context) { 
    326                 foreach($context as $mapping) { 
    327                     if(strlen($mapping[0]) == 0) { 
    328                         return array($mapping, $name); 
    329                     } 
    330                 } 
    331             } 
    332         } 
    333     } 
     323        function is_declared_content_ns($new_mapping) { 
     324                foreach($this->content_ns_contexts as $context) { 
     325                        foreach($context as $mapping) { 
     326                                if($new_mapping == $mapping) 
     327                                        return true; 
     328                        } 
     329                } 
     330                return false; 
     331        } 
    334332 
    335     function is_declared_content_ns($new_mapping) { 
    336         foreach($this->content_ns_contexts as $context) { 
    337             foreach($context as $mapping) { 
    338                 if($new_mapping == $mapping) { 
    339                     return true; 
    340                 } 
    341             } 
    342         } 
    343         return false; 
    344     } 
    345  
    346     function xml_escape($string) 
    347     { 
    348              return str_replace(array('&','"',"'",'<','>'), 
    349                 array('&amp;','&quot;','&apos;','&lt;','&gt;'), 
    350                 $string ); 
    351     } 
     333        function xml_escape($string) 
     334        { 
     335                         return str_replace(array('&','"',"'",'<','>'), 
     336                                array('&amp;','&quot;','&apos;','&lt;','&gt;'), 
     337                                $string ); 
     338        } 
    352339} 
    353340 
    354341?>