work.log

元エンジニアの備忘録的ブログ

WordPressのXML-RPCでwp_optionsを操作する

投稿:

WordPress 自動投稿ツール作成の関連記事です。

肝心の「自動」部分を未だに書けずにいるのですが、今回は XML-RPC で wp_options を操作するメモを残したいと思います。

wp_options にはブログの設定情報や、プラグインのデータ、その他色々入っている WordPress のテーブルで、ちょっとしたデータを保存するのにも便利で何かと重宝します。

設定値何かはリモートから一元管理できたらさぞ便利だろうなと思ったので、XML-RPC のカスタムメソッドを書いてみました。

WordPress XML-RPC サーバの拡張

実の所、wp_options 関連メソッドとして「wp.getOptions」と「wp.setOptions」が用意されています。ですが、WordPress の基本設定以外は操作できないみたいだったので、オリジナルのメソッドを作成してみます。

メソッドの拡張は以下のコードを functions.php に追加します。

function add_wp_methods( $methods ) {

	$methods['my.getWpOptions'] = 'my_get_options';
	$methods['my.setWpOptions'] = 'my_set_options';
	$methods['my.delWpOptions'] = 'my_del_options';
	return $methods;

}
add_filter( 'xmlrpc_methods', 'add_wp_methods' );

function my_get_options( $args ) {

	if ( ! isset( $args[3]['opt_name'] ) ) { return FALSE; }
	return get_option( $args[3]['opt_name'] );

}

function my_del_options( $args ) {

	if ( ! isset( $args[3]['opt_name'] ) ) { return FALSE; }
	return delete_option( $args[3]['opt_name'] );

}

function my_set_options( $args ) {

	if ( ! isset( $args[3]['opt_name'], $args[3]['opt_value'] ) ) { return FALSE; }

	update_option( $args[3]['opt_name'], $args[3]['opt_value'] );

	if ( get_option( $args[3]['opt_name'] ) === $args[3]['opt_value'] ) {

		return TRUE;

	} else {

		return FALSE;

	}
}

こんな感じに XML-RPC クライアントからオプションを渡して get_option 等で操作するという単純な処理です。

「取得、設定、削除」と 3 つのメソッドを追加してサーバ側の拡張はお終いです。今回は functions.php に書いていますが、できればプラグイン化して有効化させといたほうが理想だと思います。

ちなみにですが、デフォルトのメソッドでは以下のパラメータを操作できるようです。

software_name
software_version
blog_url
home_url
login_url
admin_url
image_default_link_type
image_default_size
image_default_align
template
stylesheet
post_thumbnail
time_zone
blog_title
blog_tagline
date_format
time_format
users_can_register
thumbnail_size_h
thumbnail_crop
medium_size_w
medium_size_h
large_size_w
large_size_h
default_comment_status
default_ping_status

XML-RPC クライアントの拡張

次に、クライアント側を拡張します。以下の記事で書いたクラスを元にコードを書き足します。

関連記事

WordPressのXML-RPCクライアント自作クラスを改修した

書き足すのは以下のクライアント用メソッドです。

	/*
	 * Usage: $get = $wp->wp_ope_options( array( 'opt_ope' => 'get', 'opt_name' => 'name' );
	 *        $del = $wp->wp_ope_options( array( 'opt_ope' => 'del', 'opt_name' => 'name' );
	 *        $set = $wp->wp_ope_options( array( 'opt_ope' => 'del', 'opt_name' => 'name', 'opt_value' => 'value' );
	 *
	 * wp_options の「取得,削除,設定」操作
	*/
	public function wp_ope_options( $p = FALSE ) {

		if ( ! $p || ! isset( $p['opt_name'], $p['opt_ope'] ) ) { return FALSE; }

		if ( $p['opt_ope'] === 'set' && ! isset( $p['opt_value'] ) ) { return FALSE; }

		// value タイプのデフォルトは 'string'
		if ( $p['opt_ope'] === 'set' && ! isset( $p['opt_type'] ) ) { $p['opt_type'] = 'string'; }

		// 操作するメソッド名を設定
		$xmlrpc_method = 'my.' . $p['opt_ope'] . 'WpOptions';

		// 送信する XML データの作成
		$options = array(
			'opt_name' => new XML_RPC_Value( $p['opt_name'], 'string' )
		);

		// set の場合に value と type を追加
		if ( $p['opt_ope'] === 'set' ) {

			$options['opt_value'] = new XML_RPC_Value( $p['opt_value'], $p['opt_type'] );
		}

		$options = new XML_RPC_Value( $options, 'struct' );

		$xmldata = new XML_RPC_Message(
			$xmlrpc_method,
			array( $this->wp_id, $this->wp_user, $this->wp_pass, $options )
		);

		$result = $this->rpc_send( $xmldata );
		$result = XML_RPC_decode( $result->value() );

		return $result;

	}

こんな感じのコードで、全ての操作をオプションで切り替えるようにまとめてみました。

これを使って早速テストしていきます。実際に DB を触るので念のためバックアップも忘れずに。

XML-RPC で wp_options を操作するテスト

テスト用のクライアントは以下のように書いてみました。ファイル名は仮に xml-conn.php とします。

<?php 

	require_once("class-xmlrpc-wp-client.php");

	$param = array(
		'host' => 'example.jp',
		'port' => '80',
		'path' => '/xmlrpc.php',
		'user' => 'user',
		'pass' => 'password',
	);

	$options = array(
		'opt_ope'   => 'set', /* <get|del|set> */
		'opt_name'  => 'test_option',
		'opt_value' => 'test_value',
		'opt_type'  => 'string' /* <int|string|boolean> */
	);


	$wp     = new WordPressRpc( $param );
	$result = $wp->wp_ope_options( $options );

	var_dump( $result );

?>

$options[‘opt_ope’] に操作内容、$options[‘opt_name’] に操作対象のオプション名を指定します。

$options[‘opt_ope’] が set の場合は、$options[‘opt_value’] と$options[‘opt_type’] も指定する必要があります。

存在しないオプションを GET

# php xml-conn.php
int(0)

オプション名が存在しない場合には 0 が返ります。

オプション名 test_option を SET

# php xml-conn.php
int(1)

オプションの設定に成功すると 1、失敗すると 0 が返ります。mysql を SELECT してみるとちゃんと登録されているのを確認できます。

mysql> SELECT * FROM wp_options WHERE option_name = 'test_option';
+-----------+-------------+--------------+----------+
| option_id | option_name | option_value | autoload |
+-----------+-------------+--------------+----------+
|      5250 | test_option | test_value   | yes      |
+-----------+-------------+--------------+----------+

存在するオプションを GET

# php xml-conn.php
string(10) "test_value"

上記で登録したので、もう一度情報を取得してみます。成功すると設定値が返ってきます。

オプションを DEL

# php xml-conn.php
int(1)

オプションの削除に成功すると 1、失敗すると 0 が返ってきます。

簡単ですがこんな感じにできました。

XML-RPC のセキュリティについて

最後に、おまけ程度ですが WordPress の XML-RPC に関するセキュリティについて。

拡張次第でリモートから何でもできて便利な XML-RPC ですが、セキュリティ機構がパスワード認証だけというのはちょっと危なっかしい感じがしています。

最近では、wp-login.php への総当り攻撃も増えているみたいなので .htacess 等でログインできる対象を絞っている人も多いかと思いますが XML-RPC への対処はあまり見ないです。

wp-login.php の対処だけじゃ不完全なんですよね。これとは別に動くので。

という事で以下のように XML-RPC サーバ側に「接続ホスト制限」を追加してみました。

function add_wp_methods( $methods ) {

	if ( $_SERVER['REMOTE_ADDR'] !== '192.168.0.1' ) {
		add_filter( 'xmlrpc_enabled', '__return_false' );
	}

	$methods['my.getWpOptions'] = 'my_get_options';
	$methods['my.setWpOptions'] = 'my_set_options';
	$methods['my.delWpOptions'] = 'my_del_options';
	return $methods;

}
add_filter( 'xmlrpc_methods', 'add_wp_methods' );

この状態で許可されていないホストからアクセスすると以下のようになります。

# php xml-conn.php
このサイト上では XML-RPC サービスが無効になっています。

アチコチから XML-RPC に接続して操作するという事がなければこれで大体 OK です。ただ、ピンバックも強制的に受け付けなくなるのでそこは注意です。(もしかしたら他にも影響が)

本当は、ピンバックだけは許可したいんだけど当面はこんな感じで。

また何かわかったら別記事で書きたいと思います。

コメント

コメントを残す