ssh接続したリモートサーバの出力を手元Macのクリップボードに送る – Glide Note – グライドノートssh先screenのペーストバッファをクリップボードに貼り付ける – Keep It Simple, StupidでRemoteForwardを使って、リモートのテキストをローカルに送って、クリップボードにコピーする方法が紹介されているが、リモートのURLをブラウザで開きたいことがよくあるので、それもできるようにしてみた。

Macでの話だけど、pbcopyの部分や、サーバを立ち上げるために使っているLaunchAgentsの部分を変更すれば、windowsでもいけるはず。

仕組み

ローカルにPHPのビルトインサーバを使って、2224ポートでサーバを立ち上げる。(2224ポートは参照先に従った)

サーバにapacheを使うとpbcopyが権限などの理由?でうまく行かなかったので、PHPのビルトインサーバをLaunchAgentsで立ち上げることにした。

次にRemoteForwardを使って、リモートサーバにsshする。

$ ssh -R 2224:127.0.0.1:2224 remote.com

こうすると、リモートサーバの2224ポート(前の2224)への接続がローカルの2224ポート(後ろの2224)につながる。

リモート上で自分自身に向かって

$ curl -n -d “url=http://example.com” “http://localhost:2224/browser”

などのリクエストを送る。-nはBasic認証。

するとローカルサーバにリクエストが来るので、ローカル側でexample.comをブラウザで立ち上げる処理を書いておく。

pbcopyの場合も同じような感じ。

使い方

git cloneする。

Library/LaunchAgents/rfrouter.plistというファイルを~/Library/LaunchAgents/に絶対パスでシンボリックリンクを貼る。

~/src/github.com/tmsanrinsha/remote2localにgit cloneした場合はこんな感じ。

ln -s ~/src/github.com/tmsanrinsha/remote2local/router.php ~/Library/LaunchAgents

launchctl load ~/Library/LaunchAgents/rfrouter.plistでサーバを立ち上げる。次回からはログイン時に自動的に立ち上がるようになる。

止めたい場合はlanchctl unloadする。設定を変更した時はlanchctl unloadしてからlanchctl loadする。

gitのルートディレクトリに移動して、Basic認証用のファイルを作る

$ htpasswd -mc .htpasswd <username>
  
$ chmod 600 .htpasswd

-mは暗号化にMD5を使うオプション(version 2.2.18からはこれがデフォルト)。-cは新規にファイルを作るときのオプション。(htpasswd – Manage user files for basic authentication – Apache HTTP Server Version 2.4)

パスワード用のランダムな文字列がほしいなら

$ brew install pwgen
  
$ pwgen -y 8 1

などと打つと記号入り(-yオプション)のランダムな8文字が1つ手に入る。

素のpbcopyは日本語のコピーがうまくいかないことがあるので、router.phpからは、付属のbin/pbcopyを参照している。内部でnkfを使っているのでインストールする

$ brew install nkf

コードはUTF-8でpbcopyできるようにする – by edvakf in hatenaを元にした。

ローカルからローカルへのリクエストがうまくいくか試してみる。~/.netrcにhtpasswdで設定した値を書く。

machine localhost login <usrname> password <password> [/bash]
  
パーミッションも600に変更しておく。
  
付属のbin以下のファイルにPATHが通った状態にして、
  
[bash]
  
$ date | rfpbcopy

としてコピーできているか

$ rfbrowser &#8216;http://t.co&#8217;

でブラウザが開くかを確かめる。

ローカルで確認ができたら、次はリモート。

毎回-Rで指定するのは面倒なので、~/.ssh/configに

Host remote.com
      
RemoteForward 2224 127.0.0.1:2224

のような感じで設定する。sshで接続

$ ssh remote.com

して、.netrcに設定。ローカルでした確認を行ってみて、

$ date | rfpbcopy
  
$ rfbrowser &#8216;http://t.co&#8217;

成功すればOK。

連携

vim-fakeclip

クリップボードがないときにpbcopyとかxclipとかなど駆使してクリップボードにコピーするVimプラグイン。

そのままだと、任意のコピー用のコマンドを設定できなかったので、フォークしてg:fakeclip_write_clipboard_commandをという設定を加えてプルリクを送ってみたけどマージされない。

フォーク版

こんな風に設定しておく

&#8221; clipboardが使えない、もしくはsshで接続している時にvim-fakeclipを使う。
  
if !has(&#8216;clipboard&#8217;) || $SSH_CLIENT != &#8221;
      
NeoBundle &#8216;tmsanrinsha/vim-fakeclip&#8217;
  
endif
  
&#8221; +clipboardでもfakeclipのキーマッピングを使う
  
let g:fakeclip\_provide\_provide\_key\_mapping = 1
  
&#8221; クリップボードコピーのコマンドにrfpbcopyを使う
  
let g:fakeclip\_write\_clipboard_command = &#8216;rfpbcopy&#8217;

open-browser.vim

url上で、gxと打つと、そのURLをブラウザで開いてくれたり、検索してくれたりするプラグイン。

以下のように設定しておく。

NeoBundleLazy &#8216;tyru/open-browser.vim&#8217;, {
      
\ &#8216;autoload&#8217;:{
      
\ &#8216;mappings&#8217;:[
      
\ &#8216;<Plug>(openbrowser-&#8216;
      
\ ]
      
\ }
      
\ }
  
let g:netrw_nogx = 1 &#8221; disable netrw&#8217;s gx mapping.
  
if $SSH_CLIENT != &#8221;
      
let g:openbrowser\_browser\_commands = [
          
\ {
          
\ &#8220;name&#8221;: &#8220;rfbrowser&#8221;,
          
\ &#8220;args&#8221;: &#8220;rfbrowser {uri}&#8221;
          
\ }
          
\ ]
  
endif

nmap gx <Plug>(openbrowser-smart-search)
  
vmap gx <Plug>(openbrowser-smart-search)

vim-fugitive

gitを扱うプラグイン。

:Gbrowseとうつと、開いているファイルをgit-web–browseを使って、Github上で開くとhelpに書いてあるけど、ソース見るとgit-web–browseは使ってないような気がする。実際.gitconfig

[web]
      
browser = rfbrowser
  
[browser &#8220;rfbrowser&#8221;]
      
cmd = rfbrowser

のように設定して

git web&#8211;browse http://github.com

とうつと、ブラウザを開いてくれるが、:Gbrowseでは開いてくれない。ソース見ると

if a:bang
    
if has(&#8216;clipboard&#8217;)
      
let @* = url
    
endif
    
return &#8216;echomsg &#8216;.string(url)
  
elseif exists(&#8216;:Browse&#8217;) == 2
    
return &#8216;echomsg a&#8217;.string(url).&#8217;|Browse &#8216;.url
  
else
    
return &#8216;echomsg &#8216;.string(url).&#8217;|call netrw#NetrwBrowseX(&#8216;.string(url).&#8217;, 0)&#8217;
  
endif

となっていて、:Browseコマンドはないので、次のnetrw#NetrwBrowseXが実行される。

.vimrc

let g:netrw\_browsex\_viewer = &#8216;rfbrowser&#8217;

と書けば解決した。

補足

LaunchDaemons

以下が参考になった。

Salted md5

上によると単にパスワードをハッシュ値に変換して保存すると、あらかじめ作られた平文とハッシュ値の表から複合化されてしまう。そこで、パスワードにランダムな文字列(salt)を加えてからハッシュ化して、ハッシュ値とsaltの値を保存しておくと復号化されにくくなるとのこと。レインボーテーブル – Wikipediaも参照。

で、今回パスワードをsalted md5で.htpasswdに保存しているから、送信されてきたパスワードを.htpasswdにあるsaltを加えてからmd5で変換して、比較しなくてならない。Password Formats – Apache HTTP Server Version 2.4によると、1000回md5でハッシュ化しているらしい。ソースコードは[Apache-SVN] Contents of /apr/apr/trunk/crypto/apr_md5.cにある。 このアルゴリズムをPHPで書いたコードがapache – how to edit .htpasswd using php? – Stack Overflowにあるので、そのcrypt_apr1_md5()という関数をrouter.phpで使って、パスワードの比較を行っている。