SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|

2006-01-16(Mon) tdiaryのコメントスパムを排除してみる

  当ブログはtdiaryというブログシステムを利用しているが、このtdiaryというブログシステムには「ツッコミ」を入れられるという特徴がある。日記の1日のエントリごとに、小さな掲示板が付いているというようなモノなのであるが、掲示板であるから余計な書き込みをする輩が現れる。面倒なことはキライだし、アホな書き込みも「枯木も山の賑わい」と、基本的に放置の方向で運営してきたが、怪しげな薬品の広告スペースとかに使われたり、私信のチャットに使われたりしだすと、さすがに見苦しさに余る。

  こーゆー時にはIPアドレスで制限したりするのが、基本的な対処であるが、IPアドレスでの制限は大抵はドロ沼になる。書き込む方は基本的に攻撃側であり、防御側が屈するまで、気の済むまで攻撃できるんだから当然である。IPを変えるなんざ、いとも簡単なことであり、そりゃ効き目があるわけがないのである。

  基本的に、攻撃もしくはどちらかというとダークな行動をする輩はスキルが低いことが多い。以前にFOMAの端末のボタンに直に配線をつなぐ改造を加え、端末をPCから制御して迷惑メールを出しまくっていた業者が摘発されたというニュースを見たが、その改造のアホさには目を見張るものがあった。端末のボタンへの配線が2本ずつあったのである。どうやら彼らには「GND」という概念がないらしい。同様に推測すると、以前に悪いことするために「サリンちゃん」なんていう妙薬を作り出した団体があり、ニュースでは「高度な技術を持つエリートを擁している」などとして扱われていたが、パンピーからは高度な技術にみえても、きっとフツーの薬品エンジニアからはなんでもないことなんじゃねーかと思う。まっとーな人間なら、ハナっからあんな団体に属したりしませんって。

  脱線したが、よーするに、そのようなダークな輩に正義のエンジニア(?)が負けるなどということはあってはならないコトなのである。ちゅーわけで、なんかいい方法はないかと考えていたのだが、あった。tdiaryの場合、うっとおしいコメントがあったら、管理画面でチェックボックスを外すことで非表示にできるのであるが、これをデフォルトにしてしまえばいいのである。そうすりゃ書き込まれた後に管理者が確認して、内容によって表示したり、放置したりすることができる。なんだ、簡単だ。いわゆる、オプトアウトでなく、オプトイン方式にすりゃいいのである。

  通常であれば、簡単な変更ではあっても、そのような変更は不可能なところであるが、ウチは自宅サーバであり、tdiaryはRubyで書かれたオープンソースアプリであり、オイラはRubyプログラマである。チョイチョイと直してしまえばいい。

  まずは、該当する部分を処理部を探さなければならない。grepである。早速tdiaryのホームディレクトリ下でgrepしてみる。検索ワードは「ツッコミ」だ。

colinux:/home/mitsu/public_html/diary $ grep -r ツッコミ *
skel/update.rhtml:                              <input type="submit" tabindex="<%=2000+idx%>" name="comment" value="ツッコミ表示状態変更">

  ココがクサい。ソースを読んでみる。

colinux:/home/mitsu/public_html/diary $ vi skel/update.rhtml
     59         @diary.each_comment( 100 ) do |comment| %>
     60             <div class="commentator">
     61                 <span class="checkbox">
     62                     <input class="checkbox" type="checkbox" tabindex="<%=2000+idx%>" name="<%= idx += 1 %>" value="true"<% if comment.visible? then %> checked<% end %>>
     63                 </span>
     64                 <span class="commentator"><%= CGI::escapeHTML( comment.name ) %><%= CGI::escapeHTML( " <#{comment.mail}>" ) unless comment.mail.empty? %></span>
     65                 <span class="commenttime"><%%=comment_date( Time::at( <%=comment.date.to_i%> ) )%></span>
     66             </div>
     67             <p><%= comment.body.make_link.gsub( /\n/, "<br>" ).gsub( /<br><br>\Z/, '' ) %></p><%
     68         end
     69         if idx > 0 then %>
     70             <div class="button">
     71                 <input type="submit" tabindex="<%=2000+idx%>" name="comment" value="ツッコミ表示状態変更">
     72             </div><%
     73         end %>

  ここはおそらくツッコミの表示部らしい。「comment.visible?」あたりで引っ掛けられそうである。おそらく、ツッコミはcommentであり、commentはオブジェクトなのであろう。

colinux:/home/mitsu/public_html/diary $ grep -r "visible?" *
tdiary.rb:              def visible?; @show; end
tdiary.rb:                              i += 1 if all or comment.visible?
tdiary.rb:                              if c.visible? then
tdiary.rb:                              next unless com.visible?
tdiary.rb:              def visible?
tdiary.rb:                                              break if @diary.visible?
tdiary.rb:                              lm = lmd if lm < lmd and diary.visible?
tdiary.rb:                              next unless diary.visible?
tdiary.rb:                      @diary = nil if @diary and not @diary.visible?
tdiary.rb:                              @diaries_size += 1 if diary.visible?
tdiary.rb:                              next unless diary.visible?
tdiary.rb:                                      next unless com.visible?

  いい感じに引っかかってきた。こーなりゃ、tdiary.rbを読むしかない。

colinux:/home/mitsu/public_html/diary $ vi tdiary.rb
     93     #
     94     # class Comment
     95     #  Management a comment.
     96     #
     97     class Comment
     98         attr_reader :name, :mail, :body, :date
     99
    100         def initialize( name, mail, body, date = Time::now )
    101             @name, @mail, @body, @date = name, mail, body, date
    102             @show = true
    103         end
    104
    105         def shorten( length = 120 )
    106             matched = body.gsub( /\n/, ' ' ).scan( /^.{0,#{length - 2}}/ )[0]
    107             unless $'.empty? then
    108                 matched + '..'
    109             else
    110                 matched
    111             end
    112         end
    113
    114         def visible?; @show; end
    115         def show=( s ); @show = s; end
    116
    117         def ==( c )
    118             (@name == c.name) and (@mail == c.mail) and (@body == c.body)
    119         end
    120     end

  ん? 114行目の「def visible?; @show; end」があって、102行目の「@show = true」があるっつーことは……これをfalseにするだけじゃん!! わー!! こんな1行ばっかの変更じゃ、ブログのネタにならないじゃねーかッ!!

  ……などといいつつも、ネッチリとソースコードを入れてネタにしてしまったが、結論から言うと「tdiary.rb」の以下の部分(Commentクラスのコンストラクタだ)を書き換えるだけで、所望する動作を行うことができた。

    100         def initialize( name, mail, body, date = Time::now )
    101             @name, @mail, @body, @date = name, mail, body, date
    102             @show = true	(※trueをfalseに書き換える)
    103         end

  以上、tdiaryをお使いで、コメントスパムに困っている人。この対処法を試してみてはいかがであろうか。ほんじゃ。

  あ、そうそう、この一連のツッコミには笑わせてもらった。オイラには書き込み元のIPが同じだってこと、わかっちゃってるんだよねぇ。