Ticket #4191: wp-app.patch

File wp-app.patch, 27.3 kB (added by eliast, 1 year ago)
  • wp-app.php

    old new  
    1111 
    1212require_once('wp-config.php'); 
    1313require_once('wp-includes/post-template.php'); 
     14require_once('wp-includes/atomlib.php'); 
    1415 
    1516// Attempt to automatically detect whether to use querystring 
    1617// or PATH_INFO, based on our environment: 
     
    1819 
    1920// If using querystring, we need to put the path together manually: 
    2021if ($use_querystring) { 
    21         $GLOBALS['use_querystring'] = $use_querystring; 
     22        GLOBALS['use_querystring'] = $use_querystring; 
    2223        $action = $_GET['action']; 
    2324        $eid = (int) $_GET['eid']; 
    2425 
     
    2829                $_SERVER['PATH_INFO'] .= "/$eid"; 
    2930        } 
    3031} else { 
    31         $_SERVER['PATH_INFO'] = str_replace( '/wp-app.php', '', $_SERVER['REQUEST_URI'] ); 
     32        $_SERVER['PATH_INFO'] = str_replace( '.*/wp-app.php', '', $_SERVER['REQUEST_URI'] ); 
    3233} 
    3334 
    3435$app_logging = 0; 
     
    3637function log_app($label,$msg) { 
    3738        global $app_logging; 
    3839        if ($app_logging) { 
    39                 $fp = fopen( 'app.log', 'a+'); 
     40                $fp = fopen( 'wp-app.log', 'a+'); 
    4041                $date = gmdate( 'Y-m-d H:i:s' ); 
    4142                fwrite($fp, "\n\n$date - $label\n$msg\n"); 
    4243                fclose($fp); 
     
    5758endif; 
    5859 
    5960function wa_posts_where_include_drafts_filter($where) { 
    60        $where = ereg_replace("post_author = ([0-9]+) AND post_status != 'draft'","post_author = \\1 AND post_status = 'draft'", $where); 
    61        return $where; 
     61    $where = ereg_replace("post_status = 'publish'","post_status = 'publish' OR post_status = 'future' OR post_status = 'draft'", $where); 
     62    return $where; 
    6263} 
    6364add_filter('posts_where', 'wa_posts_where_include_drafts_filter'); 
    6465 
    65 class AtomEntry { 
    66         var $links = array(); 
    67         var $categories = array(); 
    68 } 
    69  
    70 class AtomParser { 
    71  
    72         var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights'); 
    73         var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft'); 
    74  
    75         var $depth = 0; 
    76         var $indent = 2; 
    77         var $in_content; 
    78         var $ns_contexts = array(); 
    79         var $ns_decls = array(); 
    80         var $is_xhtml = false; 
    81         var $skipped_div = false; 
    82  
    83         var $entry; 
    84  
    85         function AtomParser() { 
    86  
    87                 $this->entry = new AtomEntry(); 
    88                 $this->map_attrs_func = create_function('$k,$v', 'return "$k=\"$v\"";'); 
    89                 $this->map_xmlns_func = create_function('$p,$n', '$xd = "xmlns"; if(strlen($n[0])>0) $xd .= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";'); 
    90         } 
    91  
    92         function parse() { 
    93  
    94                 global $app_logging; 
    95                 array_unshift($this->ns_contexts, array()); 
    96  
    97                 $parser = xml_parser_create_ns(); 
    98                 xml_set_object($parser, $this); 
    99                 xml_set_element_handler($parser, "start_element", "end_element"); 
    100                 xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); 
    101                 xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0); 
    102                 xml_set_character_data_handler($parser, "cdata"); 
    103                 xml_set_default_handler($parser, "_default"); 
    104                 xml_set_start_namespace_decl_handler($parser, "start_ns"); 
    105                 xml_set_end_namespace_decl_handler($parser, "end_ns"); 
    106  
    107                 $contents = ""; 
    108  
    109                 $fp = fopen("php://input", "r"); 
    110                 while(!feof($fp)) { 
    111                         $line = fgets($fp, 4096); 
    112                   
    113                         if($app_logging) $contents .= $line; 
    114  
    115                         if(!xml_parse($parser, $line)) { 
    116                                 log_app("xml_parse_error", "line: $line"); 
    117                                 $this->error = sprintf(__('XML error: %s at line %d')."\n", 
    118                                         xml_error_string(xml_get_error_code($xml_parser)), 
    119                                         xml_get_current_line_number($xml_parser)); 
    120                                 log_app("xml_parse_error", $this->error); 
    121                                 return false; 
    122                         } 
    123                 } 
    124                 fclose($fp); 
    125  
    126                 xml_parser_free($parser); 
    127  
    128                 log_app("AtomParser->parse()",trim($contents)); 
    129  
    130                 return true; 
    131         } 
    132  
    133         function start_element($parser, $name, $attrs) { 
    134  
    135                 $tag = array_pop(split(":", $name)); 
    136  
    137                 array_unshift($this->ns_contexts, $this->ns_decls); 
    138  
    139                 $this->depth++; 
    140  
    141                 #print str_repeat(" ", $this->depth * $this->indent) . "start_element('$name')" ."\n"; 
    142                 #print str_repeat(" ", $this->depth+1 * $this->indent) . print_r($this->ns_contexts,true) ."\n"; 
    143  
    144                 if(!empty($this->in_content)) { 
    145                         $attrs_prefix = array(); 
    146  
    147                         // resolve prefixes for attributes 
    148                         foreach($attrs as $key => $value) { 
    149                                 $attrs_prefix[$this->ns_to_prefix($key)] = $this->xml_escape($value); 
    150                         } 
    151                         $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix))); 
    152                         if(strlen($attrs_str) > 0) { 
    153                                 $attrs_str = " " . $attrs_str; 
    154                         } 
    155  
    156                         $xmlns_str = join(' ', array_map($this->map_xmlns_func, array_keys($this->ns_contexts[0]), array_values($this->ns_contexts[0]))); 
    157                         if(strlen($xmlns_str) > 0) { 
    158                                 $xmlns_str = " " . $xmlns_str; 
    159                         } 
    160  
    161                         // handle self-closing tags (case: a new child found right-away, no text node) 
    162                         if(count($this->in_content) == 2) { 
    163                                 array_push($this->in_content, ">"); 
    164                         } 
    165                   
    166                         array_push($this->in_content, "<". $this->ns_to_prefix($name) ."{$xmlns_str}{$attrs_str}"); 
    167                 } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) { 
    168                         $this->in_content = array(); 
    169                         $this->is_xhtml = $attrs['type'] == 'xhtml';  
    170                         array_push($this->in_content, array($tag,$this->depth)); 
    171                 } else if($tag == 'link') { 
    172                         array_push($this->entry->links, $attrs); 
    173                 } else if($tag == 'category') { 
    174                         array_push($this->entry->categories, $attrs); 
    175                 } 
    176  
    177                 $this->ns_decls = array(); 
    178         } 
    179  
    180         function end_element($parser, $name) { 
    181  
    182                 $tag = array_pop(split(":", $name)); 
    183  
    184                 if(!empty($this->in_content)) { 
    185                         if($this->in_content[0][0] == $tag &&  
    186                         $this->in_content[0][1] == $this->depth) { 
    187                                 array_shift($this->in_content); 
    188                                 if($this->is_xhtml) { 
    189                                         $this->in_content = array_slice($this->in_content, 2, count($this->in_content)-3); 
    190                                 } 
    191                                 $this->entry->$tag = join('',$this->in_content); 
    192                                 $this->in_content = array(); 
    193                         } else { 
    194                                 $endtag = $this->ns_to_prefix($name); 
    195                                 if (strpos($this->in_content[count($this->in_content)-1], '<' . $endtag) !== false) { 
    196                                         array_push($this->in_content, "/>"); 
    197                                 } else { 
    198                                         array_push($this->in_content, "</$endtag>"); 
    199                                 } 
    200                         } 
    201                 } 
    202  
    203                 array_shift($this->ns_contexts); 
    204  
    205                 #print str_repeat(" ", $this->depth * $this->indent) . "end_element('$name')" ."\n"; 
    206  
    207                 $this->depth--; 
    208         } 
    209  
    210         function start_ns($parser, $prefix, $uri) { 
    211                 #print str_repeat(" ", $this->depth * $this->indent) . "starting: " . $prefix . ":" . $uri . "\n"; 
    212                 array_push($this->ns_decls, array($prefix,$uri)); 
    213         } 
    214  
    215         function end_ns($parser, $prefix) { 
    216                 #print str_repeat(" ", $this->depth * $this->indent) . "ending: #" . $prefix . "#\n"; 
    217         } 
    218  
    219         function cdata($parser, $data) { 
    220                 #print str_repeat(" ", $this->depth * $this->indent) . "data: #" . $data . "#\n"; 
    221                 if(!empty($this->in_content)) { 
    222                         // handle self-closing tags (case: text node found, need to close element started) 
    223                         if (strpos($this->in_content[count($this->in_content)-1], '<') !== false) { 
    224                                 array_push($this->in_content, ">"); 
    225                         } 
    226                         array_push($this->in_content, $this->xml_escape($data)); 
    227                 } 
    228         } 
    229  
    230         function _default($parser, $data) { 
    231                 # when does this gets called? 
    232         } 
    233  
    234  
    235         function ns_to_prefix($qname) { 
    236                 $components = split(":", $qname); 
    237                 $name = array_pop($components); 
    238  
    239                 if(!empty($components)) { 
    240                         $ns = join(":",$components); 
    241                         foreach($this->ns_contexts as $context) { 
    242                                 foreach($context as $mapping) { 
    243                                         if($mapping[1] == $ns && strlen($mapping[0]) > 0) { 
    244                                                 return "$mapping[0]:$name"; 
    245                                         } 
    246                                 } 
    247                         } 
    248                 }  
    249                 return $name; 
    250         } 
    251  
    252         function xml_escape($string) 
    253         { 
    254                          return str_replace(array('&','"',"'",'<','>'),  
    255                                 array('&amp;','&quot;','&apos;','&lt;','&gt;'),  
    256                                 $string ); 
    257         } 
    258 } 
    259  
    26066class AtomServer { 
    26167 
    26268        var $ATOM_CONTENT_TYPE = 'application/atom+xml'; 
    26369        var $CATEGORIES_CONTENT_TYPE = 'application/atomcat+xml'; 
    264         var $INTROSPECTION_CONTENT_TYPE = 'application/atomserv+xml'; 
     70        var $INTROSPECTION_CONTENT_TYPE = 'application/atomsvc+xml'; 
    26571 
    26672        var $ENTRIES_PATH = "posts"; 
    26773        var $CATEGORIES_PATH = "categories"; 
    26874        var $MEDIA_PATH = "attachments"; 
    26975        var $ENTRY_PATH = "post"; 
     76        var $SERVICE_PATH = "service"; 
    27077        var $MEDIA_SINGLE_PATH = "attachment"; 
    27178 
    27279        var $params = array(); 
     
    28491                $this->script_name = array_pop(explode('/',$_SERVER['SCRIPT_NAME'])); 
    28592 
    28693                $this->selectors = array( 
    287                         '@/service@' =>  
     94                        '@/service$@' =>  
    28895                                array('GET' => 'get_service'), 
    289                         '@/categories@' => 
     96                        '@/categories$@' => 
    29097                                array('GET' => 'get_categories_xml'), 
    291                         '@/post/(\d+)@' =>  
     98                        '@/post/(\d+)$@' =>  
    29299                                array('GET' => 'get_post',  
    293100                                                'PUT' => 'put_post',  
    294101                                                'DELETE' => 'delete_post'), 
    295                         '@/posts/?([^/]+)?@' =>  
     102                        '@/posts/?(\d+)?$@' =>  
    296103                                array('GET' => 'get_posts',  
    297104                                                'POST' => 'create_post'), 
    298                         '@/attachments/?(\d+)?@' =>  
     105                        '@/attachments/?(\d+)?$@' =>  
    299106                                array('GET' => 'get_attachment',  
    300107                                                'POST' => 'create_attachment'), 
    301                         '@/attachment/file/(\d+)@' =>  
     108                        '@/attachment/file/(\d+)$@' =>  
    302109                                array('GET' => 'get_file',  
    303110                                                'PUT' => 'put_file',  
    304111                                                'DELETE' => 'delete_file'), 
    305                         '@/attachment/(\d+)@' =>  
     112                        '@/attachment/(\d+)$@' =>  
    306113                                array('GET' => 'get_attachment',  
    307114                                                'PUT' => 'put_attachment',  
    308115                                                'DELETE' => 'delete_attachment'), 
     
    324131                        $method = 'GET'; 
    325132                } 
    326133 
    327                 // lame.  
     134                // redirect to /service in case no path is found.  
    328135                if(strlen($path) == 0 || $path == '/') { 
    329                         $path = '/service'
     136                               $this->redirect($this->get_service_url())
    330137                } 
    331  
    332                 // authenticate regardless of the operation and set the current 
    333                 // user. each handler will decide if auth is required or not. 
    334                 $this->authenticate(); 
    335  
     138         
    336139                // dispatch 
    337140                foreach($this->selectors as $regex => $funcs) { 
    338141                        if(preg_match($regex, $path, $matches)) { 
    339                                 if(isset($funcs[$method])) { 
    340                                         array_shift($matches); 
    341                                         call_user_func_array(array(&$this,$funcs[$method]), $matches); 
    342                                         exit(); 
    343                                 } else { 
    344                                         // only allow what we have handlers for... 
    345                                         $this->not_allowed(array_keys($funcs)); 
    346                                 } 
     142                        if(isset($funcs[$method])) { 
     143 
     144                                                // authenticate regardless of the operation and set the current 
     145                                                // user. each handler will decide if auth is required or not. 
     146                                                $this->authenticate();                 
     147                                                $u = wp_get_current_user(); 
     148                                                if(!isset($u) || $u->ID == 0) { 
     149                                                $this->auth_required('Credentials required.'); 
     150                                                } 
     151 
     152                                                array_shift($matches); 
     153                                                call_user_func_array(array(&$this,$funcs[$method]), $matches); 
     154                                                exit(); 
     155                        } else { 
     156                                                // only allow what we have handlers for... 
     157                                                $this->not_allowed(array_keys($funcs)); 
    347158                        } 
     159                        } 
    348160                } 
    349161 
    350162                // oops, nothing found 
     
    353165 
    354166        function get_service() { 
    355167                log_app('function','get_service()'); 
    356                 $entries_url = $this->get_entries_url(); 
    357                 $categories_url = $this->get_categories_url();  
    358                 $media_url = $this->get_attachments_url(); 
    359                 $accepted_content_types = join(',',$this->media_content_types); 
     168                $entries_url = attribute_escape($this->get_entries_url()); 
     169                $categories_url = attribute_escape($this->get_categories_url());  
     170                $media_url = attribute_escape($this->get_attachments_url()); 
     171                $accepted_content_types = attribute_escape(join(',',$this->media_content_types)); 
    360172                $introspection = <<<EOD 
    361173<service xmlns="http://purl.org/atom/app#" xmlns:atom="http://www.w3.org/2005/Atom">  
    362         <workspace title="WordPress Workspace">  
    363             <collection href="$entries_url" title="Posts">  
    364                 <atom:title>WordPress Posts</atom:title>  
    365                 <accept>entry</accept>  
    366                 <categories href="$categories_url" />  
    367             </collection>  
    368             <collection href="$media_url" title="Media">  
    369                 <atom:title>WordPress Media</atom:title>  
    370                 <accept>$accepted_content_types</accept>  
    371             </collection>  
    372         </workspace>  
     174  <workspace>  
     175    <atom:title>WordPress Workspace</atom:title> 
     176    <collection href="$entries_url">  
     177      <atom:title>WordPress Posts</atom:title>  
     178      <accept>entry</accept>  
     179      <categories href="$categories_url" />  
     180    </collection>  
     181    <collection href="$media_url">  
     182      <atom:title>WordPress Media</atom:title>  
     183      <accept>$accepted_content_types</accept>  
     184    </collection>  
     185  </workspace>  
    373186</service> 
    374187 
    375188EOD; 
     
    377190                $this->output($introspection, $this->INTROSPECTION_CONTENT_TYPE);  
    378191        } 
    379192 
    380 function get_categories_xml() { 
    381         log_app('function','get_categories_xml()'); 
    382         $home = get_bloginfo_rss('home'); 
     193        function get_categories_xml() { 
     194         
     195            log_app('function','get_categories_xml()'); 
     196            $home = attribute_escape(get_bloginfo_rss('home')); 
    383197 
    384         $categories = ""; 
    385         $cats = get_categories("hierarchical=0&hide_empty=0"); 
    386         foreach ((array) $cats as $cat) { 
    387                 $categories .= "    <category term=\"" . attribute_escape($cat->cat_name) .  "\" />\n"; 
    388        
    389         $output = <<<EOD 
     198            $categories = ""; 
     199            $cats = get_categories("hierarchical=0&hide_empty=0"); 
     200            foreach ((array) $cats as $cat) { 
     201                    $categories .= "    <category term=\"" . attribute_escape($cat->cat_name) .  "\" />\n"; 
     202           
     203           $output = <<<EOD 
    390204<app:categories xmlns:app="http://purl.org/atom/app#" 
    391205        xmlns="http://www.w3.org/2005/Atom" 
    392206        fixed="yes" scheme="$home"> 
    393207        $categories 
    394208</app:categories> 
    395209EOD; 
    396         $this->output($output, $this->CATEGORIES_CONTENT_TYPE);  
    397 } 
    398210 
     211            $this->output($output, $this->CATEGORIES_CONTENT_TYPE);  
     212        } 
     213 
    399214        /* 
    400215         * Create Post (No arguments) 
    401216         */ 
     
    408223                        $this->client_error(); 
    409224                } 
    410225 
    411                 $entry = $parser->entry; 
     226                $entry = array_pop($parser->feed->entries); 
     227                 
     228                log_app('Received entry:', print_r($entry,true)); 
     229                 
     230                $catnames = array(); 
     231                foreach($entry->categories as $cat) 
     232                array_push($catnames, $cat["term"]); 
     233                 
     234                $wp_cats = get_categories(array('hide_empty' => false)); 
     235                 
     236                $post_categories = array(); 
     237                 
     238                foreach($wp_cats as $cat) { 
     239                if(in_array($cat->cat_name, $catnames)) 
     240                        array_push($post_categories, $cat->cat_ID); 
     241                } 
    412242 
    413243                $publish = (isset($entry->draft) && trim($entry->draft) == 'yes') ? false : true; 
    414244 
     
    420250                $blog_ID = (int ) $blog_id; 
    421251                $post_status = ($publish) ? 'publish' : 'draft'; 
    422252                $post_author = (int) $user->ID; 
    423                 $post_title = $entry->title; 
    424                 $post_content = $entry->content; 
    425                 $post_excerpt = $entry->summary; 
    426                 $post_date = current_time('mysql'); 
    427                 $post_date_gmt = current_time('mysql', 1); 
     253                $post_title = $entry->title[1]; 
     254                $post_content = $entry->content[1]; 
     255                $post_excerpt = $entry->summary[1]; 
     256                $pubtimes = $this->get_publish_time($entry); 
     257                $post_date = $pubtimes[0];  
     258                $post_date_gmt = $pubtimes[1]; 
     259                 
     260                if ( isset( $_SERVER['HTTP_SLUG'] ) ) 
     261                        $post_name = $_SERVER['HTTP_SLUG']; 
    428262 
    429                 $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt'); 
     263                $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'post_name'); 
    430264 
    431265                log_app('Inserting Post. Data:', print_r($post_data,true)); 
    432266 
     
    436270                        $this->internal_error('Sorry, your entry could not be posted. Something wrong happened.'); 
    437271                } 
    438272 
     273                // getting warning here about unable to set headers 
     274                // because something in the cache is printing to the buffer 
     275                // could we clean up wp_set_post_categories or cache to not print 
     276                // this could affect our ability to send back the right headers 
     277                @wp_set_post_categories($postID, $post_categories); 
     278 
    439279                $output = $this->get_entry($postID); 
    440280 
    441281                log_app('function',"create_post($postID)"); 
     
    463303                        $this->bad_request(); 
    464304                } 
    465305 
    466                 $parsed = $parser->entry
     306                $parsed = array_pop($parser->feed->entries)
    467307 
    468308                // check for not found 
    469309                global $entry; 
     
    478318 
    479319                extract($entry); 
    480320 
    481                 $post_title = $parsed->title; 
    482                 $post_content = $parsed->content; 
    483                 $post_excerpt = $parsed->summary; 
     321                $post_title = $parsed->title[1]; 
     322                $post_content = $parsed->content[1]; 
     323                $post_excerpt = $parsed->summary[1]; 
     324                $pubtimes = $this->get_publish_time($entry); 
     325                $post_date = $pubtimes[0];  
     326                $post_date_gmt = $pubtimes[1];       
    484327 
    485328                // let's not go backwards and make something draft again. 
    486329                if(!$publish && $post_status == 'draft') { 
    487330                        $post_status = ($publish) ? 'publish' : 'draft'; 
     331                } elseif($publish) { 
     332                        $post_status = 'publish'; 
    488333                } 
    489334 
    490                 $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt'); 
     335                $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'post_date', 'post_date_gmt'); 
    491336 
    492337                $result = wp_update_post($postdata); 
    493338 
     
    605450                        $this->bad_request(); 
    606451                } 
    607452 
    608                 $parsed = $parser->entry
     453                $parsed = array_pop($parser->feed->entries)
    609454 
    610455                // check for not found 
    611456                global $entry; 
     
    725570 
    726571        function get_entries_url($page = NULL) { 
    727572                global $use_querystring; 
     573                if($GLOBALS['post_type'] == 'attachment') { 
     574                        $path = $this->MEDIA_PATH; 
     575                } else { 
     576                        $path = $this->ENTRIES_PATH; 
     577                } 
    728578                $url = get_bloginfo('url') . '/' . $this->script_name; 
    729579                if ($use_querystring) { 
    730                         $url .= '?action=/' . $this->ENTRIES_PATH
     580                        $url .= '?action=/' . $path
    731581                        if(isset($page) && is_int($page)) { 
    732582                                $url .= "&amp;eid=$page"; 
    733583                        } 
    734584                } else { 
    735                         $url .= '/' . $this->ENTRIES_PATH
     585                        $url .= '/' . $path
    736586                        if(isset($page) && is_int($page)) { 
    737587                                $url .= "/$page"; 
    738588                        } 
     
    759609        function the_categories_url() { 
    760610                $url = $this->get_categories_url(); 
    761611                echo $url; 
    762    
     612       
    763613 
    764614        function get_attachments_url($page = NULL) { 
    765615                global $use_querystring; 
     
    783633                echo $url; 
    784634        } 
    785635 
     636        function get_service_url() { 
     637                global $use_querystring; 
     638                $url = get_bloginfo('url') . '/' . $this->script_name; 
     639                if ($use_querystring) { 
     640                        $url .= '?action=/' . $this->SERVICE_PATH; 
     641                } else { 
     642                        $url .= '/' . $this->SERVICE_PATH; 
     643                } 
     644                return $url; 
     645        } 
    786646 
    787647        function get_entry_url($postID = NULL) { 
    788648                global $use_querystring; 
     
    845705                return; 
    846706        } 
    847707 
    848         function get_posts_count() { 
    849                 global $wpdb; 
    850                 log_app('function',"get_posts_count()"); 
    851                 return $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_date_gmt < '" . gmdate("Y-m-d H:i:s",time()) . "'"); 
    852         } 
    853  
    854  
    855708        function get_posts($page = 1, $post_type = 'post') { 
    856709                        log_app('function',"get_posts($page, '$post_type')"); 
    857710                        $feed = $this->get_feed($page, $post_type); 
     
    859712        } 
    860713 
    861714        function get_attachments($page = 1, $post_type = 'attachment') { 
    862                         log_app('function',"get_attachments($page, '$post_type')"); 
    863                         $feed = $this->get_feed($page, $post_type); 
    864                         $this->output($feed); 
     715            log_app('function',"get_attachments($page, '$post_type')"); 
     716            $GLOBALS['post_type'] = $post_type; 
     717            $feed = $this->get_feed($page, $post_type); 
     718            $this->output($feed); 
    865719        } 
    866720 
    867721        function get_feed($page = 1, $post_type = 'post') { 
     
    875729                $page = (int) $page; 
    876730 
    877731                $count = get_option('posts_per_rss'); 
    878                 $query = "paged=$page&posts_per_page=$count&order=DESC"; 
    879                 if($post_type == 'attachment') { 
    880                         $query .= "&post_type=$post_type"; 
    881                 } 
    882                 query_posts($query); 
     732 
     733                wp('what_to_show=posts&posts_per_page=' . $count . '&offset=' . ($page-1)); 
     734 
    883735                $post = $GLOBALS['post']; 
    884736                $posts = $GLOBALS['posts']; 
    885737                $wp = $GLOBALS['wp']; 
     
    887739                $wpdb = $GLOBALS['wpdb']; 
    888740                $blog_id = (int) $GLOBALS['blog_id']; 
    889741                $post_cache = $GLOBALS['post_cache']; 
     742                log_app('function',"query_posts(# " . print_r($wp_query, true) . "#)"); 
    890743 
    891  
    892                 $total_count = $this->get_posts_count(); 
    893                 $last_page = (int) ceil($total_count / $count); 
     744                log_app('function',"total_count(# $wp_query->max_num_pages #)"); 
     745                $last_page = $wp_query->max_num_pages; 
    894746                $next_page = (($page + 1) > $last_page) ? NULL : $page + 1; 
    895747                $prev_page = ($page - 1) < 1 ? NULL : $page - 1;  
    896748                $last_page = ((int)$last_page == 1 || (int)$last_page == 0) ? NULL : (int) $last_page; 
     
    914766$post = $GLOBALS['post']; 
    915767?> 
    916768<entry> 
    917                 <id><?php the_guid($post->ID); ?></id> 
    918                 <title type="html"><![CDATA[<?php the_title() ?>]]></title> 
    919                 <updated><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></updated> 
    920                 <published><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></published> 
    921                 <app:control> 
    922                         <app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft> 
    923                 </app:control> 
    924                 <author> 
    925                         <name><?php the_author()?></name> 
    926                         <email><?php the_author_email()?></email> 
    927         <?php if (get_the_author_url() && get_the_author_url() != 'http://') { ?> 
    928                  <uri><?php the_author_url()?></uri> 
    929         <?php } ?> 
    930                 </author> 
    931         <?php if($GLOBALS['post']->post_status == 'attachment') { ?> 
    932                 <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
    933                 <link rel="edit-media" href="<?php $this->the_media_url() ?>" /> 
    934         <?php } else { ?> 
    935                 <link href="<?php permalink_single_rss() ?>" /> 
    936                 <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
    937         <?php } ?> 
    938         <?php foreach(get_the_category() as $category) { ?> 
    939          <category scheme="<?php bloginfo_rss('home') ?>" term="<?php echo $category->cat_name?>" /> 
    940         <?php } ?>   <summary type="html"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary> 
    941         <?php if ( strlen( $GLOBALS['post']->post_content ) ) : ?> 
    942         <content type="html"><![CDATA[<?php echo get_the_content('', 0, '') ?>]]></content> 
     769        <id><?php the_guid($post->ID); ?></id> 
     770        <title type="text"><![CDATA[<?php the_title() ?>]]></title> 
     771        <updated><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></updated> 
     772        <published><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></published> 
     773            <app:edited><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></app:edited> 
     774        <app:control> 
     775            <app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft> 
     776        </app:control> 
     777        <author> 
     778            <name><?php the_author()?></name> 
     779            <email><?php the_author_email()?></email> 
     780    <?php if (get_the_author_url() && get_the_author_url() != 'http://') { ?> 
     781         <uri><?php the_author_url()?></uri> 
     782    <?php } ?> 
     783        </author> 
     784    <?php if($GLOBALS['post']->post_status == 'attachment') { ?> 
     785        <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
     786        <link rel="edit-media" href="<?php $this->the_media_url() ?>" /> 
     787    <?php } else { ?> 
     788        <link href="<?php permalink_single_rss() ?>" /> 
     789        <?php   if (current_user_can('edit_post', $post->ID)) { ?> 
     790        <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
     791        <?php   }?>  
     792    <?php } ?> 
     793    <?php foreach(get_the_category() as $category) { ?> 
     794     <category scheme="<?php bloginfo_rss('home') ?>" term="<?php echo $category->cat_name?>" /> 
     795    <?php } ?>   <summary type="html"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary> 
     796    <?php if ( strlen( $GLOBALS['post']->post_content ) ) : ?> 
     797    <content type="html"><![CDATA[<?php echo get_the_content('', 0, '') ?>]]></content> 
    943798<?php endif; ?> 
    944799        </entry> 
    945800<?php 
     
    970825                ?> 
    971826                <?php log_app('$post',print_r($GLOBALS['post'],true)); ?> 
    972827<entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://purl.org/atom/app#" xml:lang="<?php echo get_option('rss_language'); ?>"> 
    973        <id><?php the_guid($post->ID); ?></id> 
    974        <title type="html"><![CDATA[<?php the_title_rss() ?>]]></title> 
     828    <id><?php the_guid($post->ID); ?></id> 
     829    <title type="text"><![CDATA[<?php the_title_rss() ?>]]></title> 
    975830 
    976         <updated><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></updated> 
    977         <published><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></published> 
    978         <app:control> 
    979                 <app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft> 
    980         </app:control> 
    981         <author> 
    982                 <name><?php the_author()?></name> 
    983                 <email><?php the_author_email()?></email> 
    984                 <uri><?php the_author_url()?></uri> 
    985         </author> 
     831    <updated><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></updated> 
     832    <published><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></published> 
     833    <app:edited><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></app:edited> 
     834    <app:control> 
     835        <app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft> 
     836    </app:control> 
     837    <author> 
     838        <name><?php the_author()?></name> 
     839        <email><?php the_author_email()?></email> 
     840        <uri><?php the_author_url()?></uri> 
     841    </author> 
    986842<?php if($GLOBALS['post']->post_type == 'attachment') { ?> 
    987        <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
    988        <link rel="edit-media" href="<?php $this->the_media_url() ?>" /> 
    989        <content type="<?php echo $GLOBALS['post']->post_mime_type ?>" src="<?php the_guid(); ?>"/> 
     843    <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
     844    <link rel="edit-media" href="<?php $this->the_media_url() ?>" /> 
     845    <content type="<?php echo $GLOBALS['post']->post_mime_type ?>" src="<?php the_guid(); ?>"/> 
    990846<?php } else { ?> 
    991        <link href="<?php permalink_single_rss() ?>" /> 
    992        <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
     847    <link href="<?php permalink_single_rss() ?>" /> 
     848    <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
    993849<?php } ?> 
    994850<?php foreach(get_the_category() as $category) { ?> 
    995        <category scheme="<?php bloginfo_rss('home') ?>" term="<?php echo $category->cat_name?>" /> 
    996        <summary type="html"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary> 
     851    <category scheme="<?php bloginfo_rss('home') ?>" term="<?php echo $category->cat_name?>" /> 
     852    <summary type="html"><![CDATA[<?php the_excerpt_rss(); ?>]]></summary> 
    997853<?php } 
    998        if ( strlen( $GLOBALS['post']->post_content ) ) : ?> 
    999        <content type="html"><![CDATA[<?php echo get_the_content('', 0, '') ?>]]></content> 
     854    if ( strlen( $GLOBALS['post']->post_content ) ) : ?> 
     855    <content type="html"><![CDATA[<?php echo get_the_content('', 0, '') ?>]]></content> 
    1000856<?php endif; ?> 
    1001857</entry> 
    1002858<?php 
     
    1071927                exit; 
    1072928        } 
    1073929 
     930        function redirect($url) { 
     931 
     932                log_app('Status','302: Redirect'); 
     933                $escaped_url = attribute_escape($url); 
     934                $content = <<<EOD 
     935<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
     936<html> 
     937  <head> 
     938    <title>302 Found</title> 
     939  </head> 
     940<body> 
     941  <h1>Found</h1> 
     942  <p>The document has moved <a href="$escaped_url">here</a>.</p> 
     943  </body> 
     944</html> 
     945 
     946EOD; 
     947                header('HTTP/1.1 302 Moved'); 
     948                header('Content-Type: text/html'); 
     949                header('Location: ' . $url); 
     950                echo $content; 
     951                exit; 
     952 
     953        } 
     954 
     955 
    1074956        function client_error($msg = 'Client Error') { 
    1075                 log_app('Status','400: Client Errir'); 
     957                log_app('Status','400: Client Error'); 
    1076958                header('Content-Type: text/plain'); 
    1077959                status_header('400'); 
    1078960                exit; 
     
    1107989                log_app('Status','401: Auth Required'); 
    1108990                nocache_headers(); 
    1109991                header('WWW-Authenticate: Basic realm="WordPress Atom Protocol"'); 
    1110                 header('WWW-Authenticate: Form action="' . get_option('siteurl') . '/wp-login.php"', false);  
    1111992                header("HTTP/1.1 401 $msg"); 
    1112993                header('Status: ' . $msg); 
    1113                 header('Content-Type: plain/text'); 
    1114                 echo $msg; 
     994                header('Content-Type: text/html'); 
     995                $content = <<<EOD 
     996<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
     997<html> 
     998  <head> 
     999    <title>401 Unauthorized</title> 
     1000  </head> 
     1001<body> 
     1002    <h1>401 Unauthorized</h1> 
     1003    <p>$msg</p> 
     1004  </body> 
     1005</html> 
     1006 
     1007EOD; 
     1008                echo $content; 
    11151009                exit; 
    11161010        } 
    11171011 
     
    12511145                } 
    12521146        } 
    12531147 
     1148         
     1149        function rfc3339_str2time($str) { 
     1150             
     1151            $match = false; 
     1152            if(!preg_match("/(\d{4}-\d{2}-\d{2})T(\d{2}\:\d{2}\:\d{2})\.?\d{0,3}(Z|[+-]+\d{2}\:\d{2})/", $str, $match)) 
     1153                        return false; 
     1154         
     1155            if($match[3] == 'Z') 
     1156                        $match[3] == '+0000'; 
     1157         
     1158            return strtotime($match[1] . " " . $match[2] . " " . $match[3]); 
     1159        }         
    12541160 
     1161        function get_publish_time($entry) { 
     1162 
     1163            $pubtime = $this->rfc3339_str2time($entry->published); 
     1164             
     1165            if(!$pubtime) { 
     1166                        return array(current_time('mysql'),current_time('mysql',1)); 
     1167            } else { 
     1168                        return array(date("Y-m-d H:i:s", $pubtime), gmdate("Y-m-d H:i:s", $pubtime)); 
     1169