WordPress.org

Make WordPress Core

Changeset 20062


Ignore:
Timestamp:
03/01/12 21:15:44 (2 years ago)
Author:
ryan
Message:

wp-app.php cleanup:

  • Put the atom server class in class-wp-atom-server.php
  • Remove log_api calls
  • Update the query filter
  • Replace exit calls with wp_die() for unit test compat
  • Add override handler for wp_die()
  • Allow plugins to replace the atom class
  • Whitespace cleanup

Props kurtpayne. fixes #20042

Location:
trunk
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/wp-app.php

    r20000 r20062  
    1919require_once(ABSPATH . WPINC . '/atomlib.php'); 
    2020 
     21/** Atom Server **/ 
     22require_once(ABSPATH . WPINC . '/class-wp-atom-server.php'); 
     23 
    2124/** Admin Image API for metadata updating */ 
    2225require_once(ABSPATH . '/wp-admin/includes/image.php'); 
    2326 
    2427$_SERVER['PATH_INFO'] = preg_replace( '/.*\/wp-app\.php/', '', $_SERVER['REQUEST_URI'] ); 
    25  
    26 /** 
    27  * Whether to always authenticate user. Permanently set to true. 
    28  * 
    29  * @name always_authenticate 
    30  * @var int|bool 
    31  * @todo Should be an option somewhere 
    32  */ 
    33 $always_authenticate = 1; 
    3428 
    3529/** 
     
    4741    _deprecated_function( __FUNCTION__, '3.4', 'error_log()' ); 
    4842    if ( ! empty( $GLOBALS['app_logging'] ) ) 
    49         error_log( $label . ' - ' . $message ); 
     43            error_log( $label . ' - ' . $message ); 
    5044} 
    5145 
    52 /** 
    53  * Filter to add more post statuses. 
    54  * 
    55  * @since 2.2.0 
    56  * 
    57  * @param string $where SQL statement to filter. 
    58  * @return string Filtered SQL statement with added post_status for where clause. 
    59  */ 
    60 function wa_posts_where_include_drafts_filter($where) { 
    61     $where = str_replace("post_status = 'publish'","post_status = 'publish' OR post_status = 'future' OR post_status = 'draft' OR post_status = 'inherit'", $where); 
    62     return $where; 
     46// Allow for a plugin to insert a different class to handle requests. 
     47$wp_atom_server_class = apply_filters('wp_atom_server_class', 'wp_atom_server'); 
     48$wp_atom_server = new $wp_atom_server_class; 
    6349 
    64 } 
    65 add_filter('posts_where', 'wa_posts_where_include_drafts_filter'); 
    66  
    67 /** 
    68  * WordPress AtomPub API implementation. 
    69  * 
    70  * @package WordPress 
    71  * @subpackage Publishing 
    72  * @since 2.2.0 
    73  */ 
    74 class AtomServer { 
    75  
    76     /** 
    77      * ATOM content type. 
    78      * 
    79      * @since 2.2.0 
    80      * @var string 
    81      */ 
    82     var $ATOM_CONTENT_TYPE = 'application/atom+xml'; 
    83  
    84     /** 
    85      * Categories ATOM content type. 
    86      * 
    87      * @since 2.2.0 
    88      * @var string 
    89      */ 
    90     var $CATEGORIES_CONTENT_TYPE = 'application/atomcat+xml'; 
    91  
    92     /** 
    93      * Service ATOM content type. 
    94      * 
    95      * @since 2.3.0 
    96      * @var string 
    97      */ 
    98     var $SERVICE_CONTENT_TYPE = 'application/atomsvc+xml'; 
    99  
    100     /** 
    101      * ATOM XML namespace. 
    102      * 
    103      * @since 2.3.0 
    104      * @var string 
    105      */ 
    106     var $ATOM_NS = 'http://www.w3.org/2005/Atom'; 
    107  
    108     /** 
    109      * ATOMPUB XML namespace. 
    110      * 
    111      * @since 2.3.0 
    112      * @var string 
    113      */ 
    114     var $ATOMPUB_NS = 'http://www.w3.org/2007/app'; 
    115  
    116     /** 
    117      * Entries path. 
    118      * 
    119      * @since 2.2.0 
    120      * @var string 
    121      */ 
    122     var $ENTRIES_PATH = "posts"; 
    123  
    124     /** 
    125      * Categories path. 
    126      * 
    127      * @since 2.2.0 
    128      * @var string 
    129      */ 
    130     var $CATEGORIES_PATH = "categories"; 
    131  
    132     /** 
    133      * Media path. 
    134      * 
    135      * @since 2.2.0 
    136      * @var string 
    137      */ 
    138     var $MEDIA_PATH = "attachments"; 
    139  
    140     /** 
    141      * Entry path. 
    142      * 
    143      * @since 2.2.0 
    144      * @var string 
    145      */ 
    146     var $ENTRY_PATH = "post"; 
    147  
    148     /** 
    149      * Service path. 
    150      * 
    151      * @since 2.2.0 
    152      * @var string 
    153      */ 
    154     var $SERVICE_PATH = "service"; 
    155  
    156     /** 
    157      * Media single path. 
    158      * 
    159      * @since 2.2.0 
    160      * @var string 
    161      */ 
    162     var $MEDIA_SINGLE_PATH = "attachment"; 
    163  
    164     /** 
    165      * ATOMPUB parameters. 
    166      * 
    167      * @since 2.2.0 
    168      * @var array 
    169      */ 
    170     var $params = array(); 
    171  
    172     /** 
    173      * Supported ATOMPUB media types. 
    174      * 
    175      * @since 2.3.0 
    176      * @var array 
    177      */ 
    178     var $media_content_types = array('image/*','audio/*','video/*'); 
    179  
    180     /** 
    181      * ATOMPUB content type(s). 
    182      * 
    183      * @since 2.2.0 
    184      * @var array 
    185      */ 
    186     var $atom_content_types = array('application/atom+xml'); 
    187  
    188     /** 
    189      * ATOMPUB methods. 
    190      * 
    191      * @since 2.2.0 
    192      * @var unknown_type 
    193      */ 
    194     var $selectors = array(); 
    195  
    196     /** 
    197      * Whether to do output. 
    198      * 
    199      * Support for head. 
    200      * 
    201      * @since 2.2.0 
    202      * @var bool 
    203      */ 
    204     var $do_output = true; 
    205  
    206     /** 
    207      * Constructor - Sets up object properties. 
    208      * 
    209      * @since 2.2.0 
    210      * @return AtomServer 
    211      */ 
    212     function __construct() { 
    213  
    214         $var_by_ref = explode( '/', $_SERVER['SCRIPT_NAME'] ); 
    215         $this->script_name = array_pop( $var_by_ref ); 
    216         $this->app_base = site_url( $this->script_name . '/' ); 
    217  
    218         $this->selectors = array( 
    219             '@/service$@' => 
    220                 array('GET' => 'get_service'), 
    221             '@/categories$@' => 
    222                 array('GET' => 'get_categories_xml'), 
    223             '@/post/(\d+)$@' => 
    224                 array('GET' => 'get_post', 
    225                         'PUT' => 'put_post', 
    226                         'DELETE' => 'delete_post'), 
    227             '@/posts/?(\d+)?$@' => 
    228                 array('GET' => 'get_posts', 
    229                         'POST' => 'create_post'), 
    230             '@/attachments/?(\d+)?$@' => 
    231                 array('GET' => 'get_attachment', 
    232                         'POST' => 'create_attachment'), 
    233             '@/attachment/file/(\d+)$@' => 
    234                 array('GET' => 'get_file', 
    235                         'PUT' => 'put_file', 
    236                         'DELETE' => 'delete_file'), 
    237             '@/attachment/(\d+)$@' => 
    238                 array('GET' => 'get_attachment', 
    239                         'PUT' => 'put_attachment', 
    240                         'DELETE' => 'delete_attachment'), 
    241         ); 
    242     } 
    243  
    244     /** 
    245      * Handle ATOMPUB request. 
    246      * 
    247      * @since 2.2.0 
    248      */ 
    249     function handle_request() { 
    250         global $always_authenticate; 
    251  
    252         if ( !empty( $_SERVER['ORIG_PATH_INFO'] ) ) 
    253             $path = $_SERVER['ORIG_PATH_INFO']; 
    254         else 
    255             $path = $_SERVER['PATH_INFO']; 
    256  
    257         $method = $_SERVER['REQUEST_METHOD']; 
    258  
    259         $this->process_conditionals(); 
    260         //$this->process_conditionals(); 
    261  
    262         // exception case for HEAD (treat exactly as GET, but don't output) 
    263         if ($method == 'HEAD') { 
    264             $this->do_output = false; 
    265             $method = 'GET'; 
    266         } 
    267  
    268         // redirect to /service in case no path is found. 
    269         if (strlen($path) == 0 || $path == '/') 
    270             $this->redirect($this->get_service_url()); 
    271  
    272         // check to see if AtomPub is enabled 
    273         if ( !get_option( 'enable_app' ) ) 
    274             $this->forbidden( sprintf( __( 'AtomPub services are disabled on this site. An admin user can enable them at %s' ), admin_url('options-writing.php') ) ); 
    275  
    276         // dispatch 
    277         foreach ( $this->selectors as $regex => $funcs ) { 
    278             if ( preg_match($regex, $path, $matches) ) { 
    279                 if ( isset($funcs[$method]) ) { 
    280  
    281                     // authenticate regardless of the operation and set the current 
    282                     // user. each handler will decide if auth is required or not. 
    283                     if ( !$this->authenticate() ) { 
    284                         if ( $always_authenticate ) 
    285                             $this->auth_required('Credentials required.'); 
    286                     } 
    287  
    288                     array_shift($matches); 
    289                     call_user_func_array(array(&$this,$funcs[$method]), $matches); 
    290                     exit(); 
    291                 } else { 
    292                     // only allow what we have handlers for... 
    293                     $this->not_allowed(array_keys($funcs)); 
    294                 } 
    295             } 
    296         } 
    297  
    298         // oops, nothing found 
    299         $this->not_found(); 
    300     } 
    301  
    302     /** 
    303      * Retrieve XML for ATOMPUB service. 
    304      * 
    305      * @since 2.2.0 
    306      */ 
    307     function get_service() { 
    308         if ( !current_user_can( 'edit_posts' ) ) 
    309             $this->auth_required( __( 'Sorry, you do not have the right to access this site.' ) ); 
    310  
    311         $entries_url = esc_attr($this->get_entries_url()); 
    312         $categories_url = esc_attr($this->get_categories_url()); 
    313         $media_url = esc_attr($this->get_attachments_url()); 
    314         $accepted_media_types = ''; 
    315         foreach ($this->media_content_types as $med) { 
    316             $accepted_media_types = $accepted_media_types . "<accept>" . $med . "</accept>"; 
    317         } 
    318         $atom_prefix="atom"; 
    319         $atom_blogname = get_bloginfo('name'); 
    320         $service_doc = <<<EOD 
    321 <service xmlns="$this->ATOMPUB_NS" xmlns:$atom_prefix="$this->ATOM_NS"> 
    322   <workspace> 
    323     <$atom_prefix:title>$atom_blogname Workspace</$atom_prefix:title> 
    324     <collection href="$entries_url"> 
    325       <$atom_prefix:title>$atom_blogname Posts</$atom_prefix:title> 
    326       <accept>$this->ATOM_CONTENT_TYPE;type=entry</accept> 
    327       <categories href="$categories_url" /> 
    328     </collection> 
    329     <collection href="$media_url"> 
    330       <$atom_prefix:title>$atom_blogname Media</$atom_prefix:title> 
    331       $accepted_media_types 
    332     </collection> 
    333   </workspace> 
    334 </service> 
    335  
    336 EOD; 
    337  
    338         $this->output($service_doc, $this->SERVICE_CONTENT_TYPE); 
    339     } 
    340  
    341     /** 
    342      * Retrieve categories list in XML format. 
    343      * 
    344      * @since 2.2.0 
    345      */ 
    346     function get_categories_xml() { 
    347         if ( !current_user_can( 'edit_posts' ) ) 
    348             $this->auth_required( __( 'Sorry, you do not have the right to access this site.' ) ); 
    349  
    350         $home = esc_attr(get_bloginfo_rss('url')); 
    351  
    352         $categories = ""; 
    353         $cats = get_categories(array('hierarchical' => 0, 'hide_empty' => 0)); 
    354         foreach ( (array) $cats as $cat ) { 
    355             $categories .= "    <category term=\"" . esc_attr($cat->name) . "\" />\n"; 
    356         } 
    357         $output = <<<EOD 
    358 <app:categories xmlns:app="$this->ATOMPUB_NS" 
    359     xmlns="$this->ATOM_NS" 
    360     fixed="yes" scheme="$home"> 
    361     $categories 
    362 </app:categories> 
    363 EOD; 
    364         $this->output($output, $this->CATEGORIES_CONTENT_TYPE); 
    365     } 
    366  
    367     /** 
    368      * Create new post. 
    369      * 
    370      * @since 2.2.0 
    371      */ 
    372     function create_post() { 
    373         global $user_ID; 
    374         $this->get_accepted_content_type($this->atom_content_types); 
    375  
    376         $parser = new AtomParser(); 
    377         if ( !$parser->parse() ) 
    378             $this->client_error(); 
    379  
    380         $entry = array_pop($parser->feed->entries); 
    381  
    382         $catnames = array(); 
    383         if ( !empty( $entry->categories ) ) { 
    384             foreach ( $entry->categories as $cat ) { 
    385                 array_push($catnames, $cat["term"]); 
    386             } 
    387         } 
    388  
    389         $wp_cats = get_categories(array('hide_empty' => false)); 
    390  
    391         $post_category = array(); 
    392  
    393         foreach ( $wp_cats as $cat ) { 
    394             if ( in_array($cat->name, $catnames) ) 
    395                 array_push($post_category, $cat->term_id); 
    396         } 
    397  
    398         $publish = ! ( isset( $entry->draft ) && 'yes' == trim( $entry->draft ) ); 
    399  
    400         $cap = ($publish) ? 'publish_posts' : 'edit_posts'; 
    401  
    402         if ( !current_user_can($cap) ) 
    403             $this->auth_required(__('Sorry, you do not have the right to edit/publish new posts.')); 
    404  
    405         $blog_ID = get_current_blog_id(); 
    406         $post_status = ($publish) ? 'publish' : 'draft'; 
    407         $post_author = (int) $user_ID; 
    408  
    409         $post_title   = ''; 
    410         $post_content = ''; 
    411         $post_excerpt = ''; 
    412         $pubtimes     = ''; 
    413  
    414         if ( isset( $entry->title ) && is_array( $entry->title ) && !empty( $entry->title[1] ) ) 
    415             $post_title = (string) $entry->title[1]; 
    416         if ( isset( $entry->content ) && is_array( $entry->content ) && !empty( $entry->content[1] ) ) 
    417             $post_content = (string) $entry->content[1]; 
    418         if ( isset( $entry->summary ) && is_array( $entry->summary ) && !empty( $entry->summary[1] ) ) 
    419             $post_excerpt = (string) $entry->summary[1]; 
    420         if ( !empty( $entry->published ) ) 
    421             $pubtimes = (string) $entry->published; 
    422  
    423         $pubtimes = $this->get_publish_time( $pubtimes ); 
    424  
    425         $post_date = $pubtimes[0]; 
    426         $post_date_gmt = $pubtimes[1]; 
    427  
    428         if ( isset( $_SERVER['HTTP_SLUG'] ) ) 
    429             $post_name = $_SERVER['HTTP_SLUG']; 
    430  
    431         $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'post_name'); 
    432  
    433         $this->escape($post_data); 
    434  
    435         $postID = wp_insert_post($post_data); 
    436         if ( is_wp_error( $postID ) ) 
    437             $this->internal_error($postID->get_error_message()); 
    438  
    439         if ( !$postID ) 
    440             $this->internal_error(__('Sorry, your entry could not be posted. Something wrong happened.')); 
    441  
    442         // getting warning here about unable to set headers 
    443         // because something in the cache is printing to the buffer 
    444         // could we clean up wp_set_post_categories or cache to not print 
    445         // this could affect our ability to send back the right headers 
    446         @wp_set_post_categories($postID, $post_category); 
    447  
    448         do_action( 'atompub_create_post', $postID, $entry ); 
    449  
    450         $output = $this->get_entry($postID); 
    451  
    452         $this->created($postID, $output); 
    453     } 
    454  
    455     /** 
    456      * Retrieve post. 
    457      * 
    458      * @since 2.2.0 
    459      * 
    460      * @param int $postID Post ID. 
    461      */ 
    462     function get_post($postID) { 
    463         global $entry; 
    464  
    465         if ( !current_user_can( 'edit_post', $postID ) ) 
    466             $this->auth_required( __( 'Sorry, you do not have the right to access this post.' ) ); 
    467  
    468         $this->set_current_entry($postID); 
    469         $output = $this->get_entry($postID); 
    470         $this->output($output); 
    471  
    472     } 
    473  
    474     /** 
    475      * Update post. 
    476      * 
    477      * @since 2.2.0 
    478      * 
    479      * @param int $postID Post ID. 
    480      */ 
    481     function put_post($postID) { 
    482         // checked for valid content-types (atom+xml) 
    483         // quick check and exit 
    484         $this->get_accepted_content_type($this->atom_content_types); 
    485  
    486         $parser = new AtomParser(); 
    487         if ( !$parser->parse() ) 
    488             $this->bad_request(); 
    489  
    490         $parsed = array_pop($parser->feed->entries); 
    491  
    492         // check for not found 
    493         global $entry; 
    494         $this->set_current_entry($postID); 
    495  
    496         if ( !current_user_can('edit_post', $entry['ID']) ) 
    497             $this->auth_required(__('Sorry, you do not have the right to edit this post.')); 
    498  
    499         $publish = ! ( isset($parsed->draft) && 'yes' == trim($parsed->draft) ); 
    500         $post_status = ($publish) ? 'publish' : 'draft'; 
    501  
    502         extract($entry); 
    503  
    504         $post_title = $parsed->title[1]; 
    505         $post_content = $parsed->content[1]; 
    506         $post_excerpt = $parsed->summary[1]; 
    507         $pubtimes = $this->get_publish_time($entry->published); 
    508         $post_date = $pubtimes[0]; 
    509         $post_date_gmt = $pubtimes[1]; 
    510         $pubtimes = $this->get_publish_time($parsed->updated); 
    511         $post_modified = $pubtimes[0]; 
    512         $post_modified_gmt = $pubtimes[1]; 
    513  
    514         $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt'); 
    515         $this->escape($postdata); 
    516  
    517         $result = wp_update_post($postdata); 
    518  
    519         if ( !$result ) 
    520             $this->internal_error(__('For some strange yet very annoying reason, this post could not be edited.')); 
    521  
    522         do_action( 'atompub_put_post', $ID, $parsed ); 
    523  
    524         $this->ok(); 
    525     } 
    526  
    527     /** 
    528      * Remove post. 
    529      * 
    530      * @since 2.2.0 
    531      * 
    532      * @param int $postID Post ID. 
    533      */ 
    534     function delete_post($postID) { 
    535  
    536         // check for not found 
    537         global $entry; 
    538         $this->set_current_entry($postID); 
    539  
    540         if ( !current_user_can('edit_post', $postID) ) 
    541             $this->auth_required(__('Sorry, you do not have the right to delete this post.')); 
    542  
    543         if ( $entry['post_type'] == 'attachment' ) { 
    544             $this->delete_attachment($postID); 
    545         } else { 
    546             $result = wp_delete_post($postID); 
    547  
    548             if ( !$result ) { 
    549                 $this->internal_error(__('For some strange yet very annoying reason, this post could not be deleted.')); 
    550             } 
    551  
    552             $this->ok(); 
    553         } 
    554  
    555     } 
    556  
    557     /** 
    558      * Retrieve attachment. 
    559      * 
    560      * @since 2.2.0 
    561      * 
    562      * @param int $postID Optional. Post ID. 
    563      */ 
    564     function get_attachment($postID = null) { 
    565         if ( !current_user_can( 'upload_files' ) ) 
    566             $this->auth_required( __( 'Sorry, you do not have permission to upload files.' ) ); 
    567  
    568         if ( !isset($postID) ) { 
    569             $this->get_attachments(); 
    570         } else { 
    571             $this->set_current_entry($postID); 
    572             $output = $this->get_entry($postID, 'attachment'); 
    573             $this->output($output); 
    574         } 
    575     } 
    576  
    577     /** 
    578      * Create new attachment. 
    579      * 
    580      * @since 2.2.0 
    581      */ 
    582     function create_attachment() { 
    583  
    584         $type = $this->get_accepted_content_type(); 
    585  
    586         if ( !current_user_can('upload_files') ) 
    587             $this->auth_required(__('You do not have permission to upload files.')); 
    588  
    589         $fp = fopen("php://input", "rb"); 
    590         $bits = null; 
    591         while ( !feof($fp) ) { 
    592             $bits .= fread($fp, 4096); 
    593         } 
    594         fclose($fp); 
    595  
    596         $slug = ''; 
    597         if ( isset( $_SERVER['HTTP_SLUG'] ) ) 
    598             $slug = $_SERVER['HTTP_SLUG']; 
    599         elseif ( isset( $_SERVER['HTTP_TITLE'] ) ) 
    600             $slug = $_SERVER['HTTP_TITLE']; 
    601         elseif ( empty( $slug ) ) // just make a random name 
    602             $slug = substr( md5( uniqid( microtime() ) ), 0, 7); 
    603         $ext = preg_replace( '|.*/([a-z0-9]+)|', '$1', $_SERVER['CONTENT_TYPE'] ); 
    604         $slug = sanitize_file_name( "$slug.$ext" ); 
    605         $file = wp_upload_bits( $slug, null, $bits); 
    606  
    607         $url = $file['url']; 
    608         $file = $file['file']; 
    609  
    610         do_action('wp_create_file_in_uploads', $file); // replicate 
    611  
    612         // Construct the attachment array 
    613         $attachment = array( 
    614             'post_title' => $slug, 
    615             'post_content' => $slug, 
    616             'post_status' => 'attachment', 
    617             'post_parent' => 0, 
    618             'post_mime_type' => $type, 
    619             'guid' => $url 
    620             ); 
    621  
    622         // Save the data 
    623         $postID = wp_insert_attachment($attachment, $file); 
    624  
    625         if (!$postID) 
    626             $this->internal_error(__('Sorry, your entry could not be posted. Something wrong happened.')); 
    627  
    628         $output = $this->get_entry($postID, 'attachment'); 
    629  
    630         $this->created($postID, $output, 'attachment'); 
    631     } 
    632  
    633     /** 
    634      * Update attachment. 
    635      * 
    636      * @since 2.2.0 
    637      * 
    638      * @param int $postID Post ID. 
    639      */ 
    640     function put_attachment($postID) { 
    641         // checked for valid content-types (atom+xml) 
    642         // quick check and exit 
    643         $this->get_accepted_content_type($this->atom_content_types); 
    644  
    645         $parser = new AtomParser(); 
    646         if (!$parser->parse()) { 
    647             $this->bad_request(); 
    648         } 
    649  
    650         $parsed = array_pop($parser->feed->entries); 
    651  
    652         // check for not found 
    653         global $entry; 
    654         $this->set_current_entry($postID); 
    655  
    656         if ( !current_user_can('edit_post', $entry['ID']) ) 
    657             $this->auth_required(__('Sorry, you do not have the right to edit this post.')); 
    658  
    659         extract($entry); 
    660  
    661         $post_title = $parsed->title[1]; 
    662         $post_content = $parsed->summary[1]; 
    663         $pubtimes = $this->get_publish_time($parsed->updated); 
    664         $post_modified = $pubtimes[0]; 
    665         $post_modified_gmt = $pubtimes[1]; 
    666  
    667         $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'post_modified', 'post_modified_gmt'); 
    668         $this->escape($postdata); 
    669  
    670         $result = wp_update_post($postdata); 
    671  
    672         if ( !$result ) 
    673             $this->internal_error(__('For some strange yet very annoying reason, this post could not be edited.')); 
    674  
    675         $this->ok(); 
    676     } 
    677  
    678     /** 
    679      * Remove attachment. 
    680      * 
    681      * @since 2.2.0 
    682      * 
    683      * @param int $postID Post ID. 
    684      */ 
    685     function delete_attachment($postID) { 
    686         // check for not found 
    687         global $entry; 
    688         $this->set_current_entry($postID); 
    689  
    690         if ( !current_user_can('edit_post', $postID) ) 
    691             $this->auth_required(__('Sorry, you do not have the right to delete this post.')); 
    692  
    693         $location = get_post_meta($entry['ID'], '_wp_attached_file', true); 
    694         $filetype = wp_check_filetype($location); 
    695  
    696         if ( !isset($location) || 'attachment' != $entry['post_type'] || empty($filetype['ext']) ) 
    697             $this->internal_error(__('Error occurred while accessing post metadata for file location.')); 
    698  
    699         // delete file 
    700         @unlink($location); 
    701  
    702         // delete attachment 
    703         $result = wp_delete_post($postID); 
    704  
    705         if ( !$result ) 
    706             $this->internal_error(__('For some strange yet very annoying reason, this post could not be deleted.')); 
    707  
    708         $this->ok(); 
    709     } 
    710  
    711     /** 
    712      * Retrieve attachment from post. 
    713      * 
    714      * @since 2.2.0 
    715      * 
    716      * @param int $postID Post ID. 
    717      */ 
    718     function get_file($postID) { 
    719  
    720         // check for not found 
    721         global $entry; 
    722         $this->set_current_entry($postID); 
    723  
    724         // then whether user can edit the specific post 
    725         if ( !current_user_can('edit_post', $postID) ) 
    726             $this->auth_required(__('Sorry, you do not have the right to edit this post.')); 
    727  
    728         $location = get_post_meta($entry['ID'], '_wp_attached_file', true); 
    729         $location = get_option ('upload_path') . '/' . $location; 
    730         $filetype = wp_check_filetype($location); 
    731  
    732         if ( !isset($location) || 'attachment' != $entry['post_type'] || empty($filetype['ext']) ) 
    733             $this->internal_error(__('Error occurred while accessing post metadata for file location.')); 
    734  
    735         status_header('200'); 
    736         header('Content-Type: ' . $entry['post_mime_type']); 
    737         header('Connection: close'); 
    738  
    739         if ( $fp = fopen($location, "rb") ) { 
    740             status_header('200'); 
    741             header('Content-Type: ' . $entry['post_mime_type']); 
    742             header('Connection: close'); 
    743  
    744             while ( !feof($fp) ) { 
    745                 echo fread($fp, 4096); 
    746             } 
    747  
    748             fclose($fp); 
    749         } else { 
    750             status_header ('404'); 
    751         } 
    752  
    753         exit; 
    754     } 
    755  
    756     /** 
    757      * Upload file to blog and add attachment to post. 
    758      * 
    759      * @since 2.2.0 
    760      * 
    761      * @param int $postID Post ID. 
    762      */ 
    763     function put_file($postID) { 
    764  
    765         // first check if user can upload 
    766         if ( !current_user_can('upload_files') ) 
    767             $this->auth_required(__('You do not have permission to upload files.')); 
    768  
    769         // check for not found 
    770         global $entry; 
    771         $this->set_current_entry($postID); 
    772  
    773         // then whether user can edit the specific post 
    774         if ( !current_user_can('edit_post', $postID) ) 
    775             $this->auth_required(__('Sorry, you do not have the right to edit this post.')); 
    776  
    777         $upload_dir = wp_upload_dir( ); 
    778         $location = get_post_meta($entry['ID'], '_wp_attached_file', true); 
    779         $filetype = wp_check_filetype($location); 
    780  
    781         $location = "{$upload_dir['basedir']}/{$location}"; 
    782  
    783         if (!isset($location) || 'attachment' != $entry['post_type'] || empty($filetype['ext'])) 
    784             $this->internal_error(__('Error occurred while accessing post metadata for file location.')); 
    785  
    786         $fp = fopen("php://input", "rb"); 
    787         $localfp = fopen($location, "w+"); 
    788         while ( !feof($fp) ) { 
    789             fwrite($localfp,fread($fp, 4096)); 
    790         } 
    791         fclose($fp); 
    792         fclose($localfp); 
    793  
    794         $ID = $entry['ID']; 
    795         $pubtimes = $this->get_publish_time($entry->published); 
    796         $post_date = $pubtimes[0]; 
    797         $post_date_gmt = $pubtimes[1]; 
    798         $pubtimes = $this->get_publish_time($parsed->updated); 
    799         $post_modified = $pubtimes[0]; 
    800         $post_modified_gmt = $pubtimes[1]; 
    801  
    802         $post_data = compact('ID', 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt'); 
    803         $result = wp_update_post($post_data); 
    804  
    805         if ( !$result ) 
    806             $this->internal_error(__('Sorry, your entry could not be posted. Something wrong happened.')); 
    807  
    808         wp_update_attachment_metadata( $postID, wp_generate_attachment_metadata( $postID, $location ) ); 
    809  
    810         $this->ok(); 
    811     } 
    812  
    813     /** 
    814      * Retrieve entries URL. 
    815      * 
    816      * @since 2.2.0 
    817      * 
    818      * @param int $page Page ID. 
    819      * @return string 
    820      */ 
    821     function get_entries_url($page = null) { 
    822         if ( isset($GLOBALS['post_type']) && ( $GLOBALS['post_type'] == 'attachment' ) ) 
    823             $path = $this->MEDIA_PATH; 
    824         else 
    825             $path = $this->ENTRIES_PATH; 
    826         $url = $this->app_base . $path; 
    827         if ( isset($page) && is_int($page) ) 
    828             $url .= "/$page"; 
    829         return $url; 
    830     } 
    831  
    832     /** 
    833      * Display entries URL. 
    834      * 
    835      * @since 2.2.0 
    836      * 
    837      * @param int $page Page ID. 
    838      */ 
    839     function the_entries_url($page = null) { 
    840         echo $this->get_entries_url($page); 
    841     } 
    842  
    843     /** 
    844      * Retrieve categories URL. 
    845      * 
    846      * @since 2.2.0 
    847      * 
    848      * @param mixed $deprecated Not used. 
    849      * @return string 
    850      */ 
    851     function get_categories_url($deprecated = '') { 
    852         if ( !empty( $deprecated ) ) 
    853             _deprecated_argument( __FUNCTION__, '2.5' ); 
    854         return $this->app_base . $this->CATEGORIES_PATH; 
    855     } 
    856  
    857     /** 
    858      * Display category URL. 
    859      * 
    860      * @since 2.2.0 
    861      */ 
    862     function the_categories_url() { 
    863         echo $this->get_categories_url(); 
    864     } 
    865  
    866     /** 
    867      * Retrieve attachment URL. 
    868      * 
    869      * @since 2.2.0 
    870      * 
    871      * @param int $page Page ID. 
    872      * @return string 
    873      */ 
    874     function get_attachments_url($page = null) { 
    875         $url = $this->app_base . $this->MEDIA_PATH; 
    876         if (isset($page) && is_int($page)) { 
    877             $url .= "/$page"; 
    878         } 
    879         return $url; 
    880     } 
    881  
    882     /** 
    883      * Display attachment URL. 
    884      * 
    885      * @since 2.2.0 
    886      * 
    887      * @param int $page Page ID. 
    888      */ 
    889     function the_attachments_url($page = null) { 
    890         echo $this->get_attachments_url($page); 
    891     } 
    892  
    893     /** 
    894      * Retrieve service URL. 
    895      * 
    896      * @since 2.3.0 
    897      * 
    898      * @return string 
    899      */ 
    900     function get_service_url() { 
    901         return $this->app_base . $this->SERVICE_PATH; 
    902     } 
    903  
    904     /** 
    905      * Retrieve entry URL. 
    906      * 
    907      * @since 2.7.0 
    908      * 
    909      * @param int $postID Post ID. 
    910      * @return string 
    911      */ 
    912     function get_entry_url($postID = null) { 
    913         if (!isset($postID)) { 
    914             global $post; 
    915             $postID = (int) $post->ID; 
    916         } 
    917  
    918         $url = $this->app_base . $this->ENTRY_PATH . "/$postID"; 
    919  
    920         return $url; 
    921     } 
    922  
    923     /** 
    924      * Display entry URL. 
    925      * 
    926      * @since 2.7.0 
    927      * 
    928      * @param int $postID Post ID. 
    929      */ 
    930     function the_entry_url($postID = null) { 
    931         echo $this->get_entry_url($postID); 
    932     } 
    933  
    934     /** 
    935      * Retrieve media URL. 
    936      * 
    937      * @since 2.2.0 
    938      * 
    939      * @param int $postID Post ID. 
    940      * @return string 
    941      */ 
    942     function get_media_url($postID = null) { 
    943         if (!isset($postID)) { 
    944             global $post; 
    945             $postID = (int) $post->ID; 
    946         } 
    947  
    948         $url = $this->app_base . $this->MEDIA_SINGLE_PATH ."/file/$postID"; 
    949  
    950         return $url; 
    951     } 
    952  
    953     /** 
    954      * Display the media URL. 
    955      * 
    956      * @since 2.2.0 
    957      * 
    958      * @param int $postID Post ID. 
    959      */ 
    960     function the_media_url($postID = null) { 
    961         echo $this->get_media_url($postID); 
    962     } 
    963  
    964     /** 
    965      * Set the current entry to post ID. 
    966      * 
    967      * @since 2.2.0 
    968      * 
    969      * @param int $postID Post ID. 
    970      */ 
    971     function set_current_entry($postID) { 
    972         global $entry; 
    973  
    974         if (!isset($postID)) { 
    975             // $this->bad_request(); 
    976             $this->not_found(); 
    977         } 
    978  
    979         $entry = wp_get_single_post($postID,ARRAY_A); 
    980  
    981         if (!isset($entry) || !isset($entry['ID'])) 
    982             $this->not_found(); 
    983  
    984         return; 
    985     } 
    986  
    987     /** 
    988      * Display posts XML. 
    989      * 
    990      * @since 2.2.0 
    991      * 
    992      * @param int $page Optional. Page ID. 
    993      * @param string $post_type Optional, default is 'post'. Post Type. 
    994      */ 
    995     function get_posts($page = 1, $post_type = 'post') { 
    996             $feed = $this->get_feed($page, $post_type); 
    997             $this->output($feed); 
    998     } 
    999  
    1000     /** 
    1001      * Display attachment XML. 
    1002      * 
    1003      * @since 2.2.0 
    1004      * 
    1005      * @param int $page Page ID. 
    1006      * @param string $post_type Optional, default is 'attachment'. Post type. 
    1007      */ 
    1008     function get_attachments($page = 1, $post_type = 'attachment') { 
    1009         $GLOBALS['post_type'] = $post_type; 
    1010         $feed = $this->get_feed($page, $post_type); 
    1011         $this->output($feed); 
    1012     } 
    1013  
    1014     /** 
    1015      * Retrieve feed XML. 
    1016      * 
    1017      * @since 2.2.0 
    1018      * 
    1019      * @param int $page Page ID. 
    1020      * @param string $post_type Optional, default is post. Post type. 
    1021      * @return string 
    1022      */ 
    1023     function get_feed($page = 1, $post_type = 'post') { 
    1024         global $post, $wp, $wp_query, $posts, $wpdb, $blog_id; 
    1025         ob_start(); 
    1026  
    1027         $this->ENTRY_PATH = $post_type; 
    1028  
    1029         if (!isset($page)) { 
    1030             $page = 1; 
    1031         } 
    1032         $page = (int) $page; 
    1033  
    1034         $count = get_option('posts_per_rss'); 
    1035  
    1036         wp('posts_per_page=' . $count . '&offset=' . ($count * ($page-1) . '&orderby=modified')); 
    1037  
    1038         $post = $GLOBALS['post']; 
    1039         $posts = $GLOBALS['posts']; 
    1040         $wp = $GLOBALS['wp']; 
    1041         $wp_query = $GLOBALS['wp_query']; 
    1042         $wpdb = $GLOBALS['wpdb']; 
    1043         $blog_id = (int) $GLOBALS['blog_id']; 
    1044  
    1045         $last_page = $wp_query->max_num_pages; 
    1046         $next_page = (($page + 1) > $last_page) ? null : $page + 1; 
    1047         $prev_page = ($page - 1) < 1 ? null : $page - 1; 
    1048         $last_page = ((int)$last_page == 1 || (int)$last_page == 0) ? null : (int) $last_page; 
    1049         $self_page = $page > 1 ? $page : null; 
    1050 ?><feed xmlns="<?php echo $this->ATOM_NS ?>" xmlns:app="<?php echo $this->ATOMPUB_NS ?>" xml:lang="<?php bloginfo_rss( 'language' ); ?>" <?php do_action('app_ns'); ?> > 
    1051 <id><?php $this->the_entries_url() ?></id> 
    1052 <updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></updated> 
    1053 <title type="text"><?php bloginfo_rss('name') ?></title> 
    1054 <subtitle type="text"><?php bloginfo_rss("description") ?></subtitle> 
    1055 <link rel="first" type="<?php echo $this->ATOM_CONTENT_TYPE ?>" href="<?php $this->the_entries_url() ?>" /> 
    1056 <?php if (isset($prev_page)): ?> 
    1057 <link rel="previous" type="<?php echo $this->ATOM_CONTENT_TYPE ?>" href="<?php $this->the_entries_url($prev_page) ?>" /> 
    1058 <?php endif; ?> 
    1059 <?php if (isset($next_page)): ?> 
    1060 <link rel="next" type="<?php echo $this->ATOM_CONTENT_TYPE ?>" href="<?php $this->the_entries_url($next_page) ?>" /> 
    1061 <?php endif; ?> 
    1062 <link rel="last" type="<?php echo $this->ATOM_CONTENT_TYPE ?>" href="<?php $this->the_entries_url($last_page) ?>" /> 
    1063 <link rel="self" type="<?php echo $this->ATOM_CONTENT_TYPE ?>" href="<?php $this->the_entries_url($self_page) ?>" /> 
    1064 <rights type="text">Copyright <?php echo date('Y'); ?></rights> 
    1065 <?php do_action('app_head'); ?> 
    1066 <?php if ( have_posts() ) { 
    1067             while ( have_posts() ) { 
    1068                 the_post(); 
    1069                 $this->echo_entry(); 
    1070             } 
    1071         } 
    1072 ?></feed> 
    1073 <?php 
    1074         $feed = ob_get_contents(); 
    1075         ob_end_clean(); 
    1076         return $feed; 
    1077     } 
    1078  
    1079     /** 
    1080      * Display entry XML. 
    1081      * 
    1082      * @since 2.2.0 
    1083      * 
    1084      * @param int $postID Post ID. 
    1085      * @param string $post_type Optional, default is post. Post type. 
    1086      * @return string. 
    1087      */ 
    1088     function get_entry($postID, $post_type = 'post') { 
    1089         ob_start(); 
    1090         switch($post_type) { 
    1091             case 'post': 
    1092                 $varname = 'p'; 
    1093                 break; 
    1094             case 'attachment': 
    1095                 $this->ENTRY_PATH = 'attachment'; 
    1096                 $varname = 'attachment_id'; 
    1097                 break; 
    1098         } 
    1099         query_posts($varname . '=' . $postID); 
    1100         if ( have_posts() ) { 
    1101             while ( have_posts() ) { 
    1102                 the_post(); 
    1103                 $this->echo_entry(); 
    1104                 $entry = ob_get_contents(); 
    1105                 break; 
    1106             } 
    1107         } 
    1108         ob_end_clean(); 
    1109  
    1110         return $entry; 
    1111     } 
    1112  
    1113     /** 
    1114      * Display post content XML. 
    1115      * 
    1116      * @since 2.3.0 
    1117      */ 
    1118     function echo_entry() { ?> 
    1119 <entry xmlns="<?php echo $this->ATOM_NS ?>" 
    1120        xmlns:app="<?php echo $this->ATOMPUB_NS ?>" xml:lang="<?php bloginfo_rss( 'language' ); ?>"> 
    1121     <id><?php the_guid( $GLOBALS['post']->ID ); ?></id> 
    1122 <?php list($content_type, $content) = prep_atom_text_construct(get_the_title()); ?> 
    1123     <title type="<?php echo $content_type ?>"><?php echo $content ?></title> 
    1124     <updated><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></updated> 
    1125     <published><?php echo get_post_time('Y-m-d\TH:i:s\Z', true); ?></published> 
    1126     <app:edited><?php echo get_post_modified_time('Y-m-d\TH:i:s\Z', true); ?></app:edited> 
    1127     <app:control> 
    1128         <app:draft><?php echo ($GLOBALS['post']->post_status == 'draft' ? 'yes' : 'no') ?></app:draft> 
    1129     </app:control> 
    1130     <author> 
    1131         <name><?php the_author()?></name> 
    1132 <?php if ( get_the_author_meta('url') && get_the_author_meta('url') != 'http://' ) { ?> 
    1133         <uri><?php the_author_meta('url') ?></uri> 
    1134 <?php } ?> 
    1135     </author> 
    1136 <?php if ($GLOBALS['post']->post_type == 'attachment') { ?> 
    1137     <link rel="edit-media" href="<?php $this->the_media_url() ?>" /> 
    1138     <content type="<?php echo $GLOBALS['post']->post_mime_type ?>" src="<?php the_guid() ; ?>"/> 
    1139 <?php } else { ?> 
    1140     <link href="<?php the_permalink_rss() ?>" /> 
    1141 <?php if ( strlen( $GLOBALS['post']->post_content ) ) : 
    1142 list($content_type, $content) = prep_atom_text_construct(get_the_content()); ?> 
    1143     <content type="<?php echo $content_type ?>"><?php echo $content ?></content> 
    1144 <?php endif; ?> 
    1145 <?php } ?> 
    1146     <link rel="edit" href="<?php $this->the_entry_url() ?>" /> 
    1147     <?php the_category_rss( 'atom' ); ?> 
    1148 <?php list($content_type, $content) = prep_atom_text_construct(get_the_excerpt()); ?> 
    1149     <summary type="<?php echo $content_type ?>"><?php echo $content ?></summary> 
    1150     <?php do_action('app_entry'); ?> 
    1151 </entry> 
    1152 <?php } 
    1153  
    1154     /** 
    1155      * Set 'OK' (200) status header. 
    1156      * 
    1157      * @since 2.2.0 
    1158      */ 
    1159     function ok() { 
    1160         header('Content-Type: text/plain'); 
    1161         status_header('200'); 
    1162         exit; 
    1163     } 
    1164  
    1165     /** 
    1166      * Set 'No Content' (204) status header. 
    1167      * 
    1168      * @since 2.2.0 
    1169      */ 
    1170     function no_content() { 
    1171         header('Content-Type: text/plain'); 
    1172         status_header('204'); 
    1173         echo "Moved to Trash."; 
    1174         exit; 
    1175     } 
    1176  
    1177     /** 
    1178      * Display 'Internal Server Error' (500) status header. 
    1179      * 
    1180      * @since 2.2.0 
    1181      * 
    1182      * @param string $msg Optional. Status string. 
    1183      */ 
    1184     function internal_error($msg = 'Internal Server Error') { 
    1185         header('Content-Type: text/plain'); 
    1186         status_header('500'); 
    1187         echo $msg; 
    1188         exit; 
    1189     } 
    1190  
    1191     /** 
    1192      * Set 'Bad Request' (400) status header. 
    1193      * 
    1194      * @since 2.2.0 
    1195      */ 
    1196     function bad_request() { 
    1197         header('Content-Type: text/plain'); 
    1198         status_header('400'); 
    1199         exit; 
    1200     } 
    1201  
    1202     /** 
    1203      * Set 'Length Required' (411) status header. 
    1204      * 
    1205      * @since 2.2.0 
    1206      */ 
    1207     function length_required() { 
    1208         header("HTTP/1.1 411 Length Required"); 
    1209         header('Content-Type: text/plain'); 
    1210         status_header('411'); 
    1211         exit; 
    1212     } 
    1213  
    1214     /** 
    1215      * Set 'Unsupported Media Type' (415) status header. 
    1216      * 
    1217      * @since 2.2.0 
    1218      */ 
    1219     function invalid_media() { 
    1220         header("HTTP/1.1 415 Unsupported Media Type"); 
    1221         header('Content-Type: text/plain'); 
    1222         exit; 
    1223     } 
    1224  
    1225     /** 
    1226      * Set 'Forbidden' (403) status header. 
    1227      * 
    1228      * @since 2.6.0 
    1229      */ 
    1230     function forbidden($reason='') { 
    1231         header('Content-Type: text/plain'); 
    1232         status_header('403'); 
    1233         echo $reason; 
    1234         exit; 
    1235     } 
    1236  
    1237     /** 
    1238      * Set 'Not Found' (404) status header. 
    1239      * 
    1240      * @since 2.2.0 
    1241      */ 
    1242     function not_found() { 
    1243         header('Content-Type: text/plain'); 
    1244         status_header('404'); 
    1245         exit; 
    1246     } 
    1247  
    1248     /** 
    1249      * Set 'Not Allowed' (405) status header. 
    1250      * 
    1251      * @since 2.2.0 
    1252      */ 
    1253     function not_allowed($allow) { 
    1254         header('Allow: ' . join(',', $allow)); 
    1255         status_header('405'); 
    1256         exit; 
    1257     } 
    1258  
    1259     /** 
    1260      * Display Redirect (302) content and set status headers. 
    1261      * 
    1262      * @since 2.3.0 
    1263      */ 
    1264     function redirect($url) { 
    1265         $escaped_url = esc_attr($url); 
    1266         $content = <<<EOD 
    1267 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
    1268 <html> 
    1269   <head> 
    1270     <title>302 Found</title> 
    1271   </head> 
    1272 <body> 
    1273   <h1>Found</h1> 
    1274   <p>The document has moved <a href="$escaped_url">here</a>.</p> 
    1275   </body> 
    1276 </html> 
    1277  
    1278 EOD; 
    1279         header('HTTP/1.1 302 Moved'); 
    1280         header('Content-Type: text/html'); 
    1281         header('Location: ' . $url); 
    1282         echo $content; 
    1283         exit; 
    1284  
    1285     } 
    1286  
    1287     /** 
    1288      * Set 'Client Error' (400) status header. 
    1289      * 
    1290      * @since 2.2.0 
    1291      */ 
    1292     function client_error($msg = 'Client Error') { 
    1293         header('Content-Type: text/plain'); 
    1294         status_header('400'); 
    1295         exit; 
    1296     } 
    1297  
    1298     /** 
    1299      * Set created status headers (201). 
    1300      * 
    1301      * Sets the 'content-type', 'content-location', and 'location'. 
    1302      * 
    1303      * @since 2.2.0 
    1304      */ 
    1305     function created($post_ID, $content, $post_type = 'post') { 
    1306         $edit = $this->get_entry_url($post_ID); 
    1307         switch($post_type) { 
    1308             case 'post': 
    1309                 $ctloc = $this->get_entry_url($post_ID); 
    1310                 break; 
    1311             case 'attachment': 
    1312                 $edit = $this->app_base . "attachments/$post_ID"; 
    1313                 break; 
    1314         } 
    1315         header("Content-Type: $this->ATOM_CONTENT_TYPE"); 
    1316         if (isset($ctloc)) 
    1317             header('Content-Location: ' . $ctloc); 
    1318         header('Location: ' . $edit); 
    1319         status_header('201'); 
    1320         echo $content; 
    1321         exit; 
    1322     } 
    1323  
    1324     /** 
    1325      * Set 'Auth Required' (401) headers. 
    1326      * 
    1327      * @since 2.2.0 
    1328      * 
    1329      * @param string $msg Status header content and HTML content. 
    1330      */ 
    1331     function auth_required($msg) { 
    1332         nocache_headers(); 
    1333         header('WWW-Authenticate: Basic realm="WordPress Atom Protocol"'); 
    1334         header("HTTP/1.1 401 $msg"); 
    1335         header('Status: 401 ' . $msg); 
    1336         header('Content-Type: text/html'); 
    1337         $content = <<<EOD 
    1338 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
    1339 <html> 
    1340   <head> 
    1341     <title>401 Unauthorized</title> 
    1342   </head> 
    1343 <body> 
    1344     <h1>401 Unauthorized</h1> 
    1345     <p>$msg</p> 
    1346   </body> 
    1347 </html> 
    1348  
    1349 EOD; 
    1350         echo $content; 
    1351         exit; 
    1352     } 
    1353  
    1354     /** 
    1355      * Display XML and set headers with content type. 
    1356      * 
    1357      * @since 2.2.0 
    1358      * 
    1359      * @param string $xml Display feed content. 
    1360      * @param string $ctype Optional, default is 'atom+xml'. Feed content type. 
    1361      */ 
    1362     function output($xml, $ctype = 'application/atom+xml') { 
    1363             status_header('200'); 
    1364             $xml = '<?xml version="1.0" encoding="' . strtolower(get_option('blog_charset')) . '"?>'."\n".$xml; 
    1365             header('Connection: close'); 
    1366             header('Content-Length: '. strlen($xml)); 
    1367             header('Content-Type: ' . $ctype); 
    1368             header('Content-Disposition: attachment; filename=atom.xml'); 
    1369             header('Date: '. date('r')); 
    1370             if ($this->do_output) 
    1371                 echo $xml; 
    1372             exit; 
    1373     } 
    1374  
    1375     /** 
    1376      * Sanitize content for database usage. 
    1377      * 
    1378      * @since 2.2.0 
    1379      * 
    1380      * @param array $array Sanitize array and multi-dimension array. 
    1381      */ 
    1382     function escape(&$array) { 
    1383         global $wpdb; 
    1384  
    1385         foreach ($array as $k => $v) { 
    1386                 if (is_array($v)) { 
    1387                         $this->escape($array[$k]); 
    1388                 } else if (is_object($v)) { 
    1389                         //skip 
    1390                 } else { 
    1391                         $array[$k] = $wpdb->escape($v); 
    1392                 } 
    1393         } 
    1394     } 
    1395  
    1396     /** 
    1397      * Access credential through various methods and perform login. 
    1398      * 
    1399      * @since 2.2.0 
    1400      * 
    1401      * @return bool 
    1402      */ 
    1403     function authenticate() { 
    1404         // if using mod_rewrite/ENV hack 
    1405         // http://www.besthostratings.com/articles/http-auth-php-cgi.html 
    1406         if (isset($_SERVER['HTTP_AUTHORIZATION'])) { 
    1407             list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = 
    1408                 explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6))); 
    1409         } else if (isset($_SERVER['REDIRECT_REMOTE_USER'])) { 
    1410             // Workaround for setups that do not forward HTTP_AUTHORIZATION 
    1411             // See http://trac.wordpress.org/ticket/7361 
    1412             list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = 
    1413                 explode(':', base64_decode(substr($_SERVER['REDIRECT_REMOTE_USER'], 6))); 
    1414         } 
    1415  
    1416         // If Basic Auth is working... 
    1417         if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { 
    1418             $user = wp_authenticate($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); 
    1419             if ( $user && !is_wp_error($user) ) { 
    1420                 wp_set_current_user($user->ID); 
    1421                 return true; 
    1422             } 
    1423         } 
    1424  
    1425         return false; 
    1426     } 
    1427  
    1428     /** 
    1429      * Retrieve accepted content types. 
    1430      * 
    1431      * @since 2.2.0 
    1432      * 
    1433      * @param array $types Optional. Content Types. 
    1434      * @return string 
    1435      */ 
    1436     function get_accepted_content_type($types = null) { 
    1437  
    1438         if (!isset($types)) { 
    1439             $types = $this->media_content_types; 
    1440         } 
    1441  
    1442         if (!isset($_SERVER['CONTENT_LENGTH']) || !isset($_SERVER['CONTENT_TYPE'])) { 
    1443             $this->length_required(); 
    1444         } 
    1445  
    1446         $type = $_SERVER['CONTENT_TYPE']; 
    1447         list($type,$subtype) = explode('/',$type); 
    1448         list($subtype) = explode(";",$subtype); // strip MIME parameters 
    1449  
    1450         foreach($types as $t) { 
    1451             list($acceptedType,$acceptedSubtype) = explode('/',$t); 
    1452             if ($acceptedType == '*' || $acceptedType == $type) { 
    1453                 if ($acceptedSubtype == '*' || $acceptedSubtype == $subtype) 
    1454                     return $type . "/" . $subtype; 
    1455             } 
    1456         } 
    1457  
    1458         $this->invalid_media(); 
    1459     } 
    1460  
    1461     /** 
    1462      * Process conditionals for posts. 
    1463      * 
    1464      * @since 2.2.0 
    1465      */ 
    1466     function process_conditionals() { 
    1467  
    1468         if (empty($this->params)) return; 
    1469         if ($_SERVER['REQUEST_METHOD'] == 'DELETE') return; 
    1470  
    1471         switch($this->params[0]) { 
    1472             case $this->ENTRY_PATH: 
    1473                 global $post; 
    1474                 $post = wp_get_single_post($this->params[1]); 
    1475                 $wp_last_modified = get_post_modified_time('D, d M Y H:i:s', true); 
    1476                 $post = null; 
    1477                 break; 
    1478             case $this->ENTRIES_PATH: 
    1479                 $wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastpostmodified('GMT'), 0).' GMT'; 
    1480                 break; 
    1481             default: 
    1482                 return; 
    1483         } 
    1484         $wp_etag = md5($wp_last_modified); 
    1485         @header("Last-Modified: $wp_last_modified"); 
    1486         @header("ETag: $wp_etag"); 
    1487  
    1488         // Support for Conditional GET 
    1489         if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) 
    1490             $client_etag = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']); 
    1491         else 
    1492             $client_etag = false; 
    1493  
    1494         $client_last_modified = trim( $_SERVER['HTTP_IF_MODIFIED_SINCE']); 
    1495         // If string is empty, return 0. If not, attempt to parse into a timestamp 
    1496         $client_modified_timestamp = $client_last_modified ? strtotime($client_last_modified) : 0; 
    1497  
    1498         // Make a timestamp for our most recent modification... 
    1499         $wp_modified_timestamp = strtotime($wp_last_modified); 
    1500  
    1501         if ( ($client_last_modified && $client_etag) ? 
    1502         (($client_modified_timestamp >= $wp_modified_timestamp) && ($client_etag == $wp_etag)) : 
    1503         (($client_modified_timestamp >= $wp_modified_timestamp) || ($client_etag == $wp_etag)) ) { 
    1504             status_header( 304 ); 
    1505             exit; 
    1506         } 
    1507     } 
    1508  
    1509     /** 
    1510      * Convert RFC3339 time string to timestamp. 
    1511      * 
    1512      * @since 2.3.0 
    1513      * 
    1514      * @param string $str String to time. 
    1515      * @return bool|int false if format is incorrect. 
    1516      */ 
    1517     function rfc3339_str2time($str) { 
    1518  
    1519         $match = false; 
    1520         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)) 
    1521             return false; 
    1522  
    1523         if ($match[3] == 'Z') 
    1524             $match[3] = '+0000'; 
    1525  
    1526         return strtotime($match[1] . " " . $match[2] . " " . $match[3]); 
    1527     } 
    1528  
    1529     /** 
    1530      * Retrieve published time to display in XML. 
    1531      * 
    1532      * @since 2.3.0 
    1533      * 
    1534      * @param string $published Time string. 
    1535      * @return string 
    1536      */ 
    1537     function get_publish_time($published) { 
    1538  
    1539         $pubtime = $this->rfc3339_str2time($published); 
    1540  
    1541         if (!$pubtime) { 
    1542             return array(current_time('mysql'),current_time('mysql',1)); 
    1543         } else { 
    1544             return array(date("Y-m-d H:i:s", $pubtime), gmdate("Y-m-d H:i:s", $pubtime)); 
    1545         } 
    1546     } 
    1547  
    1548 } 
    1549  
    1550 /** 
    1551  * AtomServer 
    1552  * @var AtomServer 
    1553  * @global object $server 
    1554  */ 
    1555 $server = new AtomServer(); 
    1556 $server->handle_request(); 
     50// Handle the request 
     51$wp_atom_server->handle_request(); 
  • trunk/wp-includes/class-wp-atom-server.php

    r20059 r20062  
    11<?php 
    2 /** 
    3  * Atom Publishing Protocol support for WordPress 
    4  * 
    5  * @version 1.0.5-dc 
    6  */ 
    7  
    8 /** 
    9  * WordPress is handling an Atom Publishing Protocol request. 
    10  * 
    11  * @var bool 
    12  */ 
    13 define('APP_REQUEST', true); 
    14  
    15 /** Set up WordPress environment */ 
    16 require_once('./wp-load.php'); 
    17  
    18 /** Atom Publishing Protocol Class */ 
    19 require_once(ABSPATH . WPINC . '/atomlib.php'); 
    20  
    21 /** Admin Image API for metadata updating */ 
    22 require_once(ABSPATH . '/wp-admin/includes/image.php'); 
    23  
    24 $_SERVER['PATH_INFO'] = preg_replace( '/.*\/wp-app\.php/', '', $_SERVER['REQUEST_URI'] ); 
    25  
    26 /** 
    27  * Whether to always authenticate user. Permanently set to true. 
    28  * 
    29  * @name always_authenticate 
    30  * @var int|bool 
    31  * @todo Should be an option somewhere 
    32  */ 
    33 $always_authenticate = 1; 
    34  
    35 /** 
    36  * Writes logging info to a file. 
    37  * 
    38  * @since 2.2.0 
    39  * @deprecated 3.4.0 
    40  * @deprecated Use error_log() 
    41  * @link http://www.php.net/manual/en/function.error-log.php 
    42  * 
    43  * @param string $label Type of logging 
    44  * @param string $msg Information describing logging reason. 
    45  */ 
    46 function log_app( $label, $msg ) { 
    47     _deprecated_function( __FUNCTION__, '3.4', 'error_log()' ); 
    48     if ( ! empty( $GLOBALS['app_logging'] ) ) 
    49         error_log( $label . ' - ' . $message ); 
    50 } 
    51  
    52 /** 
    53  * Filter to add more post statuses. 
    54  * 
    55  * @since 2.2.0 
    56  * 
    57  * @param string $where SQL statement to filter. 
    58  * @return string Filtered SQL statement with added post_status for where clause. 
    59  */ 
    60 function wa_posts_where_include_drafts_filter($where) { 
    61     $where = str_replace("post_status = 'publish'","post_status = 'publish' OR post_status = 'future' OR post_status = 'draft' OR post_status = 'inherit'", $where); 
    62     return $where; 
    63  
    64 } 
    65 add_filter('posts_where', 'wa_posts_where_include_drafts_filter'); 
    662 
    673/** 
     
    728 * @since 2.2.0 
    739 */ 
    74 class AtomServer { 
     10class wp_atom_server { 
    7511 
    7612    /** 
     
    240176                        'DELETE' => 'delete_attachment'), 
    241177        ); 
     178 
     179        add_filter( 'wp_die_handler', array( $this, 'return_atom_die_handler' ) ); 
     180    } 
     181 
     182    /** 
     183     * Override die handler 
     184     * @return callback 
     185     */ 
     186    public function return_atom_die_handler() { 
     187        return array( $this, 'atom_die_handler' ); 
     188    } 
     189 
     190    /** 
     191     * Die with a message.  Only accept strings, no WP_Error objects yet 
     192     * @param string $message 
     193     * @return void 
     194     */ 
     195    public function atom_die_handler( $message ) { 
     196        if ( is_scalar( $message ) ) 
     197            die( (string) $message ); 
     198        die(); 
    242199    } 
    243200 
     
    248205     */ 
    249206    function handle_request() { 
    250         global $always_authenticate; 
    251207 
    252208        if ( !empty( $_SERVER['ORIG_PATH_INFO'] ) ) 
     
    282238                    // user. each handler will decide if auth is required or not. 
    283239                    if ( !$this->authenticate() ) { 
    284                         if ( $always_authenticate ) 
    285                             $this->auth_required('Credentials required.'); 
     240                        $this->auth_required('Credentials required.'); 
    286241                    } 
    287242 
    288243                    array_shift($matches); 
    289                     call_user_func_array(array(&$this,$funcs[$method]), $matches); 
    290                     exit(); 
     244                    call_user_func_array(array($this,$funcs[$method]), $matches); 
     245                    wp_die(); 
    291246                } else { 
    292247                    // only allow what we have handlers for... 
     
    306261     */ 
    307262    function get_service() { 
     263 
    308264        if ( !current_user_can( 'edit_posts' ) ) 
    309265            $this->auth_required( __( 'Sorry, you do not have the right to access this site.' ) ); 
     
    345301     */ 
    346302    function get_categories_xml() { 
     303 
    347304        if ( !current_user_can( 'edit_posts' ) ) 
    348305            $this->auth_required( __( 'Sorry, you do not have the right to access this site.' ) ); 
     
    411368        $post_excerpt = ''; 
    412369        $pubtimes     = ''; 
    413  
     370         
    414371        if ( isset( $entry->title ) && is_array( $entry->title ) && !empty( $entry->title[1] ) ) 
    415372            $post_title = (string) $entry->title[1]; 
     
    420377        if ( !empty( $entry->published ) ) 
    421378            $pubtimes = (string) $entry->published; 
    422  
     379         
    423380        $pubtimes = $this->get_publish_time( $pubtimes ); 
    424381 
     
    684641     */ 
    685642    function delete_attachment($postID) { 
     643 
    686644        // check for not found 
    687645        global $entry; 
     
    751709        } 
    752710 
    753         exit; 
     711        wp_die(); 
    754712    } 
    755713 
     
    994952     */ 
    995953    function get_posts($page = 1, $post_type = 'post') { 
    996             $feed = $this->get_feed($page, $post_type); 
    997             $this->output($feed); 
     954        $feed = $this->get_feed($page, $post_type); 
     955        $this->output($feed); 
    998956    } 
    999957 
     
    1034992        $count = get_option('posts_per_rss'); 
    1035993 
    1036         wp('posts_per_page=' . $count . '&offset=' . ($count * ($page-1) . '&orderby=modified')); 
     994        wp('posts_per_page=' . $count . '&offset=' . ($count * ($page-1)) . '&orderby=modified&post_status=any'); 
    1037995 
    1038996        $post = $GLOBALS['post']; 
     
    11601118        header('Content-Type: text/plain'); 
    11611119        status_header('200'); 
    1162         exit; 
     1120        wp_die(); 
    11631121    } 
    11641122 
     
    11721130        status_header('204'); 
    11731131        echo "Moved to Trash."; 
    1174         exit; 
     1132        wp_die(); 
    11751133    } 
    11761134 
     
    11861144        status_header('500'); 
    11871145        echo $msg; 
    1188         exit; 
     1146        wp_die(); 
    11891147    } 
    11901148 
     
    11971155        header('Content-Type: text/plain'); 
    11981156        status_header('400'); 
    1199         exit; 
     1157        wp_die(); 
    12001158    } 
    12011159 
     
    12091167        header('Content-Type: text/plain'); 
    12101168        status_header('411'); 
    1211         exit; 
     1169        wp_die(); 
    12121170    } 
    12131171 
     
    12201178        header("HTTP/1.1 415 Unsupported Media Type"); 
    12211179        header('Content-Type: text/plain'); 
    1222         exit; 
     1180        wp_die(); 
    12231181    } 
    12241182 
     
    12321190        status_header('403'); 
    12331191        echo $reason; 
    1234         exit; 
     1192        wp_die(); 
    12351193    } 
    12361194 
     
    12431201        header('Content-Type: text/plain'); 
    12441202        status_header('404'); 
    1245         exit; 
     1203        wp_die(); 
    12461204    } 
    12471205 
     
    12541212        header('Allow: ' . join(',', $allow)); 
    12551213        status_header('405'); 
    1256         exit; 
     1214        wp_die(); 
    12571215    } 
    12581216 
     
    12811239        header('Location: ' . $url); 
    12821240        echo $content; 
    1283         exit; 
     1241        wp_die(); 
    12841242 
    12851243    } 
     
    12931251        header('Content-Type: text/plain'); 
    12941252        status_header('400'); 
    1295         exit; 
     1253        wp_die(); 
    12961254    } 
    12971255 
     
    13191277        status_header('201'); 
    13201278        echo $content; 
    1321         exit; 
     1279        wp_die(); 
    13221280    } 
    13231281 
     
    13491307EOD; 
    13501308        echo $content; 
    1351         exit; 
     1309        wp_die(); 
    13521310    } 
    13531311 
     
    13611319     */ 
    13621320    function output($xml, $ctype = 'application/atom+xml') { 
    1363             status_header('200'); 
    1364             $xml = '<?xml version="1.0" encoding="' . strtolower(get_option('blog_charset')) . '"?>'."\n".$xml; 
    1365             header('Connection: close'); 
    1366             header('Content-Length: '. strlen($xml)); 
    1367             header('Content-Type: ' . $ctype); 
    1368             header('Content-Disposition: attachment; filename=atom.xml'); 
    1369             header('Date: '. date('r')); 
    1370             if ($this->do_output) 
    1371                 echo $xml; 
    1372             exit; 
     1321        status_header('200'); 
     1322        $xml = '<?xml version="1.0" encoding="' . strtolower(get_option('blog_charset')) . '"?>'."\n".$xml; 
     1323        header('Connection: close'); 
     1324        header('Content-Length: '. strlen($xml)); 
     1325        header('Content-Type: ' . $ctype); 
     1326        header('Content-Disposition: attachment; filename=atom.xml'); 
     1327        header('Date: '. date('r')); 
     1328        if ($this->do_output) 
     1329            echo $xml; 
     1330        wp_die(); 
    13731331    } 
    13741332 
     
    14021360     */ 
    14031361    function authenticate() { 
     1362 
    14041363        // if using mod_rewrite/ENV hack 
    14051364        // http://www.besthostratings.com/articles/http-auth-php-cgi.html 
     
    14161375        // If Basic Auth is working... 
    14171376        if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { 
     1377 
    14181378            $user = wp_authenticate($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); 
    14191379            if ( $user && !is_wp_error($user) ) { 
     
    15031463        (($client_modified_timestamp >= $wp_modified_timestamp) || ($client_etag == $wp_etag)) ) { 
    15041464            status_header( 304 ); 
    1505             exit; 
     1465            wp_die(); 
    15061466        } 
    15071467    } 
     
    15471507 
    15481508} 
    1549  
    1550 /** 
    1551  * AtomServer 
    1552  * @var AtomServer 
    1553  * @global object $server 
    1554  */ 
    1555 $server = new AtomServer(); 
    1556 $server->handle_request(); 
Note: See TracChangeset for help on using the changeset viewer.