basyura's blog

あしたになったらほんきだす。

hatena.vim を読む その9

"  ユーザIDを引数に取るログイン関数定義
function! HatenaLogin(user)
    " ユーザIDを保持
    let hatena_user=a:user
    " URL とユーザを取得
    let [base_url, user] = s:GetBaseURLAndUser(hatena_user)
    " テンプファイルを生成
    let tmpfile = tempname()

    " クッキーを保存するファイル
    if has('win32')
        " windows の場合はバックスラッシュで cookies フォルダを生成
        let cookie_file = g:hatena_base_dir . '\cookies\' . user
    else
        " windows 以外の場合はスラッシュで cookies フォルダを生成
        " windows もスラッシュでいいと思うんだが?
        let cookie_file = g:hatena_base_dir . '/cookies/' . user
    endif

    " クッキーがある場合はクッキーでログインを試みる
    if filereadable(cookie_file)
        "
        " curl を使ってヘッダ取得
        "
        " curl -k --silent http://d.hatena.ne.jp/basyura/edit 
        "      -b "/Users/basyrua/.vim/plugin/hatena/cookies/basyura" 
        "      -D - -o tmpfile
        "
        "  -k       セキュアじゃないアクセスを許可する
        "  --silent メッセージ表示しない
        "  -b       cookie の指定
        "  -D       指定したファイルにプロトコルヘッダを書き込む
        "           引数 - はそのまま標準出力へ?
        "  -o       出力をファイルへ書き込む
        "
        let reply_header = system(s:curl_cmd . ' ' . base_url . user 
                . '/edit -b "' . cookie_file . '" -D - -o ' . tmpfile)
        "
        " ログイン済みの場合の reply_header
        "     HTTP/1.1 200 OK
        "     Date: Wed, 15 Apr 2009 06:06:11 GMT
        "     Server: Apache
        "     Content-Type: text/html; charset=euc-jp
        "     Vary: Accept-Encoding
        "     Transfer-Encoding: chunked
        "
        " ログインしていない場合の reply_header
        "    HTTP/1.1 302 Moved
        "    Date: Wed, 15 Apr 2009 06:49:31 GMT
        "    Server: Apache
        "    Location: /basyura/
        "    Content-Type: text/html; charset=ISO-8859-1
        "    Set-Cookie: 長いので省略
        "    Vary: Accept-Encoding
        "    Transfer-Encoding: chunked
        " 
        " あっているのか?

        " ヘッダの location が https な場合
        if reply_header =~? 'Location: https:'
            " httpsなグループへ
            " base_url の http を https に変更
            let base_url = substitute(base_url, '^http', 'https', '')
            " ヘッダを取り直す
            let reply_header = system(s:curl_cmd . ' ' . base_url . user 
                . '/edit -b "' . cookie_file . '" -D - -o ' . tmpfile)
        endif
        " Location が無い場合はログイン済みと判定する
        if reply_header !~? 'Location:'
            echo 'ログインしてます'
            " url user クッキーファイルを返却
            return [base_url, user, cookie_file]
        else
            ログインしていない場合はクッキーファイルを削除
            call delete(cookie_file)
        endif
    endif

    " パスワードでログイン
    let password = inputsecret('Password: ')
    " 入力されたパスワードの長さが 0 の場合
    if !len(password)
        echo 'キャンセルしました'
        " 空配列を返却
        return []
    endif
    "
    " curl -k --silent https://www.hatena.ne.jp/login
    "         -d name=basyura -d password=xxxxxxxxx -d mode=enter 
    "         -c "/Users/basyura/.vim/plugin/hatena/cookies/basyura"
    "
    "  -k       セキュアじゃないアクセスを許可する
    "  --silent メッセージ表示しない
    "  -d       指定したデータを POST リクエストとして HTTP サーバに送信する
    "  -c       処理の完了後にすべてのクッキーを書き込むファイルを指定しする。
    "           -b/--cookie で指定したファイルから既に読み込まれたすべての
    "           クッキーとリモートのサーバから受け取った
    "           すべてのクッキーが書き込まれる。
    "
    let content = system(s:curl_cmd . ' ' . s:hatena_login_url 
            . ' -d name=' . user . ' -d password=' . password 
            . ' -d mode=enter -c "' . cookie_file . '"')
    "
    " ログイン画面の HTML が content に格納される

    " 添付ファイルを削除する
    call delete(tmpfile)
    " エラーエッセージが表示されていなければログイン済みと判定する
    if content !~ '<div [^>]*class="error-message"'
        echo 'ログインしました'
        return [base_url, user, cookie_file]
    else
        " ログインエラーと判定
        echoerr 'ログインに失敗しました'
        return []
    endif
endfunction

tempname

tempname()
        結果は文字列で、存在しないファイルのファイル名を示す。これはテ
        ンポラリファイルの名前として使用可能である。少なくとも連続26回
        の呼出しまでは違う名前を生成することが保証される。例: >
            :let tmpfile = tempname()
            :exe "redir > " . tmpfile

filereaable

filereadable({file})
        結果は数値で、{file}というファイルが存在し、読みこむことが可能
        ならばTRUEとなる。ファイル{file}が存在しないかディレクトリだっ
        た場合には、結果はFALSEとなる。引数{file}は文字列として使えれ

参考:http://www.hcn.zaq.ne.jp/___/unix/curl_manpage.html