require File.dirname(__FILE__)+'/mixins/controller_mixin' require File.dirname(__FILE__)+'/mixins/render_mixin' require File.dirname(__FILE__)+'/mixins/javascript_mixin' require File.dirname(__FILE__)+'/mixins/responder_mixin' module Merb # All of your controllers will inherit from Merb::Controller. This # superclass takes care of parsing the incoming headers and body into # params and cookies and headers. If the request is a file upload it will # stream it into a tempfile and pass in the filename and tempfile object # to your controller via params. It also parses the ?query=string and # puts that into params as well. class Controller include Merb::ControllerMixin include Merb::RenderMixin include Merb::JavascriptMixin include Merb::ResponderMixin if Merb::Server.config[:session] require "drb" DRb.start_service('druby://localhost:0') Merb.const_set :DRbSession, DRbObject.new(nil, "druby://#{Merb::Server.config[:host]}:#{Merb::Server.config[:session]}") require File.dirname(__FILE__)+"/session/merb_drb_session" include ::Merb::SessionMixin puts "drb session mixed in" end attr_accessor :status, :body # parses the http request into params, headers and cookies # that you can use in your controller classes. Also handles # file uploads by writing a tempfile and passing a reference # in params. def initialize(req, env, args, method=(env['REQUEST_METHOD']||'GET')) env = MerbHash[env.to_hash] @layout = :application @status, @method, @env, @headers, @root = 200, method.downcase.to_sym, env, {'Content-Type' =>'text/html'}, env['SCRIPT_NAME'].sub(/\/$/,'') @k = query_parse(env['HTTP_COOKIE'], ';,') qs = query_parse(env['QUERY_STRING']) #puts req.read; req.rewind @in = req if %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)|n =~ (env['CONTENT_TYPE']) b = /(?:\r?\n|\A)#{Regexp::quote("--#$1")}(?:--)?\r$/ until @in.eof? fh=MerbHash[] for l in @in case l when "\r\n" : break when /^Content-Disposition: form-data;/ fh.update MerbHash[*$'.scan(/(?:\s(\w+)="([^"]+)")/).flatten] when /^Content-Type: (.+?)(\r$|\Z)/m puts "=> fh[type] = #$1" fh[:type] = $1 end end fn=fh[:name] o=if fh[:filename] o=fh[:tempfile]=Tempfile.new(:Merb) o.binmode else fh="" end while l=@in.read(16384) if l=~b o<<$`.chomp @in.seek(-$'.size,IO::SEEK_CUR) break end o< @params.delete(:sess_id)) if @params.has_key?:sess_id MERB_LOGGER.info("Params: #{params.inspect}") end def dispatch(action=:to_s) start = Time.now setup_session if respond_to?:setup_session if catch(:halt) { call_filters(before_filters) } @body = send(action) else @body = filters_halted end finalize_session if respond_to?:finalize_session MERB_LOGGER.info("Time spent in #{action} action: #{Time.now - start} seconds") end # override this method on your controller classes to specialize # the output when the filter chain is halted. def filters_halted "

Filter Chain Halted!

" end # accessor for @params. Please use params and # never @params directly. def params @params end # accessor for @cookies. Please use cookies and # never @cookies directly. def cookies @cookies end # accessor for @headers. Please use headers and # never @headers directly. def headers @headers end # meta_accessor sets up a class instance variable that can # be unique for each class but also inherits the meta attrs # from its superclasses. Since @@class variables are almost # global vars within an inheritance tree meta_accessor :before_filters def call_filters(filter_set) (filter_set || []).each do |(filter, rule)| ok = false if rule.has_key?(:include) if rule[:include].include?(params[:action].intern) ok = true end elsif rule.has_key?(:exclude) if !rule[:exclude].include?(params[:action].intern) ok = true end else ok = true end case filter when Symbol, String send(filter) if ok when Proc filter.call(self) if ok end end end # #before is a class method that allows you to specify before # filters in your controllers. Filters can either before a symbol # or string that corresponds to a method name or a proc object. # if it is a method name that method will be called and if it # is a proc it will be called with an argument of self. When # you use a proc as a filter it needs to take one parameter. def self.before(filter, opts={}) raise(ArgumentError, "You can specify either :include or :exclude but not both at the same time for the same filter." ) if opts.has_key?(:include) && opts.has_key?(:exclude) if opts[:include] && opts[:include].is_a?(Symbol) opts[:include] = [opts[:include]] end if opts[:exclude] && opts[:exclude].is_a?(Symbol) opts[:exclude] = [opts[:exclude]] end case filter when Symbol, String, Proc (self.before_filters ||= []) << [filter, opts] else raise(MerbControllerError, 'filters need to be either a Symbol, String or a Proc' ) end end if Merb::Server.config[:basic_auth] require File.dirname(__FILE__)+"/mixins/basic_authentication_mixin" include ::Merb::Authentication puts "Basic Authentication mixed in" end end end class Noroutefound < Merb::Controller # This is the class that handles requests that don't # match any defined routes. def method_missing @status = 404 "

No Matching Route!

" end end