• 解決済 nikooiy

    (@nikooiy)


    オリジナルテーマを作りながら開発しています。
    何ページが記事を表示する以外に独自のページを作りたいのですが、良い方法はあるでしょうか?

    動的に出力したいページなのでphpでgetを使ったりしたいのですが固定ページだと不可能ではないでしょうか?

    wordpressがおいてあるフォルダに直接ファイルを置いてしまうのでもいいかなとも思うのですが、アップデートする時不安です。
    なにか良い方法はありますか?

7件の返信を表示中 - 1 - 7件目 (全7件中)
  • nobita

    (@nobita)

    動的に出力したいページなのでphpでgetを使ったりしたいのですが固定ページだと不可能ではないでしょうか?

    出来ないことではありません。

    既存のクエリと同じものを使う事はできませんので、GETで送信するクエリ文字列は、プレフィックスを付けるなどすれば、固定ページで受けることはできます。

    固定ページは、WordPressの一部として動作しますので、phpの単一のファイルと同じように扱うと、セキュリティの問題が発生します。

    http://codex.wordpress.org/WordPress_Nonces

    http://codex.wordpress.org/Plugin_API/Filter_Reference/query_vars

    apacheの mod_rewrite の動作

    等 調べて、理解を深めてからカスタマイズするといいと思います。

    PHPは、WordPressの外側に於いても、大きく問題になるようなことはないんじゃないかと思いますので、外側で十分作り混むのと並行して、いろいろ学んでいくといいと思います。

    kjmtsh

    (@kjmtsh)

    「php の get」というのが何かよくわからなかったのですが、やはり、GET リクエストを受け付けるという意味なんですかね。

    ちょっと考えてみましたが、こんなのはどうでしょう?

    add_action('template_include', 'load_other_pages');
    add_filter('query_vars', 'add_extra_pages');
    function load_other_pages($original_template) {
        $directory_path = get_template_directory() . '/';
        $file_name = get_query_var('extra_pages');
        if (!empty($file_name)) {
            if (file_exists($directory_path . $file_name . '.php')) {
                return $directory_path . $file_name . '.php';
            } else {
                return $directory_path . '404.php';
            }
        }
        return $original_template;
    }
    function add_extra_pages($queries) {
        array_push($queries, 'extra_pages');
        return $queries;
    }

    http://example.com/?extra_pages=file_name としてアクセスすると、file_name.php が読み込まれます。テンプレート・ディレクトリにしてありますが、どこに置いても使えます。file_name.php は通常の PHP ファイルとして作成することができます。WordPress と関係のない PHP ファイルとくらべた利点 (?) は、次のとおりです。

    • 形式上、WordPress から見ると、テンプレートファイルである
    • だから、メインクエリが存在する (使う、使わないは自由)
    • メインクエリを利用する場合は、pre_get_posts などのフックも使える
    • WordPress の関数が使える (使わなくてもよい)
    • WordPress の変数、定数が使えるので、WordPress 以外からのアクセスを判定する材料がそろっている

    'extra_pages/(.+?)$' => 'index.php?extra_pages=$matches[1]'

    のような rewrite rule を設定すると、http://example.com/extra_pages/file_name/ でアクセスできます。?some_var=some_value のようなクエリも指定できます。

    nobita

    (@nobita)

    @kjmtshさん

    このままだと、ディレクトリトラバーサルができてしまいませんか?

    トピック投稿者 nikooiy

    (@nikooiy)

    みなさまありがとうございました。

    おかげ様で解決しました。

    @kjmtshさまのコードを参考にGetを使えるように以下の通りに改造しました。
    ありがとうございました。

    add_action('template_include', 'load_other_pages');
    add_filter('query_vars', 'add_extra_pages');
    
    function load_other_pages($original_template) {
    
        $directory_path = get_template_directory() . '/';
        $file_name = get_query_var('extra_pages');
    
    	$id=get_query_var('id');
    	if(!$id==""){
    	$_GET['id']=$id;
    	}
    
    	if (!empty($file_name)) {
            if (file_exists($directory_path . $file_name . '.php')) {
    
                return $directory_path . $file_name . '.php';
    
            } else {
                return $directory_path . '404.php';
            }
        }
        return $original_template;
    }
    function add_extra_pages($queries) {
    
        array_push($queries, 'extra_pages');
        array_push($queries, 'id');	
    
        return $queries;
    }
    nobita

    (@nobita)

    @nikooiyさん

    脆弱性があるので、このまま解決せずに、ちょっとこのスレを継続して見てください

    @kjmtshさん

    問題ではないかと思われる点

    $file_name = get_query_var('extra_pages');

    をサニタイズしていないので、

    ?page_id=25&extra_pages=../raindrops/index

    といったクエリが可能に見えます。

    if (file_exists($directory_path . $file_name . '.php')) {

    このようなクエリの場合は、上のチェックを通過しますので、外部の誰でも、クエリを送ることが出来るので、可能性は低いと思いますがよろしくないのではないかと思います。

    今のところ、思い付きでは、

    $file_name = esc_html( basename( $file_name ) );

    訂正

    $file_name = sanitize_file_name( $file_name );

    等とすれば、いいかもと思いますが、どうでしょうか?

    kjmtsh

    (@kjmtsh)

    おお、nobita さん、ありがとうございます。さすが、頼りになりますね。

    ページ数は限られたもののようですから、念のため、合わせ技で、ファイル名決め打ちにして、他は受け付けないというのはどうでしょう? sanitize_file_name() を使うと、ファイル名に使えない文字が出てきますので、ご注意を。nikooiy さん、読んでくれるかなぁ。

    $file_name = sanitize_file_name(get_query_var('extra_pages'));
    switch ($file_name) {
    	case 'page1':
    		return $pagepath . 'page1.php';
    		break;
    	case 'page2':
    		return $pagepath . 'page2.php';
    		break;
    	default:
    		return $pagepath . '404.php';
    		break;
    }
    nobita

    (@nobita)

    @kjmtshさん 返信ありがとうございます

    @nikooiy さんに届いているといいですね

7件の返信を表示中 - 1 - 7件目 (全7件中)
  • トピック「wordpressで自作のページを作りたい。」には新たに返信することはできません。