Hikiのmod_ruby化

Hikiの0.8.0 preview1がリリースされた。mod_rubyに正式対応したそうなので、 早速試してみようかと。が、rubyが1.8以降になってしまってる。 woodyのlibapache-mod-rubyは1.6.7だ。仕方ないのでソースから入れてあった apache2で試すことに。apache2にはmod_rubyが無いので、まずこれから。

$ tar zxvf mod_ruby-1.2.0.tar.gz
$ cd mod_ruby-1.2.0/
$ ./configure.rb --with-apxs=/usr/local/apache2/bin/apxs

/usr/local/apache2/bin/apxsの先頭に

#!/usr/local/bin/perl -w

と書いてあってエラーになるので(今まで使ったこと無かったのか?)、

# ln -s /usr/bin/perl /usr/local/bin/

としてから作業継続。

$ make
# make install

httpd.confに以下を追加。

LoadModule ruby_module modules/mod_ruby.so

続いてHiki本体。hikifarmにしたいのでmisc/hikifarm/READMEに従ってインストール。

Hiki本体 → /usr/local/hiki-0.8.0
CGI → /home/httpd/hiki08
データ → /home/hiki08-data

httpd.confに以下を追加。

Alias /hiki "/home/httpd/hiki08"
<Directory "/home/httpd/hiki08">
   AllowOverride None
   Options +ExecCGI +FollowSymLinks
   #AddHandler cgi-script .cgi
   RubyRequire apache/ruby-run
   <Files *.cgi>
      SetHandler ruby-object
      RubyHandler Apache::RubyRun.instance
   </Files>
   DirectoryIndex index.cgi
   Allow from all
</Directory>

これで完了。0.6.5のhiki-data/をそのままコピーするとinternal errorになるので、 まずメニューからWikiサイトを作ってデータだけコピーする。

Wikiサイト名/hiki.conf

のフォーマットが違うのがいけないらしい。しかもその場合は、

http://server/hiki/Wikiサイト名/

は問題無く動くのに、

http://server/hiki/

がinternal errorなので、非常にわかりにくい。 あと、管理メニューで更新すると落ちる。これもhiki.confのフォーマットか? 落ちるとhiki.confが無くなってしまうようなので、あんまり試してない。

最大の関門は自作のプラグイン。 0.6.5のプラグイン→0.8.0に移行に関しては、

$変数 → @conf.変数

でいけるはずなのだが、mod_ruby化の方が厄介らしい。 attach.rbのform_procでInsecure Operationが出てしまう。 add_form_procで登録しているattach_show_page_files_checkbox()から 呼ばれているattach_file_info() (これはtDiaryから移植した自作関数)の 中で添付画像のサイズを調べているところが問題らしい。 File.open(attach_file)する前に

attach_file.untaint

とすることで解決。

また、今までimage.rbとして別プラグインにしていたcat_image()、image_external()を attach.rbに統合。

--- attach.rb.org	Thu May 26 00:28:57 2005
+++ attach.rb	Thu May 26 19:49:15 2005
@@ -11,6 +11,79 @@
    </ul></div>'
 end
 
+# 猫専用
+def cat_image( dir, file, width, height, place = "right", lnk = 0, target = "_blank" )
+  ext = '.jpg'
+  if (file =~ /SANY/)
+    ext = '.JPG'
+  end
+  if (lnk == 1)
+    begin_a = %Q[<a href="http://www.asahi-net.or.jp/~ad6h-ootk/cat/#{dir}/#{file}.html" target="#{target}">]
+    end_a = %Q[</a>]
+  else
+    begin_a = ''
+    end_a = ''
+  end
+    %Q[#{begin_a}<img class="#{place}" src="http://www.asahi-net.or.jp/~ad6h-ootk/cat/#{dir}/#{file}#{ext}" border="0" width="#{width}" height="#{height}" alt="#{file}"</img>#{end_a}] 
+end  
+#
+def image_external( url, alt, width, height, place = "right", lnk = 0, target = "_blank" )
+  if (lnk == 1)
+    begin_a = %Q[<a href="#{url}" target="#{target}">]
+    end_a = %Q[</a>]
+  else
+    begin_a = ''
+    end_a = ''
+ end
+  %Q[#{begin_a}<img class="#{place}" src="#{url}" border="0" width="#{width}" height="#{height}" alt="#{alt}"</img>#{end_a}] 
+end  
+#
+# service methods below. (from tDiary image.rb plugin)
+#
+
+def attach_file_info(fname)
+	image_type = nil
+	image_height = nil
+	image_width = nil
+  attach_file = "#{@cache_path}/attach/#{@page.escape}/#{fname.escape}"
+  attach_file.untaint
+	f = File.open(attach_file)
+
+	sig = f.read( 24 )
+	if /\A\x89PNG\x0D\x0A\x1A\x0A(....)IHDR(........)/on =~ sig
+		image_type = 'png'
+		image_height, image_width = $2.unpack( 'NN' )
+
+	elsif /\AGIF8[79]a(....)/on =~ sig
+		image_type   = 'gif'
+		image_height, image_width = $1.unpack( 'vv' )
+
+	elsif /\A\xFF\xD8/on =~ sig
+		image_type = 'jpg'
+		data = $'
+		until data.empty?
+			break if data[0] != 0xFF
+			break if data[1] == 0xD9
+
+			data_size = data[2,2].unpack( 'n' ).first + 2
+			if data[1] == 0xC0
+				image_width, image_height = data[5,4].unpack('nn')
+				break
+			else
+				if data.size < data_size
+					f.seek(data_size - data.size, IO::SEEK_CUR)
+					data = ''
+				else
+					data = data[data_size .. -1]
+				end
+				data << f.read( 128 ) if data.size < 4
+			end
+		end
+	end
+
+	return image_type, image_height, image_width, FileTest.size(f)
+end
+
 def attach_form(s = '')
   command = @command == 'create' ? 'edit' : @command
   <<EOS
@@ -61,8 +134,13 @@
   s << %Q!#{file_name.escapeHTML}</a>!
 end
 
-def attach_image_anchor(file_name, page=@page)
-  s =  %Q!<img alt="#{file_name.escapeHTML}" src="!
+def attach_image_anchor(file_name, page=@page, width=nil, height=nil, place=nil)
+  if (width && height)
+    imgsize = %Q!width="#{width}" height="#{height}"!
+  else
+    imgsize = ''
+  end
+  s =  %Q!<img class="#{place}" alt="#{file_name.escapeHTML}" #{imgsize} src="!
   s << %Q!#{@conf.cgi_name}#{cmdstr('plugin', "plugin=attach_download;p=#{page.escape};file_name=#{file_name.escape}")}">!
 end
 
@@ -143,11 +221,11 @@
   end
 end
 
-def attach_view(file_name, page=@page)
+def attach_view(file_name, width=nil, height=nil, place=nil, page=@page)
   if file_name =~ /\.(txt|rd|rb|c|pl|py|sh|java|html|htm|css|xml|xsl)\z/i
     attach_src(file_name, page)
   elsif file_name =~ /\.(jpeg|jpg|png|gif|bmp)\z/i
-    attach_image_anchor(file_name, page)
+    attach_image_anchor(file_name, page, width, height, place)
   end
 end
 
@@ -194,14 +272,38 @@
   s
 end
 
+
 def attach_show_page_files_checkbox
-  s =  ''
+  s = %Q[
+    <script type="text/javascript">
+    <!--
+      var elem=null
+      function ins(val){
+      //  alert(val)
+          elem.value+=val
+      }
+      window.onload=function(){
+        for(var i=0;i<document.forms.length;i++){
+          for(var j=0;j<document.forms[i].elements.length;j++){
+            var e=document.forms[i].elements[j]
+            if(e.type&&e.type=="textarea"){
+              if(elem==null){
+                elem=e
+              }
+              e.onfocus=new Function("elem=this")
+            }
+          }
+        }
+      }
+    //-->
+    </script>
+  ]
   if (files = attach_page_files).size > 0
-    s << %Q!<form method="post" enctype="multipart/form-data" action="attach.cgi">
-  <input type="hidden" name="p" value="#{@page.escapeHTML}">
-  <input type="hidden" name="command" value="#{@command == 'create' ? 'edit' : @command}">
-  <p>#{attach_files_label}: 
+    s << %Q!<p>#{attach_files_label}: 
 !
+    s1 = ''
+    s2 = ''
+    s3 = ''
     files.each do |file_name|
       f = file_name.unescape
       case @conf.charset
@@ -210,13 +312,51 @@
       when 'Shift_JIS'
         f = file_name.unescape.to_sjis
       end
-      s << %Q! [<input type="checkbox" name="file_#{file_name}">#{attach_anchor(f)}] \n!
-    end
-    s << %Q!<input type="submit" name="detach" value="#{detach_upload_label}">\n</p>\n</form>\n!
+      img_info = attach_file_info(f)
+#      img_info = ['jpg',100,100,500]
+      img_w = img_info[1]
+      img_h = img_info[2]
+      while (img_w > 200)
+        img_w = img_w / 2
+        img_h = img_h / 2
+      end
+      #s1 << %Q! <td><input type="button" onclick="window.status='xxx'" value="本文に追加"> </td>\n!
+      s1 << %Q! <td><input type="button" onclick="ins('{{attach_view(&quot;#{f}&quot;,#{img_w},#{img_h}}}')" value="本文に追加"> </td>\n!
+      #s1 << %Q! <td><input type="button" onclick="window.status='xxx'; ins({{attach_view(#{f})}})" value="本文に追加"> </td>\n!
+      #s1 << %Q! <td>{{attach_view(#{f},#{img_w},#{img_h})}} </td>\n!
+      s2 << %Q! <td>#{attach_view(f,img_w,img_h)} </td>\n!
+      s3 << %Q! <td><input type="button" onclick="ins('{{attach_view(&quot;#{f}&quot;,#{img_w},#{img_h}}}')" value="本文に追加"><br>#{img_info[1]}x#{img_info[2]}(#{img_info[3]/1024}K)<br><input type="checkbox" name="file_#{file_name}" value="true">#{attach_anchor(f)} </td>\n!
+    end
+    #s << %Q!<br><table><tr>#{s1}</tr><tr>#{s2}</tr><tr>#{s3}</tr></table><br>!
+    s << %Q!<br><table>\n<tr>\n#{s2}</tr>\n<tr>\n#{s3}</tr>\n</table><br>!
+    s << %Q!<input type="submit" name="detach" value="#{detach_upload_label}">\n</p>!
   end
   s
 end
 
+#def attach_show_page_files_checkbox
+#  s =  ''
+#  if (files = attach_page_files).size > 0
+#    s << %Q!<form method="post" enctype="multipart/form-data" action="attach.cgi">
+#  <input type="hidden" name="p" value="#{@page.escapeHTML}">
+#  <input type="hidden" name="command" value="#{@command == 'create' ? 'edit' : @command}">
+#  <p>#{attach_files_label}: 
+#!
+#    files.each do |file_name|
+#      f = file_name.unescape
+#      case @conf.charset
+#      when 'EUC-JP'
+#        f = file_name.unescape.to_euc
+#      when 'Shift_JIS'
+#        f = file_name.unescape.to_sjis
+#      end
+#      s << %Q! [<input type="checkbox" name="file_#{file_name}">#{attach_anchor(f)}] \n!
+#    end
+#    s << %Q!<input type="submit" name="detach" value="#{detach_upload_label}">\n</p>\n</form>\n!
+#  end
+#  s
+#end
+
 
 add_body_leave_proc {
   begin
@@ -232,12 +372,12 @@
   
 add_form_proc {
   begin
-    s = case @options['attach.form']
-    when 'edit', 'both'
+    #s = case @options['attach.form']
+    #when 'edit', 'both'
       attach_form(attach_show_page_files_checkbox)
-    else
-      ''
-    end
+    #else
+    #  ''
+    #end
   rescue Exception
   end
 }

何はともあれ、それなりに動くようだ。てか、あからさまに速い。 下手したら倍くらいの感じ。でもかみさんは満足しないだろーなー...

Last modified: 2011-03-20 by Unknown