PMAFind

Webサーバのログに記録されていたものにPMAFindというphpMyAdminを探索するロボットプログラムがいました。

/phpmyadmin/main.php
/PMA/main.php
/mysql/main.php
/admin/main.php
/db/main.php
/dbadmin/main.php
/web/phpMyAdmin/main.php
/admin/pma/main.php
/admin/phpmyadmin/main.php
/admin/mysql/main.php
/mysql-admin/main.php
/phpmyadmin2/main.php
/mysqladmin/main.php
/mysql-admin/main.php
/main.php
/phpMyAdmin-2.5.6/main.php
/phpMyAdmin-2.5.4/main.php
/phpMyAdmin-2.5.1/main.php
/phpMyAdmin-2.2.3/main.php
/phpMyAdmin-2.2.6/main.php
/myadmin/main.php

のようなパスを探しているようです。注意、注意。

PERL_DL_NONLAZY

とある環境で、PerlのTestを書いていて、make testを実行すると

install_driver(Oracle) failed: Can't load '/usr/lib/perl/site_perl/5.005/sun4-solaris/auto/DBD/Oracle/Oracle.so' for module DBD::Oracle: ld.so.1: /opt/local/bin/perl: 重大なエラー: 再配置エラー: ファイル /usr/lib/perl5/site_perl/5.005/sun4-solaris/auto/DBD/Oracle/Oracle.so: シンボル newSVuv: 参照シンボルが見つかりません。

というエラーに出くわすことがありました。これは、テスト実行時のPERL_DL_NONLAZY=1という環境変数設定を抜いてやるとうまくいったのですが、なぜテストの時はLAZYロードにするのかな?と疑問に思い調べてみると、

ExtUtils/MM_Unix.pm

  For some reason which I forget, Unix machines like to have PERL_DL_NONLAZY set for tests.

だそうです...

ExtUtils-MakeMakerの古いバージョン(その環境のものは5.4302)だと、ExtUtils/MM_Unix.pmに

$perl = "PERL_DL_NONLAZY=1 $perl" unless $Is_Win32;

とべた書きしてあって、LAZYロードに変えることはMakeMakerのオプションではできないようです。
なので、Makefile.PLで↓のようにして対処しています。

use ExtUtils::MakeMaker;
use File::Copy;

WriteMakefile(
  # ・・・
);

open(IN, "Makefile") || die;
open(OUT,">Makefile.tmp") || die;
while(<IN>) {
    s/PERL_DL_NONLAZY=1//g;
    print OUT;
}
close(OUT);
close(IN);

move("Makefile.tmp", "Makefile");

まあ、そもそもDBD/Oracle/Oracle.soのビルドの問題ではあるのですが...(多分、バイナリを他所から持ってきたのではと推測)

CでRubyモジュールを作る

PerlのXSがsoを読み込むPerlモジュールファイル(.pm)を必要とするのに比べて、Rubyのrequireは.soファイルを直接読み込んでくれるので、ちょっとばかり簡単です。

.soの作り方は、svn.ruby-lang.orgにあります。

CのコードはRubyのマクロをふんだんに使って記述します。

static VALUE
rb_hello_c(self)
  VALUE self;
{
  return rb_str_new2("Hello C");
}

void
Init_hoge()
{
  VALUE rb_cHoge = rb_define_class("Hoge", rb_cObject);
  rb_define_alloc_func(rb_cHoge, rb_hoge_s_alloc);
  rb_define_private_method(rb_cHoge, "initialize", rb_hoge_initialize);
  rb_define_method(rb_cHoge, "hello_c", rb_hello_c);
}


.soと.rbで同名の拡張モジュールにしたい場合は、.soと.rbを同じところにおき、.rb側に

◆hoge.rb

require 'hoge.so'

class Hoge
  def hello_rb
    "Hello Ruby"
  end
end

と書けば、.rbが先に読み込まれ、続いて.soが読み込まれます。

◆hoge_test.rb
require 'hoge'

hoge = Hoge.new
puts hoge.hello_c
puts hoge.hello_rb

「クラス中のあるメソッドだけは、Cライブラリを使いたい」なんて時にはこれで対応できます。

セッションIDの作り方

セッションIDを生成する際にもっとも使われているのはMD5SHA-1などで、時間やプロセスIDをハッシュ化する方法でしょうか。実際にRubyCGI::Sessionは、こんな感じです。

def create_new_id
  require 'digest/md5'
  md5 = Digest::MD5::new
  now = Time::now
  md5.update(now.to_s)
  md5.update(String(now.usec))
  md5.update(String(rand(0)))
  md5.update(String($$))
  md5.update('foobar')
  @new_session = true
  md5.hexdigest
end

ただ、MD5SHA-1でも天文学的な確率で(ハックではない偶然)、コリジョンすることを恐れてユニーク性を保証したいという場合もあります。これは、システムでユニークな連番を振ってIDに付け加えればよいでしょう。つまり、

デタラメな値(できるだけユニーク、推測が不可能) + システムユニークID(推測されても仕方なし)

という組合せでセッションIDのユニーク性とハック不可能性を同時に達成することになります。

ところが、世の中にはとほほなものもあります。時間やプロセスID(できるだけユニーク、推測が不可能)を素のまま使い、それに連番(推測されても仕方なし)を付け加えるケースです。

113555965892740005

これでは、推測不可能があやしくなります。こんなセッションIDがあったら、見る人が見ればシステム時間を使っていると推測されるでしょう。時間やプロセスIDを使っては発番されるIDの帯域を自ら狭めていることになります。「できるだけユニーク、推測が不可能」の部分は単に同じ桁数のランダム値を用いたほうが堅牢です。

Rails + Windows + Mysql(SJIS)

この組合せだとMysqlと日本語のやりとりをするときに文字化けします。「UTF-8を使え」というのが簡単な解決策ですが、しがらみ等あってそうはいかない場合もあると思いますので回避方法を...

どこかのドキュメントに書いてあるのかもしれませんが、探せなかったのでソースを読んでみる。ActiveRecordのconection_adapters/mysql_adapter.rbに

      private
        def connect
          encoding = @config[:encoding]
          if encoding
            @connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil
          end
          @connection.real_connect(*@connection_options)
          execute("SET NAMES '#{encoding}'") if encoding
        end

という行があります。@configすなわちdatabase.ymlで設定できるということです。

development:
  adapter: mysql
  database: Depot_development
  host: localhost
  username: scott
  password: tiger
  encoding: sjis

こんな感じでOKです。

飲食業にもWeb2.0の影響?

http://www.tandoor.co.jp/yaima/lunch.html


タイトルはミスリードですが、神田に沖縄料理とインド料理という、出会うことのない2つのジャンルをRemixした「やいま」というお店があります。インドの方が角煮やゴーヤチャンプルを運んでくる姿は非常に微笑ましいです。
単に奇をてらっている訳ではなく、ちゃんと共通化できるところもあって、例えばウコン(ターメリック)は両方の料理で欠かせないものだし、ひき肉がタコライス(沖縄名物)とキーマカレー両方で使えたりします。
ちなみに、料理の方もボリュームがあってオススメです。

Railsのrakeタスクあれこれ

rake -Tでrakefileに定義されているタスクを一覧表示できます。いろいろあって覚えきれないので、ココにメモっておきます。(rails-0.14.4ベース。よく使うものだけ)

タスク 説明
clear_logs すべてのログを削除します。開発中は大量のdevelopment.logが出力されるので必須
clone_structure_to_test development環境からtest環境へスキーマ定義を移行します。
db_schema_dump ActiveRecordを使ってDB定義をdumpします。db/schema.rbに出力されます。
db_schema_import db_schema_dumpで出力したものをimportします。
db_structure_dump DDLを出力します
stat 行数、クラス数、メソッド数などのメトリクスを出力できます。面白いのはプロダクトコードとテストコードの比率も出力してくれること。
recent 10分以内に更新したテスト、10分以内に更新したモデル・コントローラのテストを実行する。

こう並べてみると、他のフレームワークと異なり、Rails気が利くタスクがたくさんあり、痒いところに手が届くものになっていることが分かります。