ソースを読む - bitchannel
起動
index.cgi
load './bitchannelrc' setup_environment require 'bitchannel/cgi' BitChannel::CGI.main bitchannel_context()
BitChannel::CGI.main に Wikispace のオブジェクトを渡す(bitchannel_context()の返り値)と開始。
cgi.rb
module BitChannel class CGI < WEBrick::CGI def CGI.main(wiki, webrickconf = {}) super(webrickconf, wiki) end def do_GET(req, res) wiki, = *@options wiki.session(guess_cgi_url(req)) { bcres = Handler.new(wiki).handle(Request.new(req, wiki.locale, false)) bcres.update_for res } end
Webrick 使用。BitChannel::CGI.mainを呼び出すと、下記のとおりリクエストに対し start() を呼び出す。do_GET() にて Handlerオブジェクトを生成、それに対し Requestオブジェクトをつくり引数として handle()に渡す(後述)。
WikiSpace
wikispace.rb
module BitChannel class WikiSpace include TextUtils def initialize(config, repo) @config = config @repository = repo @repository.syntax ||= Syntax.new(config, repo) end
@repository.syntax としてシンタックスを保持、か。。。
def session(guess_cgi_url) @config.cgi_url ||= guess_cgi_url raise 'CGI url could not fixed; give up' unless @config.cgi_url return yield ensure @repository.clear_per_request_cache end
do_GET()から呼ばれる session()。yield して ensure させる。
def exist?(name) @repository.exist?(name) end def view(name) ViewPage.new(@config, @repository[name]) end def viewrev(name, rev) ViewRevPage.new(@config, @repository[name], rev) end def edit(name) unless @repository.exist?(name) return edit_new(name) end page = @repository[name] rev = page.revision # fix revision EditPage.new(@config, page, page.source(rev), rev) end def edit_revision(name, srcrev) page = @repository[name] EditPage.new(@config, page, page.source(srcrev), page.revision) end def edit_new(name) EditPage.new(@config, @repository.fetch(name), '', nil) end def edit_again(name, src, cirev, reason = :edit_conflicted) page = @repository[name] EditPage.new(@config, page, src, (cirev || page.revision), reason) end def preview(name, orgrev, text) PreviewPage.new(@config, @repository.fetch(name), text, orgrev) end def save(name, origrev, text) @repository.fetch(name).checkin origrev, text ThanksPage.new(@config, name) end
wikiに対する操作関数郡。ViewPage, EditPage, PreviewPageなど対応するクラスオブジェクトを生成。おそらくhandler から呼び出される。
Page
page.rb
module BitChannel class Page end class RhtmlPage < Page include ErbUtils include TextUtils ... def content run_erb(@config.templatedir, template_id()) end end class WikiPage < RhtmlPage ... end class NamedPage < WikiPage def initialize(config, page) super config @page = page end def compile_page(content) @page.syntax.compile(content, @page.name) end def page_name escape_html(@page.name) end def page_url escape_url(@page.name) end class ViewPage < NamedPage ... def body compile_page(@page.source) end ... end class EditPage < NamedPage def initialize(config, page, text, origrev, reason = nil) ... end end
Erb使用。Page > RhtmlPage > WikiPage > NamedPage > {View, Edit....}
handler
handler.rb
module BitChannel class Handler include TextUtils def initialize(wiki) @wiki = wiki end def handle(req) _handle(req) || @wiki.view(FRONT_PAGE_NAME).response rescue Exception => err error_response(err, true) end def _handle(req) mid = "handle_#{req.cmd || 'view'}" return nil unless respond_to?(mid, true) __send__(mid, req) end
handle_#{req.cmd}()に __send__
def handle_view(req) if req.rev then __handle_viewrev(req) else __handle_view_latest(req) end end def __handle_view_latest(req) return nil unless req.page_name return nil unless @wiki.valid?(req.page_name) unless @wiki.exist?(req.page_name) return nil if @wiki.read_only? return @wiki.edit_new(req.page_name).response end @wiki.view(req.page_name).response end
@wiki の対応する操作関数を呼び出し、response を返す。page.rb では define されてないが、
class Page # redefine def response Response.new_from_page(self) end end
と redefine。Responseクラスは handler.rb にて定義:
class Response def Response.new_from_page(page) res = new() res.last_modified = page.last_modified res.set_content_body page.content, page.type, page.charset res end def initialize @status = nil @header = {} @cookies = [] @body = nil self.no_cache = true end attr_accessor :status attr_reader :body def set_content_body(body, type, charset) @body = body @header['Content-Type'] = "#{type}; charset=#{charset}" end
Pageオブジェクトが Respose.new_from_page() に self を渡すことにより、その情報から Responseオブジェクトを生成し、それを返す。