Changeset 235
- Timestamp:
- 10/01/2007 16:49:34 (14 months ago)
- Location:
- trunk/lib
- Files:
-
- 1 added
- 3 modified
-
camping-unabridged.rb (modified) (4 diffs)
-
camping.rb (modified) (4 diffs)
-
camping/mab.rb (added)
-
camping/server.rb (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/camping-unabridged.rb
r234 r235 29 29 # in its <tt>examples/camping</tt> directory. 30 30 # 31 %w[markaby tempfile uri].map { |l| require l } 31 %w[tempfile uri].map { |l| require l } 32 33 class Object 34 def meta_def(m,&b) 35 (class<<self;self end).instance_eval{define_method(m,&b)} 36 end 37 end 32 38 33 39 # == Camping … … 529 535 class NotFound < R() 530 536 def get(p) 531 r(404, Mab.new{h1 P;h2 p + " not found"})537 r(404, "<h1>#{P}</h1><h2>#{p} not found</h2>") 532 538 end 533 539 end … … 558 564 class ServerError < R() 559 565 def get(k,m,e) 560 r(500, Mab.new { 561 h1(P) 562 h2 "#{k}.#{m}" 563 h3 "#{e.class} #{e.message}:" 564 ul { e.backtrace.each { |bt| li bt } } 565 }) 566 r(500, "<h1>#{P}</h1><h2>#{k}.#{m}</h2><h3>#{e.class} #{e.message 567 }:<ul>#{e.backtrace.map{ |b| "<li>#{b}</li>" } }") 566 568 end 567 569 end … … 725 727 end 726 728 727 # The Mab class wraps Markaby, allowing it to run methods from Camping::Views 728 # and also to replace :href, :action and :src attributes in tags by prefixing the root 729 # path. 730 class Mab < Markaby::Builder 731 include Views 732 def tag!(*g,&b) 733 h=g[-1] 734 [:href,:action,:src].map{|a|(h[a]=self/h[a])rescue 0} 735 super 736 end 737 end 729 autoload :Mab, 'camping/mab' 738 730 end 739 731 -
trunk/lib/camping.rb
r234 r235 1 %w[markaby tempfile uri].map{|l|require l};module Camping;C=self 2 S=IO.read(__FILE__)rescue nil;P="Cam\ping Problem!";class H<Hash 3 def method_missing m,*a;m.to_s=~/=$/?self[$`]=a[0]:a==[]?self[m.to_s]:super 4 end;alias u merge!;end;module Helpers def R c,*g;p,h=/\(.+?\)/,g. 5 grep(Hash);(g-=h).inject(c.urls.find{|x|x.scan(p).size==g.size}.dup){|s,a|s. 6 sub p,C.escape((a[a.class.primary_key]rescue a))}+(h.any?? "?"+h[0]. 7 map{|x|x.map{|z|C.escape z}*"="}*"&": "")end;def /(p);p[/^\//]?@root+p:p 8 end;def URL c='/',*a;c=R(c,*a)if c.respond_to?:urls;c=self/c;c="//"+ 9 @env.HTTP_HOST+c if c[/^\//];URI(c) end end;module Base;attr_accessor:input, 10 :cookies,:env,:headers,:body,:status,:root;Z="\r\n";def method_missing*a,&b;a. 11 shift if a[0]==:render;m=Mab.new({},self);s=m.capture{send(*a,&b)};s=m.capture{ 12 send(:layout){s}}if /^_/!~a[0].to_s and m.respond_to?:layout;s end;def 13 redirect*a;r 302,'','Location'=>URL(*a)end;def r s,b,h={};@status=s;headers. 14 merge!h;@body=b end;def to_a;[status,body,headers]end;def initialize r,e,m; 1 %w[tempfile uri].map{|l|require l};class Object;def meta_def m,&b 2 (class<<self;self end).instance_eval{define_method(m,&b)}end end 3 module Camping;C=self;S=IO.read(__FILE__)rescue nil;P="Cam\ping Problem!" 4 class H<Hash;def method_missing m,*a 5 m.to_s=~/=$/?self[$`]=a[0]:a==[]?self[m.to_s]:super end;alias u merge!;end 6 module Helpers def R c,*g;p,h=/\(.+?\)/,g.grep(Hash) 7 (g-=h).inject(c.urls.find{|x|x.scan(p).size==g.size}.dup){|s,a|s.sub p,C. 8 escape((a[a.class.primary_key]rescue a))}+(h.any?? "?"+h[0].map{|x|x.map{|z|C. 9 escape z}*"="}*"&": "")end;def /(p);p[/^\//]?@root+p:p;end;def URL c='/',*a 10 c=R(c,*a)if c.respond_to?:urls;c=self/c;c="//"+@env.HTTP_HOST+c if c[/^\//] 11 URI(c) end end;module Base;attr_accessor:input,:cookies,:env,:headers,:body, 12 :status,:root;Z="\r\n";def method_missing*a,&b;a.shift if a[0]==:render 13 m=Mab.new({},self);s=m.capture{send(*a,&b)};s=m.capture{send(:layout){s}}if 14 /^_/!~a[0].to_s and m.respond_to?:layout;s end;def redirect*a 15 r 302,'','Location'=>URL(*a)end;def r s,b,h={};@status=s;headers.merge!h 16 @body=b end;def to_a;[status,body,headers]end;def initialize r,e,m 15 17 @status,@method,@env,@headers,@root=200,m.downcase,e,{ 16 18 'Content-Type'=>"text/html"},e.SCRIPT_NAME.sub(/\/$/,'');@k=C.kp e.HTTP_COOKIE 17 q=C.qsp e.QUERY_STRING;@in=r 18 case e.CONTENT_TYPEwhen %r|\Amultipart/form-.*boundary=\"?([^\";,]+)|n19 q=C.qsp e.QUERY_STRING;@in=r;case e.CONTENT_TYPE 20 when %r|\Amultipart/form-.*boundary=\"?([^\";,]+)|n 19 21 b=/(?:\r?\n|\A)#{Regexp::quote"--#$1"}(?:--)?\r$/;until 20 22 @in.eof?;fh=H[];for l in@in;case l;when Z;break;when/^Content-D.+?: form-data;/ … … 25 27 break;end;o<<k.slice!(0...s);l=@in.read(s);end;C.qsp(fn,'&;',fh,q)if fn;fh. 26 28 tempfile.rewind if fh.is_a?H;end;when "application/x-www-form-urlencoded" 27 q.u C.qsp(@in.read)end;@cookies,@input=@k.dup,q.dup end 28 def service*a;@body=send(@method,*a)if respond_to?@method29 q.u C.qsp(@in.read)end;@cookies,@input=@k.dup,q.dup end;def service*a 30 @body=send(@method,*a)if respond_to?@method 29 31 headers["Set-Cookie"]=cookies.map{|k,v|"#{k}=#{C.escape v}; path=#{self/'/'}"if 30 32 v!=@k[k]}-[nil];self end;def to_s;"Status: #@status#{Z+headers.map{|k,v|[*v]. … … 35 37 send:include,C,Base,Helpers,Models;r[0,0]=k if !r.include?k;k.meta_def(:urls){[ 36 38 "/#{c.downcase}"]}if !k.respond_to?:urls}end;end;class NotFound<R();def get p 37 r(404, Mab.new{h1 P;h2 p+" not found"})end end;class ServerError<R();def get k,38 m,e;r(500,Mab.new{h1 P;h2"#{k}.#{m}";h3"#{e.class} #{e.message}:";ul{e. 39 backtrace.each{|bt|li bt}}})end end;self;end;class<<self;def goes m;eval S. 40 gsub(/Camping/,m.to_s),TOPLEVEL_BINDING;end;def escape s;s.to_s.gsub( 41 /[^ \w.-]+/n){'%'+($&.unpack('H2'*$&.size)*'%').upcase}.tr(' ','+')end;def un s 42 s.tr('+',' ').gsub(/%([\da-f]{2})/in){[$1].pack('H*')}end;def qsp q,d='&;',y= 43 nil,z=H[];m=proc{|_,o,n|o.u(n,&m)rescue([*o]<<n)};(q.to_s.split(/[#{d}]+ */n)-['']). 44 inject((b,z=z,H[])[0]){|h,p|k,v=un(p).split('=',2);h.u k.split(/[\]\[]+/).45 reverse.inject(y||v){|x,i|H[i,x]},&m}end;def kp s;c=qsp(s,';,')end;def 46 run r=$stdin,e=ENV;X.M;e=H[e.to_hash]39 r(404,"<h1>#{P}</h1><h2>#{p} not found</h2>")end end;class ServerError<R() 40 def get k,m,e;r(500,"<h1>#{P}</h1><h2>#{k}.#{m}</h2><h3>#{e.class} #{e.message 41 }:<ul>#{e.backtrace.map{ |b| "<li>#{b}</li>" } }")end end;self;end;class<<self 42 def goes m;eval S.gsub(/Camping/,m.to_s),TOPLEVEL_BINDING;end;def escape s 43 s.to_s.gsub(/[^ \w.-]+/n){'%'+($&.unpack('H2'*$&.size)*'%').upcase}.tr(' ','+') 44 end;def un s;s.tr('+',' ').gsub(/%([\da-f]{2})/in){[$1].pack('H*')}end 45 def qsp q,d='&;',y=nil,z=H[];m=proc{|_,o,n|o.u(n,&m)rescue([*o]<<n)} 46 (q.to_s.split(/[#{d}]+ */n)-['']).inject((b,z=z,H[])[0]){|h,p|k,v=un(p). 47 split('=',2);h.u k.split(/[\]\[]+/).reverse.inject(y||v){|x,i|H[i,x]},&m}end 48 def kp s;c=qsp(s,';,')end;def run r=$stdin,e=ENV;X.M;e=H[e.to_hash] 47 49 k,a=X.D e.PATH_INFO=un("/#{e.PATH_INFO}".gsub(/\/+/,'/'));k.new( 48 50 r,e,(m=e.REQUEST_METHOD||"GET")).Y.service(*a);rescue=>x;X::ServerError.new( … … 51 53 new(a.pop).each{|e,f|k.send("#{e}=",f)}if Hash===a[-1];k.service(*a);end;end 52 54 module Views;include X,Helpers;end;module Models;autoload:Base,'camping/db';def 53 Y;self;end;end;class Mab<Markaby::Builder;include Views;def tag!*g,&b;h=g[-1] 54 [:href,:action,:src].map{|a|(h[a]=self/h[a])rescue 0};super end end end 55 Y;self;end;end;autoload:Mab,'camping/mab'end -
trunk/lib/camping/server.rb
r228 r235 1 1 require 'camping/reloader' 2 require 'markaby'3 2 4 3 module Camping::Server … … 56 55 welcome = "You are Camping" 57 56 apps = self 58 b = Markaby::Builder.new({}, {}) 59 b = b.instance_eval do 60 html do 61 head do 62 title welcome 63 style <<-END, :type => 'text/css' 64 body { 65 font-family: verdana, arial, sans-serif; 66 padding: 10px 40px; 67 margin: 0; 68 } 69 h1, h2, h3, h4, h5, h6 { 70 font-family: utopia, georgia, serif; 71 } 72 END 73 end 74 body do 75 h1 welcome 76 p %{Good day. These are the Camping apps you've mounted.} 77 ul do 78 apps.values.each do |app| 79 next unless app.klass 80 li do 81 h3(:style => "display: inline") { a app.klass.name, :href => "/#{app.mount}" } 82 small { text " / " ; a "View Source", :href => "/code/#{app.mount}" } 83 end 84 end 85 end 86 end 87 end 88 end 89 b.to_s 57 <<-HTML 58 <html> 59 <head> 60 <title>#{welcome}</title> 61 <style type="text/css"> 62 body { 63 font-family: verdana, arial, sans-serif; 64 padding: 10px 40px; 65 margin: 0; 66 } 67 h1, h2, h3, h4, h5, h6 { 68 font-family: utopia, georgia, serif; 69 } 70 </style> 71 </head> 72 <body> 73 <h1>#{welcome}</h1> 74 <p>Good day. These are the Camping apps you've mounted.</p> 75 <ul> 76 #{apps.values.select{|app|app.klass}.map do |app| 77 "<li><h3 style=\"display: inline\"><a href=\"/#{app.mount}\">#{app.klass.name}</a></h3><small> / <a href=\"/code/#{app.mount}\">View source</a></small></li>" 78 end.join("\n")} 79 </ul> 80 </body> 81 </html> 82 HTML 90 83 end 91 84
