忍び歩く男 - SLYWALKER

大阪のこっそりPHPer

cURL関数で3つのハードルを乗り越えて投稿する

cURL関数を勉強してみた。
お題は

  • ベーシック認証
  • ログイン(クッキーを使ってセッション保持)
  • トークン

自分で作ったサイトに投稿してみた。
試行錯誤の末、やっとできた。

注意点

  • クッキーファイルは、絶対パス指定しないと、手の届かないところに作られてしまう。
  • 当然そこが書き込み不可ならエラーになる。
  • あらかじめファイルを作成していないとエラーになる。
  • ファイル投稿するファイルも絶対パスで。

とりあえず、クッキーが何とかなれば、セッション保持も可能になるので、あとはなんとかなるレベル。
いろんなサイトへの対応できると思うんだが・・・

サンプルコード

投稿後の成功確認とか、省いちゃってますが・・・

<?php
$curl = new myCurl;

// ベーシック認証用 user pass
$curl->setUserPass('user:pass');

// ログイン画面でトークン取得
$params = array(
    'url' => 'http://target-domain/login',
    'regix' => '/name=\"data\[_Token\]\[key\]\"  value=\"([0-9a-z]+)\"/',
);
$curl->token($params);
$token = $curl->getToken();

// ログイン
$params = array(
    'url' => 'http://target-domain/login',
    'http' => array(
        'data[_Token][key]' => $token,
        'username' => 'your_username',
        'password' => 'your_password',
    ),
);
$curl->login($params);

// 記事投稿画面でトークン取得
$params = array(
    'url' => 'http://target-domain/posts/add',
    'regix' => '/name=\"data\[_Token\]\[key\]\"  value=\"([0-9a-z]+)\"/',
);
$curl->token($params);
$token = $curl->getToken();

// 記事投稿
$params = array(
    'url' => 'http://target-domain/posts/add',
    'http' => array(
        'data[_Token][key]' => $token,
        'data[Post][title]' => 'テストタイトル',
        'data[Post][body]' => 'テスト本文テスト本文テスト本文テスト本文テスト本文テスト本文テスト本文',
        'image' => '@'.realpath('sample.jpg'), // ファイルは絶対パスを指定
    ),
);
echo $curl->post($params);

class myCurl {
    var $cookie = 'cookie.txt';
    var $userPass = '';
    var $agent = '';
    var $token = '';

    function __construct()
    {
        $this->agent = $_SERVER['HTTP_USER_AGENT'];
        // cookieファイルには、絶対パスを指定
        $this->cookie = dirname(__FILE__).DIRECTORY_SEPARATOR.$this->cookie;
        // ファイルがなければ作成
        touch($this->cookie);
    }

    function setUserPass($str)
    {
        $this->userPass = $str;
    }
    
    function getToken()
    {
        return $this->token;
    }

    function token($params)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $params['url']);
        curl_setopt($ch, CURLOPT_USERAGENT, $this->agent);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        // Cookie
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie);
        // BasicAuth
        curl_setopt($ch, CURLOPT_USERPWD, $this->userPass);
        $output = curl_exec($ch);
        curl_close($ch);
        preg_match($params['regix'], $output, $match);
        if (!empty($match[1])) {
            $this->token = $match[1];
        } else {
            throw new Exception("tokenが取得できません $url, $php_errormsg");
            return false;
        }
        if ($output) {
            return $output;
        } else {
            throw new Exception("ページ取得失敗, $php_errormsg");
            return false;
        }
    }

    function login($params)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $params['url']);
        curl_setopt($ch, CURLOPT_USERAGENT, $this->agent);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        // Cookie
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie);
        // Post
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params['http']);
        // BasicAuth
        curl_setopt($ch, CURLOPT_USERPWD, $this->userPass);
        
        $output = curl_exec($ch);
        curl_close($ch);
        if ($output) {
            return $output;
        } else {
            throw new Exception("ログイン失敗, $php_errormsg");
            return false;
        }
    }

    function post($params)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $params['url']);
        curl_setopt($ch, CURLOPT_USERAGENT, $this->agent);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        // Cookie
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie);
        curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie);
        // Post
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params['http']);
        // BasicAuth
        curl_setopt($ch, CURLOPT_USERPWD, $this->userPass);
        
        $output = curl_exec($ch);
        curl_close($ch);
        if ($output) {
            return $output;
        } else {
            throw new Exception("書き込み失敗, $php_errormsg");
            return false;
        }
    }
}
?>

参考
http://jp2.php.net/curl