Rubyで正規表現
doc = "<html>Lorem ipsum dolor sit amet</html>" # Loremという文字が出現する位置を調べる puts doc =~ /Lorem/ # => 6 # 逆でもいい puts /Lorem/ =~ doc # => 6 # 正規表現に一致する文字列を取得する if md = doc.match(/<html>(.+)<\/html>/) # これも逆でもいい。→ /.../.match(doc) puts md[0] # => "<html>Lorem ipsum dolor sit amet</html>" # 全体と一致する文字列が入る puts md[1] # => "Lorem ipsum dolor sit amet" # ()内の文字列が入る end # 取得したい文字列が複数ある場合は scan を使う doc2 = "<html>Lorem ipsum dolor sit amet</html><html>sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</html>" # 2つあるhtmlタグ内の文字列を取得したい sd = doc.scan(/<html>([^<]+)<\/html>/) # => [["Lorem ipsum dolor sit amet"], ["sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"]]
gsubの使い方メモ(Ruby)
gsubを使って、 htmlタグを大文字に変換する方法。
class TagUpper def initialize(html) @HTML = html.freeze end def convert() @HTML.gsub(/<[a-z|\/]+[>|\s]/){|tag| tag.upcase} end end tu = TagUpper.new("<html><body><a href='https://www.google.co.jp/?gfe_rd=cr&ei=OcXnV4_WF_T98wf345nADw'></body></html>") puts tu.convert()
Null参照エラーを撲滅するために
クイックソートの発明者として知られるアントニー・ホーアは同時に、 プログラマにとっては馴染み深い Null の生みの親でもあるが、 氏は次のような後悔を口にしておられる。
これ(Null)は、後に数え切れない過ち、脆弱性、システムクラッシュを引き起こし、 過去40年間で10億ドル相当の苦痛と損害を引き起こしたとみられる。
そうなのである。 多分、Null参照が原因のバグは全体の1割はある気がする(適当)。
そんなわけで、この忌まわしきNull参照を撲滅するための対策を考えみた。
その1 Nullを返さない
メソッドの戻り値としてNullを返さないようにする。 配列を返して、受け手側でループで処理しよう。 また、どうしても配列の先頭要素を取得してそれを返したい場合は、 Nullの時は空のインスタンスを返そう。 (NullObjectパタンを使ってもいいが全部のオブジェクトに対してこれを定義するのはしんどいので、重要なものだけにするのがよいと思う)
その2 Nullを代入しない
値の初期値にNullを代入しない。 stringの場合は空文字列、数値の場合は0、オブジェクトの場合は空のインスタンス(もしくはNullObject)を設定する。 「= nil」は絶対に認めない!
その3 Swiftを使う
人類は学んだ。Nullを代入できなければ、Null参照など発生しないことを。 Swiftはデフォルトの型でNullの代入ができない。 なので、以下のようなコードはエラーになりコンパイルできない。
var normalStr : String = null => エラー
Nullを代入するにはオプショナル型を使わなければならない。
var normalStr : String? = null
ビルド時にオプショナル型の使用を検知するような仕組みを作っておけば、 Null参照が起こる可能性を0にできる。
クロスサイトスクリプティングって何だ?
Wikipediaによると
クロスサイトスクリプティング(英: cross site scripting)とは、 ウェブページの部分をユーザからの入力をそのままエコーバック (オウム返し)することによって生成しているアプリケーションの セキュリティ上の不備を利用して、サイト間を横断して悪意のある スクリプトを注入する攻撃のことをいう。また経緯上、 それを許してしまう脆弱性についても、このように呼ばれている。
とのことらしい。 全然わからんかったので、自分でHTMLを書いてみたらようやく理解できた。
超簡単なXSSのサンプル
入力内容をそのままページに表示するプログラムを書いてみる。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> </head> <body> <p></p> <h4><a href="http://google.com">Google</a></h4> <ul> <li>今日はいい天気</li> </ul> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <input type="text" name="name" id="inputed_text" value=""> <input type="button" name="name" id="btnRegist" value="投稿"> <script type="text/javascript"> $(function() { $('#btnRegist').on('click', function() { var inputed_text = $('#inputed_text').val(); $('ul').append('<li>'+ inputed_text +'</li>'); }); }); </script> </body> </html>
投稿ボタンを押すと入力内容がそのままページに表示される。これはサンプルとしてHTMLだけで書いたが、実際には入力内容はサーバーに保存され、このWebサービスを使う全ユーザが同じ内容を共有できるようになっていると仮定する。
この入力欄に下記のような一文を挿れて投稿してみる。
</li> <script type="text/javascript"> $('a').attr('href','http://yahoo.co.jp'); </script> <li>
するとHtmlはこのようになる。
<html lang="ja"><head> <meta charset="utf-8"> </head> <body> <p></p> <h4><a href="http://yahoo.co.jp">Google</a></h4> <ul> <li>今日はいい天気</li> <li></li> <script type="text/javascript"> $('a').attr('href','http://yahoo.co.jp'); </script> <li></li></ul> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <input type="text" name="name" id="inputed_text" value=""> <input type="button" name="name" id="btnRegist" value="投稿"> <script type="text/javascript"> $(function() { $('#btnRegist').on('click', function() { var inputed_text = $('#inputed_text').val(); $('ul').append('<li>'+ inputed_text +'</li>'); }); }); </script> </body></html>
ul要素(リスト)の中にscriptが埋め込まれ、Googleのリンク先が Yahoo!JAPANに変わっている。
今回のサンプルはリンク先を変えただけだが、input要素のPostの送信先を改ざんしてクレジットカード番号を抜き取るというようなことが行われているらしい。
対策は?
入力内容に含まれる危ない文字(<とか>とか&やら)をエスケープするのが基本的な対策法。
RubyOnRailsはRails2までは、明示的なエスケープ処理を書く必要があったけどRails3からはエスケープがデフォルトになったんだそう。
Rubyの要点
Rubyを使っていて、自分の理解が浅かったところをまとめてみました。
map,reduce,filter
Lispなどの関数型言語でお馴染みの上記関数をRubyで使う。
map
rubyにもmapメソッドがあります。 実際はcollectというメソッドの別名ですが、mapを使うほうが混乱は少ないかな。
list = (1..10) list.map{|i| i*2} #listの全要素を2倍します
reduce
これもinjectというメソッドの別名です。
list = (1..10) list.reduce {|sum,n| sum+n} #すべての要素を足し合わせる
filter(=select)
Haskellなどで使われるfilterメソッドに対応するのはselectというメソッドです。
list = (1..10) list.select{|n| n % 3 == 0} #3の倍数を抽出する
ブロック
do 〜 end(または{〜})で囲まれた部分。 メソッドの引数として使われる。
mapを実装してみる。
list = (1..10) # 特異メソッドを使ってlistのインスタンスにmap2を実装 def list.map2(&block) new_list = [] self.each do |i| new_list << block.call(i) end new_list end list.map2{|i| i*2} => [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
&blockでブロック引数を受け取っている。
&はブロックをProcオブジェクトに変換するための記号。
(ブロック自体はオブジェクトとして存在できず引数として渡せないのでこのような方法をとるらしい)
ただ、この書き方は冗長である。なぜなら・・
「ブロック引数は仮引数の中で一番最後に渡されなければならない」
という制約があるから。
つまり、引数自体宣言する必要ないんじゃね?ということ。
このためRubyにはyield(イールド)という構文が用意されている。
これを使えばブロック引数の宣言すら必要ない。こんな感じでかけちゃう・・・
# yieldを使って書き直す def list.map3() new_list = [] self.each do |i| new_list << yield(i) end new_list end
ただ、yieldを使うと個人的には少し読みにくい気もする。
ATOMにHaskellの開発環境を導入
Haskellを学ぶため、
ATOMエディタにHaskell開発環境を導入したので、
手順のメモをQiitaに投稿しました。
ATOMのide-haskell導入手順(MacOS X)