| 3 | | module Helpers;def R c,*args;p=/\(.+?\)/;args.inject(c.urls.detect{|x|x. |
| 4 | | scan(p).size==args.size}.dup){|str,a|str.sub(p,(a.method(a.class.primary_key |
| 5 | | )[]rescue a).to_s)};end;def / p;p=~/^\//?@root+p:p end;end;module Controllers |
| 6 | | module Base;include Helpers;attr_accessor :input,:cookies,:headers,:body, |
| 7 | | :status,:root;def method_missing(m,*args,&blk);str=m==:render ? markaview( |
| 8 | | *args,&blk):eval("markaby.#{m}(*args,&blk)");str=markaview(:layout){str |
| 9 | | }rescue nil;r(200,str.to_s);end;def r(s,b,h={});@status=s;@headers.merge!(h) |
| 10 | | @body=b;end;def redirect(c,*args);c=R(c,*args)if c.respond_to?:urls;r(302,'', |
| 11 | | 'Location'=>self/c);end;def service(r,e,m,a)@status,@headers,@root=200,{},e[ |
| 12 | | 'SCRIPT_NAME'];cook=C.cookie_parse(e['HTTP_COOKIE']);qs=C.qs_parse(e[ |
| 13 | | 'QUERY_STRING']);if "POST"==m;inp=r.read(e['CONTENT_LENGTH'].to_i);if |
| 14 | | %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(e['CONTENT_TYPE']) |
| 15 | | b="--#$1";inp.split(/(?:\r?\n|\A)#{Regexp::quote(b)}(?:--)?\r\n/m).each{|pt| |
| 16 | | h,v=pt.split("\r\n\r\n",2);fh={};[:name,:filename].each{|x|fh[x]=$1 if h=~ |
| 17 | | /Content-Disposition: form-data;.*(?:\s#{x}="([^"]+)")/m};fn=fh[:name];if fh[ |
| 18 | | :filename];fh[:type]=$1 if h =~ /Content-Type: (.+?)(\r\n|\Z)/m;fh[:tempfile]= |
| 19 | | Tempfile.new("#{C}").instance_eval{binmode;write v;rewind;self};else;fh=v;end |
| 20 | | qs[fn]=fh if fn};else;qs.merge!(C.qs_parse(inp));end;end;@cookies,@input=[cook, |
| 21 | | qs].map{|_|OpenStruct.new(_)};@body=method(m.downcase).call(*a);@headers["Set-\ |
| 22 | | Cookie"]=@cookies.marshal_dump.map{|k,v|"#{k}=#{C.escape(v)}; path=/" if v != |
| 23 | | cook[k]}.compact;self;end;def to_s |
| 24 | | "Status: #{@status}\n#{{'Content-Type'=>'text/html'}.merge(@headers).map{|k,v| |
| 25 | | v.to_a.map{|v2|"#{k}: #{v2}"}}.flatten.join("\n")}\n\n#{@body}";end;def \ |
| 26 | | markaby;Mab.new(instance_variables.map{|iv|[iv[1..-1],instance_variable_get(iv |
| 27 | | )]},{}) |
| 28 | | end;def markaview(m,*args,&blk);markaby.instance_eval{Views.instance_method(m |
| 29 | | ).bind(self).call(*args, &blk);self}.to_s;end;end;class R;include Base end |
| 30 | | class NotFound<R;def get(p);r(404,div{h1("#{C} Problem!")+h2("#{p} not found") |
| 31 | | });end end;class ServerError<R;def get(k,m,e);r(500,markaby.div{h1 "#{C} Prob\ |
| 32 | | lem!";h2 "#{k}.#{m}";h3 "#{e.class} #{e.message}:";ul{e.backtrace.each{|bt|li( |
| 33 | | bt)}}})end end;class<<self;def R(*urls);Class.new(R){meta_def(:inherited){|c| |
| 34 | | c.meta_def(:urls){urls}}};end;def D(path);constants.each{|c|k=const_get(c) |
| 35 | | return k,$~[1..-1] if (k.urls rescue "/#{c.downcase}").find {|x|path=~/^#{x}\ |
| 36 | | \/?$/}};[NotFound,[path]];end end end;class<<self;def goes m;eval(S.gsub(/Ca\ |
| 37 | | mping/,m.to_s),TOPLEVEL_BINDING)end;def escape s;s.to_s.gsub( |
| 38 | | /([^ a-zA-Z0-9_.-]+)/n){'%'+$1.unpack('H2'*$1.size).join('%').upcase}.tr(' ', |
| 39 | | '+') end;def unescape(s);s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){[$1. |
| 40 | | delete('%')].pack('H*')} end;def qs_parse(qs,d ='&;');(qs||'').split(/[#{d}]\ |
| 41 | | */n).inject({}){|hsh, p|k,v=p.split('=',2).map{|v|unescape(v)};hsh[k]=v \ |
| 42 | | unless v.blank?;hsh} end; def cookie_parse(s);c=qs_parse(s,';,') end |
| | 3 | module Helpers;def R c,*args;p=/\(.+?\)/;args.inject(c.urls.detect{|x|x.scan(p |
| | 4 | ).size==args.size}.dup){|str,a|str.sub(p,(a.method(a.class.primary_key)[]rescue |
| | 5 | a).to_s)};end;def / p;p[/^\//]?@root+p:p end;end;module Controllers;module Base |
| | 6 | include Helpers;attr_accessor :input,:cookies,:headers,:body,:status,:root;def |
| | 7 | method_missing(m,*args,&blk);str=m==:render ? markaview(*args,&blk):eval( |
| | 8 | "markaby.#{m}(*args,&blk)");str=markaview(:layout){str}rescue nil;r(200,str. |
| | 9 | to_s);end;def r(s,b,h={});@status=s;@headers.merge!(h);@body=b;end;def |
| | 10 | redirect(c,*args);c=R(c,*args);r(302,'','Location'=>self/c);end;def service(r, |
| | 11 | e,m,a)@status,@headers,@root=200,{},e['SCRIPT_NAME'];cook=C.cookie_parse(e[ |
| | 12 | 'HTTP_COOKIE']);qs=C.qs_parse(e['QUERY_STRING']);if "POST"==m;inp=r.read(e[ |
| | 13 | 'CONTENT_LENGTH'].to_i);if %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"\ |
| | 14 | ?|n.match(e['CONTENT_TYPE']);b="--#$1";inp.split(/(?:\r?\n|\A)#{Regexp::quote( |
| | 15 | b)}(?:--)?\r\n/m).each{|pt|h,v=pt.split("\r\n\r\n",2);fh={};[:name,:filename]. |
| | 16 | each{|x|fh[x]=$1 if h=~/Content-Disposition: form-data;.*(?:\s#{x}="([^"]+)")\ |
| | 17 | /m};fn=fh[:name];if fh[:filename];fh[:type]=$1 if h =~ /Content-Type: (.+?)(\ |
| | 18 | \r\n|\Z)/m;fh[:tempfile]=Tempfile.new("#{C}").instance_eval{binmode;write v |
| | 19 | rewind;self};else;fh=v;end;qs[fn]=fh if fn};else;qs.merge!(C.qs_parse(inp));end |
| | 20 | end;@cookies,@input=[cook,qs].map{|_|OpenStruct.new(_)};@body=method(m.downcase |
| | 21 | ).call(*a);@headers["Set-Cookie"]=@cookies.marshal_dump.map{|k,v|"#{k}=#{C. |
| | 22 | escape(v)}; path=/" if v != cook[k]}.compact;self;end;def to_s;"Status: #{ |
| | 23 | @status}\n#{{'Content-Type'=>'text/html'}.merge(@headers).map{|k,v|v.to_a.map{ |
| | 24 | |v2|"#{k}: #{v2}"}}.flatten.join("\n")}\n\n#{@body}";end;def markaby;Mab.new( |
| | 25 | instance_variables.map{|iv|[iv[1..-1],instance_variable_get(iv)]},{});end;def |
| | 26 | markaview(m,*args,&blk);markaby.instance_eval{Views.instance_method(m).bind( |
| | 27 | self).call(*args, &blk);self}.to_s;end;end;class R;include Base end;class |
| | 28 | NotFound;def get(p);r(404,div{h1("#{C} Problem!")+h2("#{p} not found")});end |
| | 29 | end;class ServerError<R;def get(k,m,e);r(500,markaby.div{h1 "#{C} Problem!" |
| | 30 | h2 "#{k}.#{m}";h3 "#{e.class} #{e.message}:";ul{e.backtrace.each{|bt|li(bt)}}} |
| | 31 | )end end;class<<self;def R(*urls);Class.new(R){meta_def(:inherited){|c|c. |
| | 32 | meta_def(:urls){urls}}};end;def D(path);constants.inject(nil){|d,c|k= |
| | 33 | const_get(c);k.meta_def(:urls){["/#{c.downcase}"]}if !(k<R);d||([k, $~[1..-1] |
| | 34 | ] if k.urls.find { |x| path =~ /^#{x}\/?$/ })}||[NotFound, [path]];end end end |
| | 35 | class<<self;def goes m;eval(S.gsub(/Camping/,m.to_s),TOPLEVEL_BINDING)end;def |
| | 36 | escape s;s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n){'%'+$1.unpack('H2'*$1.size).join( |
| | 37 | '%').upcase}.tr(' ','+') end;def unescape(s);s.tr('+', ' ').gsub(/((?:%[0-9a-f\ |
| | 38 | A-F]{2})+)/n){[$1.delete('%')].pack('H*')} end;def qs_parse(qs,d ='&;');(qs||'' |
| | 39 | ).split(/[#{d}] */n).inject({}){|hsh, p|k,v=p.split('=',2).map{|v|unescape(v)} |
| | 40 | hsh[k]=v unless v.blank?;hsh} end; def cookie_parse(s);c=qs_parse(s,';,') end |