/ 最近 .rdf 追記 設定 本棚

脳log[Hiki: 2007-01-16~]



2007年01月16日 (火)

[Hiki]ユーザー管理

 管理者

Hikiにはデフォルトで adminという名前の管理ユーザーが一人。Hikiをインストールして FrontPageを表示したら、まず管理者のパスワードを設定するよう促される。

 登録ユーザー

管理画面で edit_user.rbプラグインを有効にするとユーザー名とパスワードの組をいくつでも追加でき、ページの編集を登録ユーザーだけに許すということもできる。必ずしも編集権を登録ユーザーのみに制限する必要はない。

 仮ユーザー(仮称) のようなものがあればと思う

パスワードはなし。名を名乗るだけでなれる。ただし登録ユーザーと同じ名は名乗れない。

掲示板に書き込むときに名前を書くように Wikiを編集するときにも名前を入力できたらな、と思ったので。

パスワード無しの単なる自称なのでなりすましもできるし、しょうもないコメントを(ユーザー名として)入力することもできるけど、貢献してくれた人に名無しでいることを強要するのは間違い。ペンネームでもなんでも名乗る自由と匿名でいる自由が与えられていいと思う。善意の第三者の協力を期待するのなら。


2007年01月13日 (土)

[Ruby][Hiki] Hiki-0.8.6のインストロールインストゥール、install。

まずローカルで試してからアップロードしたのだがローカルの Apacheが Ruby-1.9.0を呼ぶので、FrontPageの表示からログインまでを可能にするために加えた変更点のリストをメモしておく。

 hiki/config.rb: Hiki::Config#initialize

-      instance_variables.each do |v|
+      instance_variables.each do |v| v = v.to_s;

vにシンボルが渡されて、次の行で v.sub!したときにエラーになっていた。

 hiki/command.rb: Hiki::Command#cmd_login

          if page && !page.empty?
-           redirect(@cgi, @conf.base_url + @plugin.hiki_url( page ), session_cookie( session.session_id ))
+           redirect(@cgi, @conf.base_url + @plugin.hiki_url( page ), [session_cookie( session.session_id )])
          else
-           redirect(@cgi, @conf.index_url, session_cookie( session.session_id ))
+           redirect(@cgi, @conf.index_url, [session_cookie( session.session_id )])

Cookieが session_id=SESSIONIDの形でなく SESSIONIDと key名なしの状態でブラウザにセットされるからログインに失敗していた。

Hiki::Command#cmd_logoutでは同じ引数を [session_cookie(session_id, -1)] としていたので同じように配列にした。

 hiki/storage.rb: Hiki::HikiDBBase#md5hex

-      Digest::MD5::new( s || '' ).hexdigest
+      Digest::MD5::hexdigest( s || '' )

リファレンスマニュアルには Digest::MD5.new([str]) とあるが引数の数が 0でないと叱られる。

 hiki/db/tmarshal.rb: TMarshal::dump_text

    when Array
-     "[\n"+obj.collect{|x| dump_text(x)+",\n"}.to_s+"]"
+     "[\n"+obj.collect{|x| dump_text(x)}.join(",\n")+"\n]"
    when Hash
-     "{\n"+obj.sort_by{|e| e[0].inspect}.collect{|k,v| "#{dump_text(k)} => #{dump_text(v)},\n"}.to_s+"}"
+     "{\n"+obj.sort_by{|e| e[0].inspect}.collect{|k,v| "#{dump_text(k)} => #{dump_text(v)}"}.join(",\n")+"\n}"

dumpに失敗していた。

原因となった Array#to_sのバージョンによる出力の違い↓。

Ruby-1.8.5p12> [1,2,3].to_s #=> "123"
Ruby-1.9.0 20061205> [1,2,3].to_s #=> "[1, 2, 3]"

リファレンスマニュアルには

to_s
   self.join($,) と同じです。

と書いてあるから to_sで(ある種の) joinを代用していても仕方ない。

と思ったがどちらにしろ Array#to_sの出力は $, に依存するので、後で(loadするときに) evalすることを考えれば今回の to_sの使用は不適切か。

[Ruby][Hiki] 差分の表示

上のエントリで FrontPageの表示とログインまでやったが、差分の表示もおかしかったので Array#to_s らしき部分を join('') に書き換えまくったら直った模様。

'string'.join は存在しなかったので、書き換えてエラーにならないということは考えたとおり Array#to_sだったか、そのコードが実行されてなくて発覚してないが実は間違いだった(実行されたらNoMethodErrorになる)かのどちらか ^_^; こういう実行してみないとわからないところは javascriptと同じでレアなコードパスのデバッグを難しくするね。

以下、リスト。

 style/default/hikidoc.rb: HikiDoc#escape_meta_char

+if(defined? ' '.ord) # Ruby-1.9
   def escape_meta_char( text )
     text.gsub( META_CHAR_RE ) do |s|
+      '&#x%x;' % s[1].ord
+    end
+  end
+else
+  def escape_meta_char( text )
+    text.gsub( META_CHAR_RE ) do |s|
       '&#x%x;' % s[1]
     end
   end
+end

いきなり Array#to_sと関係ないが String#[index] が Integerに代えて一文字の Stringを返すようになった対策。

 hiki/util.rb: Hiki::Util#word_diff

      if digest
-        return View.new( diff, src.encoding, src.eol ).to_html_digest(overriding_tags, false).to_s.gsub( %r|<br />|, '' ).gsub( %r|\n</ins>|, "</ins>\n" )
+        return View.new( diff, src.encoding, src.eol ).to_html_digest(overriding_tags, false).join(\).gsub( %r|<br />|,  ).gsub( %r|\n</ins>|, "</ins>\n" )
      else
-        return View.new( diff, src.encoding, src.eol ).to_html(overriding_tags, false).to_s.gsub( %r|<br />|, '' ).gsub( %r|\n</ins>|, "</ins>\n" )
+        return View.new( diff, src.encoding, src.eol ).to_html(overriding_tags, false).join(\).gsub( %r|<br />|,  ).gsub( %r|\n</ins>|, "</ins>\n" )
      end

 hiki/util.rb: Hiki::Util#word_diff_text

      if digest
-        return View.new( diff, src.encoding, src.eol ).to_wdiff_digest({}, false).join.gsub( %r|\n\+\}|, "+}\n" )
+        return View.new( diff, src.encoding, src.eol ).to_wdiff_digest({}, false).join(nil).gsub( %r|\n\+\}|, "+}\n" )
      else
-        return View.new( diff, src.encoding, src.eol ).to_wdiff({}, false).join.gsub( %r|\n\+\}|, "+}\n" )
+        return View.new( diff, src.encoding, src.eol ).to_wdiff({}, false).join(nil).gsub( %r|\n\+\}|, "+}\n" )
      end

join('')か join(nil)か統一しろよ、とセルフツッコミ。

 hiki/util.rb: Hiki::Util#compare_by_line_word

-          before_change = Document.new(line[1].to_s,
+          before_change = Document.new(line[1].join(''),
                                       doc1.encoding, doc1.eol)
-          after_change  = Document.new(line[2].to_s,
+          after_change  = Document.new(line[2].join(''),
                                       doc2.encoding, doc2.eol)

 hiki/docdiff/view.rb: View#apply_style

       if block_given?
-        source = yield block[1].to_s
-        target = yield block[2].to_s
+        source = yield block[1].to_a.join ''
+        target = yield block[2].to_a.join ''
       else
-        source = block[1].to_s
-        target = block[2].to_s
+        source = block[1].to_a.join ''
+        target = block[2].to_a.join ''
       end

block[i]は nilの可能性があるので to_a.join

 hiki/docdiff/view.rb: View#apply_style_digest

       if block_given?
-        source = yield entry[1].to_s
-        target = yield entry[2].to_s
+        source = yield entry[1].to_a.join ''
+        target = yield entry[2].to_a.join ''
       else
-        source = entry[1].to_s
-        target = entry[2].to_s
+        source = entry[1].to_a.join ''
+        target = entry[2].to_a.join ''
         end
       if  i == 0
         context_pre  = ""  # no pre context for the first entry
       else
-        context_pre  = @difference[i-1][1].to_s.scan(context_pre_pat).to_s
+        context_pre  = @difference[i-1][1].to_a.join('').scan(context_pre_pat).to_s
       end
       if (i + 1) == @difference.size
         context_post = ""  # no post context for the last entry
       else
-        context_post = @difference[i+1][1].to_s.scan(context_post_pat).to_s
+        context_post = @difference[i+1][1].to_a.join('').scan(context_post_pat).to_s
       end

 hiki/docdiff/view.rb: View#source_lines

   def source_lines()
     if @source_lines == nil
-      @source_lines = @difference.collect{|entry| entry[1]}.join.scan_lines(@eol)
+      @source_lines = @difference.collect{|entry| entry[1]}.join(nil).scan_lines(@eol)

 hiki/docdiff/view.rb: View#target_lines

   def target_lines()
     if @target_lines == nil
-      @target_lines = @difference.collect{|entry| entry[2]}.join.scan_lines(@eol)
+      @target_lines = @difference.collect{|entry| entry[2]}.join(nil).scan_lines(@eol)

[Hiki]セキュリティエラー続発

Hikiの設置が一段落したようなのでページの編集に取りかかる。が、こちらもすんなりとはいかない。プラグイン記法でできることが著しく制限されているのだ。

tDiaryは日記の著者を信用している(自分の日記を壊そうとする者はいないので。著者!=管理者となるレンタルサービスでは話が違って、セキュアモードでシステムを守る必要があるが)のに対し、Hikiはページ編集者を全く信用することができない。誰でも書き込めるのが Wikiだから。

そんなわけでセキュリティエラーが続発中。プラグイン記法で許されるのは単一のプラグイン呼び出しだけ。任意の文字列を埋め込むことも、プラグイン呼び出しを連ねることも、Rubyであれやこれやをすることもできない。全てをプラグインの中に閉じこめてしまい、Hikiページではそれを呼び出すしかないわけだ。(プラグインは Hikiの設置者が責任を持っているので信用されている)

{{CGI::escapeHTML @hoge.inspect}}

どころか

 {{CGI::escapeHTML '<abc>'}}

ですら通らないんだから。いやはや全く。

 いやいやいやいや

SecurityError (Insecure: can't intern tainted string)

これは Ruby 1.9.0に固有のエラーじゃまいか。だったら Hikiの方をちょこっと変更してもいいんじゃないか?

[Hiki][Ruby]プラグイン記法

 {{hoge a b 5}}      #=> hoge('a', 'b', 5)
 {{hoge 'a' b(5)}}   #=> hoge('a', 'b', 5)
 {{hoge ,a(, b)(5)}} #=> hoge('a', 'b', 5)
 {{hoge, a, b, 5}}   #=> PluginException('not plugin method: hoge,')
 {{hoge; hage}}      #=> PluginException

文法の緩さとか、一つのメソッドしか呼べないとか、嫌すぎる。

そりゃあ Rubyで

require digest/md5

という風にライブラリ名をクォーテーションで括らずに書けたら楽だなとかは考えるし、Symbolが Stringのサブクラスになったときは

require :sqlite3

が通るのを一番に確認したけど、

defined? printf
alias printg printf

を見て、

  • printfって何?クラスは?
  • printgと printfの間にカンマがないけどどういう文法? alias専用ルール?

というのと同種の嫌悪を感じる。