[ Root ] [ Search ] [ Index ]

PHP Cross Reference of WordPress 3.0.1

Provided by Yoast

title

Body

[close]

/ -> wp-app.php (source)

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


Generated: Thu Oct 14 05:12:05 2010 Cross-referenced by PHPXref 0.7