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