WordPressでpingbackを検証できないサイトがある

最近うちのブログにpingbackを飛ばしてきたブログがあってそのブログのpingbackがエラーコード0、エラーメッセージnullで失敗とログに記録されていました。
なんだろうー?とXMLRPCサーバーの処理を追ってみたところ、HEADエレメント内のHTML文法エラーとJavaScriptの問題でした。

HTML文法エラーはそのまんまで <meta property="og:description" content=""説明""/> など普通の文法エラーによる解析失敗。
そしてJavaScriptはpackerで難読化した物がHEAD内にあると動作不良を起こしていました。

pingbackの主な処理はwp-includes/class-wp-xmlrpc-server.phpのfunction pingback_pingで行われます。

<?php
 
public function pingback_ping( $args ) {
    ...省略...
 
    $request = wp_safe_remote_get( $pagelinkedfrom, $http_api_args );
    $remote_source = $remote_source_original = wp_remote_retrieve_body( $request );
 
    if ( ! $remote_source ) {
        return $this->pingback_error( 16, __( 'The source URL does not exist.' ) );
    }
 
    /**
     * Filters the pingback remote source.
     *
     * @since 2.5.0
     *
     * @param string $remote_source Response source for the page linked from.
     * @param string $pagelinkedto  URL of the page linked to.
     */
    $remote_source = apply_filters( 'pre_remote_source', $remote_source, $pagelinkedto );
 
    // Work around bug in strip_tags():
    $remote_source = str_replace( '<!DOC', '<DOC', $remote_source );
    $remote_source = preg_replace( '/[\r\n\t ]+/', ' ', $remote_source ); // normalize spaces
    $remote_source = preg_replace( "/<\/*(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $remote_source );
 
    preg_match( '|<title>([^<]*?)</title>|is', $remote_source, $matchtitle );
    $title = isset( $matchtitle[1] ) ? $matchtitle[1] : '';
    if ( empty( $title ) ) {
        return $this->pingback_error( 32, __( 'We cannot find a title on that page.' ) );
    }
 
    $remote_source = strip_tags( $remote_source, '<a>' ); // just keep the tag we need
 
    $preg_target = preg_quote($pagelinkedto, '|');
 
    foreach ( $p as $para ) {
        if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link?
            preg_match("|<a[^>]+?".$preg_target."[^>]*>([^>]+?)</a>|", $para, $context);
 
            // If the URL isn't in a link context, keep looking
            if ( empty($context) )
                continue;
 
            // We're going to use this fake tag to mark the context in a bit
            // the marker is needed in case the link text appears more than once in the paragraph
            $excerpt = preg_replace('|\</?wpcontext\>|', '', $para);
 
            // prevent really long link text
            if ( strlen($context[1]) > 100 )
                $context[1] = substr($context[1], 0, 100) . '&#8230;';
 
            $marker = '<wpcontext>'.$context[1].'</wpcontext>';    // set up our marker
            $excerpt= str_replace($context[0], $marker, $excerpt); // swap out the link for our marker
            $excerpt = strip_tags($excerpt, '<wpcontext>');        // strip all tags but our context marker
            $excerpt = trim($excerpt);
            $preg_marker = preg_quote($marker, '|');
            $excerpt = preg_replace("|.*?\s(.{0,100}$preg_marker.{0,100})\s.*|s", '$1', $excerpt);
            $excerpt = strip_tags($excerpt); // YES, again, to remove the marker wrapper
            break;
        }
    }
 
    ...省略...
}
 
?>

ここのwp_safe_remote_getでpingback送信元へGETリクエストを送信しHTTPヘッダーとHTMLをダウンロードします。
そして次のwp_remote_retrieve_bodyでHTMLのみのデータを変数へセット。

その後はスペース、改行、エレメントを整理しpreg_match( '|<title>([^<]*?)</title>|is'....で記事タイトルをゲット。
strip_tagsでアンカーを消してexplode( "\n\n", $remote_source );で改行毎に配列に格納します。

後はforeach ($p as $para)で配列の中からpingback送信先URLが含まれる配列を探して、配列内にあるpingback送信先URLの前後の文章を抜粋して終了の流れ。

抜粋処理周りにはフィルターが一切ないので処理の変更ができません。
packerの難読化を使っているどうしようもないサイトからのpingbackへどうしても対応したい・・って事なら処理が開始される前に通るフィルターpre_remote_sourceがあるので、これでscriptタグを全て削除すると良いかもしれません。
 
私的には・・・
packerの難読化のような何にもならない物を使っているサイトは放置しても良いと考えます。
と言うのも、packerには悪いと思いますが、後ろめたいコードを書いている多くのサイトに使われている物ですし、元のコードへ戻すのが非常に簡単で使う意味がほぼ無な物なので。

送信側の方はpingbackの送信に失敗するな?と思ったら自分のブログのコードが正常か確認を。

関連するかもしれない記事



トラックバックURL


スパム対策のためトラックバックURLを動的に生成しています。
生成されるトラックバックURLはコンテンツURLと紐付けされますので、コンテンツURLで指定したサイト以外では使用できませんのでご注意ください。
トラックバックの注意事項などの詳しい説明は About ページを閲覧してください。
「コンテンツURL」を入力し「URL生成」ボタンを押してください。
トラックバックを送る際はあなたの記事やコンテンツにこの記事のURLを書くかリンクしておいてください。
URLがない場合はスパムとして削除され以降の全トラックバックは拒否されます。

コメントを残す

メールアドレスは公開されません、また は必須項目です。
このブログに初めてコメントする方は こちら をご覧ください。


画像認証は待機中です、先にコメント本文を入力して下さい。

コメントを送信しています、しばらくお待ち下さい...
(Akismetスパムデータベース及びブラックリストへの照会を行っています)


キャンセルをした場合でもコメント投稿が完了している場合があります