サポート » プラグイン » オリジナル画像アップローダプラグインを作成したい

  • 解決済 tk9

    (@tk9)


    よろしくお願いします。

    ただいま、プラグインを自作してオリジナルの画像アップローダを作成しています。
    最初にPHPで作成してプラグイン化する流れで作成しています。
    PHPでは問題なかったのですが、wordpressのプラグイン化するとエラーがでてアップロードができません。

    ソースコードはこちらを参考にしています。
    http://the-zombis.sakura.ne.jp/wp/?p=1252

    プラグインにして動くか確認してからカスタムしようと思っているのですが、動作エラーの原因がわかりません。
    どなたか教えていただけないでしょうか?
    ディレクトリ構成
    upload.php
    imageフォルダ

    下記にソース記載します。

    function my_form_setting(){
    	$dir="image/";
    	if($_SERVER["REQUEST_METHOD"]=="POST" && !empty ($_POST)){
    	    $action=$_POST["action"];
    	    if($action=="upload"){
    	       $pattern="/^[a-z0-9A-Z\-_]+\.[a-zA-Z]{3}$/";
    	    $upfile=$_FILES["image"]["name"];
    	    if(!empty ($upfile)){
    	        if(!preg_match($pattern,$upfile)){
    	           $er["jp"]="日本語はダメ";
    	        }
    	        $ext=substr($upfile,-3);
    	        if($ext!="jpg" && $ext!="png"){
    	            $er["image"]="拡張子はjpgとpngのみです。";
    	        }else{
    	          //ファイル重複チェック
    	            $filelist=scandir($dir);
    	        foreach($filelist as $file){
    	        }
    	        }
    	    }else{
    	        echo "ファイルをアップしてください";
    	    }
    	    if(empty ($er)){
    	       move_uploaded_file($_FILES["image"]["tmp_name"],"image/".$upfile);
    	    }
    	       //--------------------------------------
    	    }elseif($action=="delete"){
    	        if(!empty ($_POST["deletefile"])){
    	            $deletefiles=$_POST["deletefile"];
    	           //
    	           foreach($deletefiles as $dfile){
    	               if(file_exists($dir.$dfile)){
    	                   unlink($dir.$dfile);
    	               }
    	           }
    	            }else{
    	                $error="何もチェックされてません";
    	            }
    	        }
    	}

    ファイルをアップする前はエラーなしで正常です。
    ファイルをアップすると下記のエラーがでてきます。
    Warning: scandir(image/) [function.scandir]: failed to open dir: No such file or directory in on line 47

    Warning: scandir() [function.scandir]: (errno 2): No such file or directory in on line 47

    Warning: Invalid argument supplied for foreach() in on line 48

    Warning: move_uploaded_file(image/images.jpg) [function.move-uploaded-file]: failed to open stream: No such file or directory in on line 55

    Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move ‘/tmp/phpRRqIYi’ to ‘image/images.jpg’ in on line 55

    エラー内容をみながらscandirとmove_uploaded_fileがエラーの原因っぽいと思っているのですが、具体的なエラー内容がわかりません。

    ご教授いただけますと幸いです。

10件の返信を表示中 - 1 - 10件目 (全10件中)
  • こんばんは。

    “image/”ディレクトリがオープンできていないようです。

    Warning: scandir(image/) [function.scandir]: failed to open dir: No such file or directory in on line 47

    scandirは成功した場合にファイル名の配列、失敗した場合に FALSE を返します。
    そのため、$filelistの判定が必要です。

    scandirの使用例を見ると”image/”の「/」がありません。
    $dir にファイル名を結合している様子もないため、「/」は不要ではないかと思います。

    トピック投稿者 tk9

    (@tk9)

    shirakobato様

    アドバイスありがとうございます。
    さっそく試してみました。images/の「/」が不要とのことで、まず何カ所あるかを探して
    ひとつずつ消してトライ&エラーを試してみました。
    下記に詳細まとめます。

    image/の箇所は2カ所でした。
    $dir=”image/”;

    if(empty ($er)){
    move_uploaded_file($_FILES[“image”][“tmp_name”],”image/”.$upfile);
    }

    一つずつ消してトライしてみましたが結果はエラーでした。

    ですが、エラーメッセージがこのようにかわっていました。
    Warning: scandir(image) [function.scandir]: failed to open dir: No such file or directory in on line 47

    Warning: scandir() [function.scandir]: (errno 2): No such file or directory in on line 47

    Warning: Invalid argument supplied for foreach() in on line 48

    うーん。どういうことでしょうか?

    ちなみに、imageフォルダのパーミッションを「777」にして書き込みOKなどの状態にしてもだめでした。

    まずは$filelistの戻り値がFALSEでないことを確認しましょう。
    手動でimageディレクトリを削除した場合の処理のためにもエラー処理は必要です。
    エラーの場合はエラー復帰するか、imageディレクトリを作成する処理が必要と思います。
    mkdirでディレクトリが作成できます。

    おそらくimageディレクトリの場所が表示URL配下になっているのでしょう。
    $dirの内容を/からのパスにして、どのURLから実行しても固定パスになるようにする必要があると思います。
    プラグインディレクトリの取得にはplugin_dir_pathが使用できると思います。

    move_uploaded_file($_FILES[“image”][“tmp_name”],”image/”.$upfile);

    こちらは「/」が必要です。
    エラーが消えたのは、imageディレクトリ配下ではなく、「imageimages.jpg」というファイル名で処理を行ったためです。

    トピック投稿者 tk9

    (@tk9)

    shirakobato様
    たびたび、ありがとうございますー。
    >まずは$filelistの戻り値がFALSEでないことを確認しましょう。
    すいません、確認方法がわかりません。。。
    どのようにして確認すればいいのでしょうか?

    また、教えていただいたplugin_dir_pathでパスの指定を行い、echoで表示させてみました。
    下記ソースコードです。
    $dir = plugin_dir_path( __FILE__ ) . image;
    echoの結果
    home/users/2/アカウントネーム/web/ドメイン/demo/wp/wp-content/plugins/image-upper02/image

    ※サーバ契約アカウントとドメインはふせさせてください。

    echoの結果を見るとパスの指定は間違いないようで、エラーがでなくなりました。

    ただ、move_uploaded_file($_FILES[“image”][“tmp_name”],”image/”.$upfile);にスラッシュを入れるとまたエラーがでてきます。

    Warning: move_uploaded_file(image/images.jpg) [function.move-uploaded-file]: failed to open stream: No such file or directory in on line 53

    Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move ‘/tmp/php5egSxf’ to ‘image/images.jpg’ in on line 53

    なんどもすいません。
    おかげでがんばれてます。

    トピック投稿者 tk9

    (@tk9)

    shirakobato様

    解決しました。
    どなたかの参考になればと思いますので詳細を記載しておきます。
    shirakobato様のいうとおりディレクトリパスが問題でした。

    なので、シンプルにimageフォルダを消してプラグイン直下になるように
    $dir = plugin_dir_path(__FILE__);
    に変更。

    その後、move_uploaded_file($_FILES[“image”][“tmp_name”],$dir.$upfile)
    に変更。

    この方法で無事にアップロードできましたー。
    本当にありがとうございます。

    ただ、最後にもうひとつだけお聞きしたいです。
    やはり、imageフォルダを作ってそこにまとめたいのですが、どのように記載しればいいのでしょうか?
    PHPでの階層を指定する方法がちょっとわからず。。。

    こんにちは

    余計なおせっかいかもしれませんが、このコードだと、第三者からのアップロードリクエストも受け入れてしまうことはありませんか?

    http://codex.wordpress.org/Function_Reference/wp_handle_upload

    http://codex.wordpress.org/Function_Reference/wp_verify_nonce

    あたりを、一読お勧めします

    トピック投稿者 tk9

    (@tk9)

    すいません。未解決に訂正いたします。

    nobita様

    アドバイスありがとうございます。おせっかいだなんてとんでもない!

    脆弱性ががあるのですね。それはこわいです。
    教えていただいたリンク先を拝見したところ
    wp_handle_uploadとwp_verify_nonceというのがあるんですね。
    リファレンスをみましたがよく意味がわかりません。。。

    どうしたらいいのでしょうか?

    ちなみにwordpressをログアウトしてURLを直打ちしたところ、
    Fatal error: Call to undefined function add_action() in on line 30
    とでてきました。

    line 30は add_action(‘admin_menu’,’image_upper_menu’);

    と記載されているところですね。

    うーん、ログインして動作チェックすると動いているのですがなぜここがエラーなのか不思議です。

    ちょっと、教えていただきたいことをまとめます!

    1.画像のアップロード先を下記にしたいです。
     プラグインディレクトリ>image
     試したこと→$dir = plugin_dir_path(__FILE__).’image’;
     結果→エラーメッセージはでないがアップロードもされず。;

    2.nobita様のwp_handle_uploadとwp_verify_nonceの使い方がわかりません!

    よろしくお願いします。

    例えば、tk9さんのコードを簡略化して

    WordPressのアップロードディレクトリにアップロードするような関数を書くと、

    function my_form_setting(){
    	$dir="image/";
    	if($_SERVER["REQUEST_METHOD"]=="POST" && !empty ($_POST)){
    	    $action=$_POST["action"];
    	    if($action=="upload"){
    	    	$upfile=$_FILES["image"]["name"];
    			$dir = wp_upload_dir();
    
    		 	if ( move_uploaded_file($_FILES["image"]["tmp_name"], $dir['path']. '/'. $upfile) ){
    				return true;
    			}
    		}
    		return false;
    	}
    }

    こんな感じになりますよね。プラグインファイルとして動作を確認すれば、たぶんアップロードはできると思いますが、

    これで、何が危険なのかというと、

    <form enctype="multipart/form-data" action="tk9さんのブログURL" method="POST">
    	<input name="image" type="file">
    	<input type="submit" value="upload" name="action" class="button-primary">
    </form>

    というフォームを書いて、ファイルをアップロードすると、誰でも、いつでも、tk9さんのブログのアップロードディレクトリに、ファイルをアップロードできてしまうためです。

    ファイルのアップロードは、ワードプレスのIDやパスワードを登録している人でも、比較的高い権限を持っている人しか使えない機能です。

    wp_handle_uploadとwp_verify_nonceの使い方がわかりません

    教えてあげたいのですが、安全にアップロードできるようになる道筋を簡単に示すことは、私には困難です。よくわからないようなら、プラグインなどを探してみたほうが早道なのではないかと思います。

    こんばんは。

    >まずは$filelistの戻り値がFALSEでないことを確認しましょう。
    すいません、確認方法がわかりません。。。
    どのようにして確認すればいいのでしょうか?

    以下をイメージしています。

    $filelist=scandir($dir);
    if ($filelist) {
        ディレクトリが存在するためアップロード処理
    }
    else {
        ディレクトリが存在しないため、エラー処理
    }

    1.画像のアップロード先を下記にしたいです。
     プラグインディレクトリ>image
     試したこと→$dir = plugin_dir_path(__FILE__).’image’;
     結果→エラーメッセージはでないがアップロードもされず。;

    $dir の内容は「home/users/2/アカウントネーム/web/ドメイン/demo/wp/wp-content/plugins/image-upper02/image」のようなので問題ないと思います。
    $dir の末尾に「/」がないため、$dir と $upfileの間に「/」をつける必要があります。
    以下のようにしてもアップロードできませんか?
    move_uploaded_file($_FILES["image"]["tmp_name"],$dir.'/'.$upfile);

    nobitaさんが心配される点はもっともです。
    今回のプラグインを一般公開する予定ならば仕様から見直す必要があると思います。
    特定のユーザだけに公開する場合は、ログイン状態やロールによる制限の他、IPアドレスによるアクセス制限も一つの方法です。
    それらを考慮しない状態では悪意を持つ第三者に細工されたjpgを置かれ、他のユーザに迷惑をかける可能性があることを忠告しておきます。
    (ディレクトリパスを見ると、共用サーバですよね?)

    トピック投稿者 tk9

    (@tk9)

    お返事遅くなり申し訳ないです。
    なんとか一段楽してきたので、あとは自力でがんばってみます。

    shirakobato様
    おっしゃる方法でエラーをチェックしましたところ問題なくscandirでtrueがかえってきました。
    $filelist=scandir($dir);
    if ($filelist) {
    echo fine;
    }
    else {
    echo erroer;
    }
    結果はfineでしたので問題ないようでした。
    次に、
    move_uploaded_file($_FILES[“image”][“tmp_name”],$dir.’/’.$upfile);
    でimageに画像を保存できました。
    これ以上みなさまのお手をわずらわせるのは恐縮ですので、いったん閉めて自力でがんばってみます。

    shirakobato様
    nobita様
    セキュリティの面については、了解いたしました。
    深い認識ができたとはいえませんが、このままでは悪意ある第三者からもアクセスできてしまういう認識です。

    一般公開予定などはないですが、危険はさけておきたいので後々に対処法を考えたいと思います。

    お二人ともご丁寧に助けていただいてありがとうございました。

    またご縁があればよろしくお願いいたします。
    こちらのトピックは解決済みとさせていただきます。

10件の返信を表示中 - 1 - 10件目 (全10件中)
  • トピック「オリジナル画像アップローダプラグインを作成したい」には新たに返信することはできません。