#!/usr/local/bin/ruby require 'authenticators' require 'yaml' # Default settings moved to soks.rb class WikiServlet < WEBrick::HTTPServlet::AbstractServlet def initialize( server, view, settings ) @server, @view, @wikiurl, @authenticators = server, view, settings[:url] , settings[:authenticators] end def service( request, response ) case request.path when '/robots.txt', '/favicon.ico' # Catch some requests to static files doAttachment( request, response, request.path[1..-1] ) when /\/(\w+?)\/(.+)/ # If request of the form /verb/pagename then doVerb on this class verb, pagename = $1, make_pagename_valid( $2 ) authenticate request, response make_username_valid( request ) if self.respond_to?( "do#{verb.capitalize}" ) self.send( "do#{verb.capitalize}", request, response, pagename, request.user ) else unknownView( request, response, pagename, verb, request.user ) end when /\/(.+)/ ; redirect( response, $1, 'view' ) # No verb given when "/" ; redirect( response, $SETTINGS[:home_page], 'view' ) # No page or verb given end if $SETTINGS[:force_no_cache] response['Cache-control'] ||= 'no-cache' response['Pragma'] ||= 'no-cache' end end def authenticate( request, response ) @authenticators.each do |path_regex,authenticator| if request.path.downcase =~ path_regex authenticator.authenticate( request, response ) break end end end def redirect( response, pagename, verb = 'view' ) pagename = pagename.url_encode # Reformat into url encoding response.set_redirect(WEBrick::HTTPStatus::Found, verb ? "#{@wikiurl}/#{verb}/#{pagename}" : "#{@wikiurl}/#{pagename}") end # These methods deal with the various views def doAttachment( request, response, pagename, person = nil ) request.script_name = 'attachment' request.path_info = "/#{pagename}" WEBrick::HTTPServlet::FileHandler.get_instance(@server, "#{$SETTINGS[:root_directory] }/attachment",true).service(request, response) end def doFind( request, response, pagename, person ) response.body = @view.find( request.query['regex'].strip ) response['Content-Type'] ||= "text/html" end def doRss( request, response, pagename, person ) response.body = @view.view( pagename, 'rss', person ) response["Content-Type"] = "application/xml" end # This captures all unkown view types def unknownView( request, response, pagename, view, person ) response.body = @view.view( pagename, view, person ) response['Content-Type'] ||= "text/html" end # All the following methods change the wiki, then redirect def doWiki( request, response, pagename, person ) redirect( response, pagename.gsub(/([a-z])([A-Z])/,'\1 \2') ) end def doSave( request, response, pagename, person ) content = request.query["content"].to_s newpagename = make_pagename_valid( request.query["titleprefix"].to_s + request.query["newtitle"].to_s) @view.revise( pagename, content.gsub(/\r\n/,"\n"), person, newpagename) if content redirect( response, newpagename ) end def doRollback( request, response, pagename, person ) revision = request.query['revision'] ? request.query['revision'].to_i : nil @view.rollback( pagename, revision, person ) if revision redirect( response, pagename ) end def doDelete( request, response, pagename, person ) @view.delete( pagename, person ) redirect( response, pagename ) end def doUpload( request, response, pagename, person ) newpagename = make_pagename_valid( request.query["titleprefix"].to_s + request.query["newtitle"].to_s) unless request.query['file'] == "" @view.revise( pagename, upload_file_data( request.query['file'] ), person, newpagename ) else @view.move( pagename, person, newpagename ) end redirect( response, newpagename ) end private def upload_file_data( upload_data ) path = "#{$SETTINGS[:root_directory]}/attachment/" filename = File.unique_filename( path , upload_data.filename ) File.open( File.join( path, filename ), 'wb' ) { |file| upload_data.list.each { |data| file << data } } "/attachment/#{filename}" end # Certain characters cause problems in titles, so delete def make_pagename_valid( pagename ) pagename.to_valid_pagename end # Because the username is also used as a page title, also delete troublesome characters from them # and make sure the name doesn't start with Automatic def make_username_valid( request ) request.user = request.user.to_valid_pagename request.user = "External #{request.user}" if request.user =~ /^Automatic/i end end def start_wiki( settings = {}, &automatic_agents ) $SETTINGS.merge! settings $MESSAGES = YAML.load( IO.readlines("#{$SETTINGS[:root_directory]}/views/messages.yaml").join ) wiki = Wiki.new( "#{$SETTINGS[:root_directory]}/content" ) view = View.new( wiki, $SETTINGS[:name] ) Thread.new( automatic_agents, wiki, view ) do |block, wiki, view| $LOG.info "Starting helper classes" block.call( wiki, view ) $LOG.info "Finished starting helper classes" end.priority = -2 server = WEBrick::HTTPServer.new( { :Port => $SETTINGS[:port], :ServerType=> $SETTINGS[:server_type] } ) server.mount("/", WikiServlet, view, $SETTINGS ) trap("INT") { $LOG.warn "Trying to shutdown gracefully" server.shutdown wiki.shutdown $LOG.info "Shutdown." } $LOG.warn "Starting server" server.start end