WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

Ruby で bash の特殊文字をエスケープする

本日は Ruby のちょっとしたユーティリティー関数のご紹介です。

Web アプリケーションを作っていると、ときには入力されたデータを引き渡して外部コマンドを実行したいときがあると思います。そのときに重要なのが、特殊記号のエスケープです。これを忘れると、 Web サーバー上で任意コマンドを実行されてしまう可能性もあります。

そこで、 bash が特殊文字として認識する文字をエスケープする Ruby の関数を作ってみました。信頼できない文字列を外部コマンドに渡す際は、ぜひご活用ください。ついでなので、先頭のハイフン(オプションとして解釈されてしまうおそれがある)やコントロールキャラクタ(空白・タブを除く)を削除する機能も付けています。

ちなみに、エスケープが必要な記号は、すべての記号を名前に含むファイルを作って、 bash にタブ補完させて調べました。まあ、これなら間違いはないでしょう(笑)。

それでは、さっそくソースコードです。

def shellesc(str, opt = {})
  str = str.dup
  if opt[:erace]
    opt[:erace] = [opt[:erace]] unless Array === opt[:erace]
    opt[:erace].each do |i|
      case i
      when :ctrl   then str.gsub!(/[\x00-\x08\x0a-\x1f\x7f]/, '')
      when :hyphen then str.gsub!(/^-+/, '')
      else              str.gsub!(i, '')
      end
    end
  end
  str.gsub!(/[\!\"\$\&\'\(\)\*\,\:\;\<\=\>\?\[\\\]\^\`\{\|\}\t ]/, '\\\\\\&')
  str
end

# 呼び出し例
shellesc('; rm *') # => '\;\ rm\ \*'
shellesc('--force', :erace => [:hyphen]) # => 'force'
shellesc("abc\ndef", :erace => [:ctrl]) # => 'abcdef'
shellesc("abc", :erace => [/b/]) # => 'ac'

ソース後半の呼び出し例を見ていただければ使い方は一目瞭然かと思います。基本的に第一引数にエスケープ前の文字列を渡して呼び出せば、エスケープ後の文字列を返します。

第二引数はオプションの Hash ですが、現在は :escape しか指定できません。 :escape は削除する文字の指定で、以下の値を配列で複数指定できます。

:ctrl
空白、タブ以外の非表示文字を削除します。
:hyphen
先頭のハイフンを削除します。
正規表現・文字列
マッチする文字列を削除します。

使い方はこれだけです。簡単ですね。

なお、これでエスケープした文字列をダブルクォートなどで囲うと、二重エスケープ(エスケープ用のバックスラッシュがゴミとして残る)になってしまうのでご注意ください。逆に、ダブルクォートで囲うことを前提に $, ¥, ` のみをエスケープするという手もあるのですが、その出力をさらにダブルクォートで囲うとエスケープが剥がれて危険なので止めました。

一応、これだけやれば十分かなと思っているのですが、もし問題点などお気づきでしたら、ぜひご指摘ください。可能な限り速やかに修正したいと思います。

ではでは、本日はこれにて。

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles