Skip to content

Commit

Permalink
Version 0.4
Browse files Browse the repository at this point in the history
  • Loading branch information
dshanske committed Jul 19, 2015
1 parent 457cbcc commit 3c3bd6e
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 39 deletions.
115 changes: 83 additions & 32 deletions micropub.php
Expand Up @@ -5,7 +5,7 @@
Description: <a href="https://indiewebcamp.com/micropub">Micropub</a> server.
Author: Ryan Barrett
Author URI: https://snarfed.org/
Version: 0.3
Version: 0.4
*/

// Example command line for testing:
Expand All @@ -20,6 +20,23 @@
// curl -i -d 'code=CODE&me=SITE&client_id=indieauth&redirect_uri=https://indieauth.com/success' 'https://tokens.indieauth.com/token'
// 4. Extract the access_token parameter from the response body.

// For debugging purposes this will bypass Micropub authentication
// in favor of WordPress authentication
// Using this to test querying(q=) parameters quickly
if ( ! defined( 'MICROPUB_LOCAL_AUTH' ) )
define('MICROPUB_LOCAL_AUTH', '0');

// Allows for a custom Authentication and Token Endpoint
if ( ! defined( 'MICROPUB_AUTHENTICATION_ENDPOINT' ) )
define('MICROPUB_AUTHENTICATION_ENDPOINT', 'https://indieauth.com/auth');
if ( ! defined( 'MICROPUB_TOKEN_ENDPOINT' ) )
define('MICROPUB_TOKEN_ENDPOINT', 'https://tokens.indieauth.com/token');

// For debugging purposes this will set all Micropub posts to Draft
if ( ! defined( 'MICROPUB_DRAFT_MODE' ) )
define('MICROPUB_DRAFT_MODE', '0');


if (!class_exists('Micropub')) :

add_action('init', array('Micropub', 'init'));
Expand Down Expand Up @@ -70,14 +87,26 @@ public static function parse_query($wp) {
return;
}
header('Content-Type: text/plain; charset=' . get_option('blog_charset'));

$user_id = Micropub::authorize();
// For debug purposes be able to bypass Micropub auth with WordPress auth
if (MICROPUB_LOCAL_AUTH!=0) {
if (!is_user_logged_in()) {
auth_redirect();
}
$user_id = wp_get_current_user();
}
else {
$user_id = Micropub::authorize();
}
// TODO: future development note to add JSON support

// validate micropub request params
if (!isset($_POST['h']) && !isset($_POST['url'])) {
Micropub::error(400, 'requires either h= (for create) or url= (for update, delete, etc)');
if (!isset($_POST['h']) && !isset($_POST['url']) && !isset($_GET['q'])) {
Micropub::error(400, 'Empty Micropub request. Either an "h", "url" or "q" property is required, e.g. h=entry or url=http://example.com/post/100 or q=syndicate-to');
}
if (isset($_GET['q'])) {
Micropub::return_query($user_id);
exit;
}

// support both action= and operation= parameter names
if (!isset($_POST['action'])) {
$_POST['action'] = isset($_POST['operation']) ? $_POST['operation']
Expand All @@ -89,11 +118,11 @@ public static function parse_query($wp) {
$args['post_author'] = $user_id;
}

if (!isset($_POST['url']) || $_POST['action'] == 'create') {
if (!isset($_POST['edit-of']) || !isset($_POST['url']) || $_POST['action'] == 'create') {
if ($user_id && !user_can($user_id, 'publish_posts')) {
Micropub::error(403, 'user id ' . $user_id . ' cannot publish posts');
}
$args['post_status'] = 'publish';
$args['post_status'] = MICROPUB_DRAFT_MODE ? 'draft' : 'publish';
kses_remove_filters(); // prevent sanitizing HTML tags in post_content
$args['ID'] = Micropub::check_error(wp_insert_post($args));
kses_init_filters();
Expand All @@ -103,7 +132,7 @@ public static function parse_query($wp) {

} else {
if ($args['ID'] == 0) {
Micropub::error(400, $_POST['url'] . ' not found');
Micropub::error(400, $_POST['edit-of'] . ' not found');
}

if ($_POST['action'] == 'edit' || !isset($_POST['action'])) {
Expand Down Expand Up @@ -197,6 +226,24 @@ private static function authorize() {
return NULL;
}

private static function return_query($user_id) {
header('Content-type: application/x-www-form-urlencoded');
switch($_GET['q']) {
case 'syndicate-to':
// Fallback
case 'mp-syndicate-to':
status_header(200);
// return empty syndication target with filter
$syndication = apply_filters('micropub_syndicate-to', array(), $user_id);
if (!empty($syndication)) {
echo 'syndicate-to[]=' . implode('&syndicate-to[]=', $syndication);
}
break;
default:
Micropub::error(400, 'unknown query ' . $_GET['q']);
}
}

private static function handle_authorize_error($code, $msg) {
$home = untrailingslashit(home_url());
if ($home == 'http://localhost') {
Expand Down Expand Up @@ -226,10 +273,14 @@ private static function generate_args() {
}

// these are transformed or looked up
if (isset($_POST['edit-of'])) {
$args['ID'] = url_to_postid($_POST['edit-of']);
}
if (isset($_POST['url'])) {
$args['ID'] = url_to_postid($_POST['url']);
}


if (isset($_POST['published'])) {
$args['post_date'] = iso8601_to_datetime($_POST['published']);
$args['post_date_gmt'] = get_gmt_from_date($args['post_date']);
Expand All @@ -252,6 +303,9 @@ private static function generate_args() {
if (isset($_POST['content'])) {
$args['post_content'] = $_POST['content'];
}
else if (isset($_POST['summary'])) {
$args['post_content'] = $_POST['summary'];
}
}
// Else markup the content before passing it through
else {
Expand Down Expand Up @@ -377,24 +431,23 @@ private static function postprocess($post_id) {
* https://indiewebcamp.com/WordPress_Data#Microformats_data
*/
private static function store_mf2($post_id) {
$props = array('category', 'content', 'description', 'end', 'h', 'in-reply-to',
'like', 'like-of', 'location', 'name', 'photo', 'published',
'repost', 'repost-of', 'rsvp', 'slug', 'start', 'summary');

foreach ($props as $prop) {
if (isset($_POST[$prop])) {
$vals = $_POST[$prop];
if (!is_array($vals)) {
$vals = array($vals);
}

$key = 'mf2_' . $prop;
// Do not store access_token or other optional parameters
$blacklist = array('access_token');
foreach ($_POST as $key => $value) {
if (!is_array($value)) {
$value = array($value);
}
if (!in_array($key, $blacklist)) {
$key = 'mf2_' . $key;
delete_post_meta($post_id, $key); // clear old value(s)
foreach ($vals as $val) {
add_post_meta($post_id, $key, $val);
foreach ($value as $val) {
if (!empty($val)) {
add_post_meta($post_id, $key, $val);
}
}
}
}

}

private static function error($code, $msg) {
Expand All @@ -416,20 +469,18 @@ private static function check_error($result) {
* The micropub autodicovery meta tags
*/
public static function html_header() {
?>
<link rel="micropub" href="<?php echo site_url('?micropub=endpoint') ?>">
<link rel="authorization_endpoint" href="https://indieauth.com/auth">
<link rel="token_endpoint" href="https://tokens.indieauth.com/token">
<?php
echo '<link rel="micropub" href="' . site_url('?micropub=endpoint') . '">';
echo '<link rel="authorization_endpoint" href="' . MICROPUB_AUTHENTICATION_ENDPOINT . '">';
echo '<link rel="token_endpoint" href="' . MICROPUB_TOKEN_ENDPOINT . '">';
}

/**
* The micropub autodicovery http-header
*/
public static function http_header() {
header('Link: <' . site_url('?micropub=endpoint') . '>; rel="micropub"', false);
header('Link: <https://indieauth.com/auth>; rel="authorization_endpoint"', false);
header('Link: <https://tokens.indieauth.com/token>; rel="token_endpoint"', false);
header('Link: <' . MICROPUB_AUTHENTICATION_ENDPOINT . '>; rel="authorization_endpoint"', false);
header('Link: <' . MICROPUB_TOKEN_ENDPOINT . '>; rel="token_endpoint"', false);
}

/**
Expand All @@ -439,9 +490,9 @@ public static function jrd_links($array) {
$array['links'][] = array('rel' => 'micropub',
'href' => site_url('?micropub=endpoint'));
$array['links'][] = array('rel' => 'authorization_endpoint',
'href' => 'https://indieauth.com/auth');
'href' => MICROPUB_AUTHENTICATION_ENDPOINT);
$array['links'][] = array('rel' => 'token_endpoint',
'href' => 'https://tokens.indieauth.com/token');
'href' => MICROPUB_TOKEN_ENDPOINT);
}
}

Expand Down
42 changes: 35 additions & 7 deletions readme.txt
@@ -1,8 +1,8 @@
=== Plugin Name ===
Contributors: snarfed
Contributors: snarfed, dshanske
Tags: micropub
Requires at least: 3.0.1
Tested up to: 4.1
Tested up to: 4.2
Stable tag: trunk
License: CC0
License URI: http://creativecommons.org/publicdomain/zero/1.0/
Expand Down Expand Up @@ -44,13 +44,18 @@ Micropub properties:
* `summary`
* `url`

Adds one WordPress filter, `before_micropub($wp_args)`, and one hook,
`after_micropub($post_id)`.
Adds the following filters:
* `before_micropub($wp_args)`
* `micropub_syndicate-to', array(), $user_id)`

And the hook:
* `after_micropub($post_id)`

Delegates token handling to
[tokens.indieauth.com](https://tokens.indieauth.com/). For ease of development,
if the WordPress site is running on `localhost`, it logs a warning if the access
token is missing or invalid and still allows the request.
[tokens.indieauth.com](https://tokens.indieauth.com/) by default. For ease of
development, if the WordPress site is running on `localhost`, it logs a warning
if the access token is missing or invalid and still allows the request.
There is also a wp-config option to use WordPress authentication.

Stores [microformats2](http://microformats.org/wiki/microformats2) properties in
[post metadata](http://codex.wordpress.org/Function_Reference/post_meta_Function_Examples)
Expand All @@ -64,6 +69,18 @@ and pull requests are welcome!

Install from the WordPress plugin directory or put `micropub.php` in your plugin directory. No setup needed.

== Configuration Options ==

These configuration options can be enabled by adding them to your wp-config.php

* `define('MICROPUB_LOCAL_AUTH', '1')` - Bypasses Micropub authentication in
favor of WordPress authentication for testing purposes
* `define('MICROPUB_AUTHENTICATION_ENDPOINT'`, 'https://indieauth.com/auth')
Define a custom authentication endpoint
* `define('MICROPUB_TOKEN_ENDPOINT', 'https://tokens.indieauth.com/token')` -
Define a custom token endpoint
* `define('MICROPUB_DRAFT_MODE', '1')` - set all micropub posts to draft mode

== Frequently Asked Questions ==

None yet.
Expand All @@ -78,6 +95,17 @@ TODO

== Changelog ==

= 0.4 =
* Store all properties in post meta except those in a blacklist
* Support setting authentication and token endpoint in wp-config
(set MICROPUB_AUTHENTICATION_ENDPOINT and MICROPUB_TOKEN_ENDPOINT)
* Support setting all micropub posts to draft in wp-config for testing by
setting MICROPUB_DRAFT_MODE in wp-config.
* Support using local auth to authenticate as opposed to Indieauth
as by setting MICROPUB_LOCAL_AUTH in wp-config
* Set content to summary if no content provided
* Support querying for syndicate-to and future query options

= 0.3 =
* Use the specific WordPress user whose URL matches the access token, if
possible.
Expand Down

0 comments on commit 3c3bd6e

Please sign in to comment.