PK:{8org/PK:{8 org/jruby/PK:{8org/jruby/rack/PK:{8org/jruby/webapp/PK:{8D2MH-org/jruby/rack/DefaultRackApplication$1.classH1N , - ./ 01 23 45 67 89:;<val$envLjavax/servlet/ServletRequest;this$0'Lorg/jruby/rack/DefaultRackApplication;H(Lorg/jruby/rack/DefaultRackApplication;Ljavax/servlet/ServletRequest;)VCodeLineNumberTableLocalVariableTablethis InnerClasses)Lorg/jruby/rack/DefaultRackApplication$1;execute(Lorg/jruby/runtime/builtin/IRubyObject;[Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/Block;)Lorg/jruby/runtime/builtin/IRubyObject;exLjava/io/IOException;recv'Lorg/jruby/runtime/builtin/IRubyObject;args([Lorg/jruby/runtime/builtin/IRubyObject;blockLorg/jruby/runtime/Block;getArity()Lorg/jruby/runtime/Arity; SourceFileDefaultRackApplication.javaEnclosingMethod= >?   @org/jruby/RubyIOA BCD EF Gjava/io/IOExceptionH IJK LM'org/jruby/rack/DefaultRackApplication$1java/lang/Object#org/jruby/runtime/callback/Callback%org/jruby/rack/DefaultRackApplicationcall=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;()V%org/jruby/runtime/builtin/IRubyObject getRuntime()Lorg/jruby/Ruby;javax/servlet/ServletRequestgetInputStream$()Ljavax/servlet/ServletInputStream;((Lorg/jruby/Ruby;Ljava/io/InputStream;)V#org/jruby/exceptions/RaiseExceptioncreateNativeRaiseExceptionL(Lorg/jruby/Ruby;Ljava/lang/Throwable;)Lorg/jruby/exceptions/RaiseException;org/jruby/runtime/Arity NO_ARGUMENTSLorg/jruby/runtime/Arity;  9*+*,*( %Y+*:+ #$%4 %% %!"%#$%&. ) '()*+  PK:{8%n* % +org/jruby/rack/DefaultRackApplication.class% 1] 1 23 4 5 67 28 69:; > ?@ AB 2C DEFGH application'Lorg/jruby/runtime/builtin/IRubyObject;adapterLorg/jruby/RubyObjectAdapter;()VCodeLineNumberTableLocalVariableTablethis'Lorg/jruby/rack/DefaultRackApplication;call=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;envLjavax/servlet/ServletRequest;runtimeLorg/jruby/Ruby; servlet_envresponseinit ExceptionsIdestroysetApplication*(Lorg/jruby/runtime/builtin/IRubyObject;)V__callP(Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; SourceFileDefaultRackApplication.java J KL  M NO PQ RSto_io'org/jruby/rack/DefaultRackApplication$1 InnerClasses TU VW -.org/jruby/rack/RackResponse XYZ [\%org/jruby/rack/DefaultRackApplicationjava/lang/Objectorg/jruby/rack/RackApplication*org/jruby/rack/RackInitializationException$org/jruby/javasupport/JavaEmbedUtilsnewObjectAdapter()Lorg/jruby/RubyObjectAdapter;%org/jruby/runtime/builtin/IRubyObject getRuntime()Lorg/jruby/Ruby; javaToRubyK(Lorg/jruby/Ruby;Ljava/lang/Object;)Lorg/jruby/runtime/builtin/IRubyObject; getMetaClass()Lorg/jruby/RubyClass;H(Lorg/jruby/rack/DefaultRackApplication;Ljavax/servlet/ServletRequest;)Vorg/jruby/RubyClass defineMethod:(Ljava/lang/String;Lorg/jruby/runtime/callback/Callback;)V rubyToJava\(Lorg/jruby/Ruby;Lorg/jruby/runtime/builtin/IRubyObject;Ljava/lang/Class;)Ljava/lang/Object;org/jruby/RubyObjectAdapter callMethod(Lorg/jruby/runtime/builtin/IRubyObject;Ljava/lang/String;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;!: **    8*M,+N- Y*+ *- :,    $,+-488!" .#$(%+ &'+1 ()*+4 +,>*+ 78-.E**+<!/0=  PK:{84org/jruby/rack/DefaultRackApplicationFactory$1.class41'    this$0.Lorg/jruby/rack/DefaultRackApplicationFactory;1(Lorg/jruby/rack/DefaultRackApplicationFactory;)VCodeLineNumberTableLocalVariableTablethis InnerClasses0Lorg/jruby/rack/DefaultRackApplicationFactory$1;create9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;runtimeLorg/jruby/Ruby; SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod" #$  % &.org/jruby/rack/DefaultRackApplicationFactory$1java/lang/ObjectEorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactoryApplicationObjectFactory,org/jruby/rack/DefaultRackApplicationFactorynewApplication"()Lorg/jruby/rack/RackApplication;()VcreateApplicationObject   4 *+* -   = *+ .   ! PK:{84org/jruby/rack/DefaultRackApplicationFactory$2.class*1'    this$0.Lorg/jruby/rack/DefaultRackApplicationFactory;1(Lorg/jruby/rack/DefaultRackApplicationFactory;)VCodeLineNumberTableLocalVariableTablethis InnerClasses0Lorg/jruby/rack/DefaultRackApplicationFactory$2;create9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;runtimeLorg/jruby/Ruby; SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod" #$  % &.org/jruby/rack/DefaultRackApplicationFactory$2java/lang/ObjectEorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactoryApplicationObjectFactory,org/jruby/rack/DefaultRackApplicationFactorynewErrorApplication"()Lorg/jruby/rack/RackApplication;()VcreateErrorApplicationObject   4 *+* e   = *+ f   ! PK:{8;L#6org/jruby/rack/DefaultRackApplicationFactory$3$1.class`1O - . /01 .2 3 4 56 7 89:;<=this$1> InnerClasses0Lorg/jruby/rack/DefaultRackApplicationFactory$3;3(Lorg/jruby/rack/DefaultRackApplicationFactory$3;)VCodeLineNumberTableLocalVariableTablethis2Lorg/jruby/rack/DefaultRackApplicationFactory$3$1; getStatus()I getHeaders()Ljava/util/Map;getBody()Ljava/lang/String;respond+(Ljavax/servlet/http/HttpServletResponse;)VexLjava/io/IOException;response(Ljavax/servlet/http/HttpServletResponse; SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod ?@  AB CDjava/lang/StringBuilder#Application initialization failed: EF GHI J" K"L MNjava/io/IOException0org/jruby/rack/DefaultRackApplicationFactory$3$1java/lang/Objectorg/jruby/rack/RackResponse.org/jruby/rack/DefaultRackApplicationFactory$3call=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;()Vjava/util/Collections EMPTY_MAPLjava/util/Map;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;val$eLjava/lang/Exception;java/lang/Exception getMessagetoString&javax/servlet/http/HttpServletResponse sendError(ILjava/lang/String;)V 4 *+*u  .r  .s !"-t #$x*+Y*  M%( w%z){ )%&**'()*+,PK:{8 '4org/jruby/rack/DefaultRackApplicationFactory$3.class11 $ % &' ()*+val$eLjava/lang/Exception;this$0.Lorg/jruby/rack/DefaultRackApplicationFactory;F(Lorg/jruby/rack/DefaultRackApplicationFactory;Ljava/lang/Exception;)VCodeLineNumberTableLocalVariableTablethis InnerClasses0Lorg/jruby/rack/DefaultRackApplicationFactory$3;init()V Exceptions,call=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;envLjavax/servlet/ServletRequest;destroy SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod- ./ 0org/jruby/rack/DefaultRackApplicationFactory$3$1 0.org/jruby/rack/DefaultRackApplicationFactory$3java/lang/Objectorg/jruby/rack/RackApplication*org/jruby/rack/RackInitializationException,org/jruby/rack/DefaultRackApplicationFactorynewErrorApplication"()Lorg/jruby/rack/RackApplication;3(Lorg/jruby/rack/DefaultRackApplicationFactory$3;)V    9*+*,*~ +o = Y*q  +~  !"#PK:{8M4org/jruby/rack/DefaultRackApplicationFactory$4.class1B ) * + , - ./0 1 2345 val$appfact6ApplicationObjectFactory InnerClassesGLorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory; val$runtimeLorg/jruby/Ruby;this$0.Lorg/jruby/rack/DefaultRackApplicationFactory;(Lorg/jruby/rack/DefaultRackApplicationFactory;Lorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;Lorg/jruby/Ruby;)VCodeLineNumberTableLocalVariableTablethis0Lorg/jruby/rack/DefaultRackApplicationFactory$4; Exceptionsinit()Vre%Lorg/jruby/exceptions/RaiseException;destroy SourceFile"DefaultRackApplicationFactory.javaEnclosingMethod7 89     :; <=#org/jruby/exceptions/RaiseException*org/jruby/rack/RackInitializationException >? @A.org/jruby/rack/DefaultRackApplicationFactory$4%org/jruby/rack/DefaultRackApplicationEorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory,org/jruby/rack/DefaultRackApplicationFactorycreateApplicationi(Lorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;)Lorg/jruby/rack/RackApplication;create9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;setApplication*(Lorg/jruby/runtime/builtin/IRubyObject;)V((Lorg/jruby/exceptions/RaiseException;)V$org/jruby/javasupport/JavaEmbedUtils terminate(Lorg/jruby/Ruby;)V  >*+*,*-*  k*** LY+  !"# 6*   $%&'(' PK:{8~qlKorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory.classl1  create9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject; SourceFile"DefaultRackApplicationFactory.java Eorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactoryApplicationObjectFactory InnerClassesjava/lang/Object,org/jruby/rack/DefaultRackApplicationFactory   PK:{8ycu2org/jruby/rack/DefaultRackApplicationFactory.class1 =z <{m |} <~   < < < < <  z   z    ' < + | / 1z 1 1 < 8 = ApplicationObjectFactory InnerClasses rackupScriptLjava/lang/String;servletContextLjavax/servlet/ServletContext; classCacheLorg/jruby/util/ClassCache;errorApplication Lorg/jruby/rack/RackApplication;()VCodeLineNumberTableLocalVariableTablethis.Lorg/jruby/rack/DefaultRackApplicationFactory;init!(Ljavax/servlet/ServletContext;)VnewApplication"()Lorg/jruby/rack/RackApplication; ExceptionsgetApplicationappfinishedWithApplication#(Lorg/jruby/rack/RackApplication;)VgetErrorApplicationdestroy newRuntime()Lorg/jruby/Ruby;binjrubyeLjava/lang/Exception;configLorg/jruby/RubyInstanceConfig;runtimeLorg/jruby/Ruby;re%Lorg/jruby/exceptions/RaiseException;createApplicationObject9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;createErrorApplicationObjectnewErrorApplicationcreateRackServletWrapperK(Lorg/jruby/Ruby;Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;rackupcreateApplicationi(Lorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;)Lorg/jruby/rack/RackApplication;rie,Lorg/jruby/rack/RackInitializationException;appfactGLorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;verify6(Lorg/jruby/Ruby;Ljava/lang/String;)Ljava/lang/String;scriptsetErrorApplication SourceFile"DefaultRackApplicationFactory.java JK DE BC  FG HI jT.org/jruby/rack/DefaultRackApplicationFactory$1 J no ST QK [Korg/jruby/RubyInstanceConfig /META-INF/jruby.home/bin/jruby    java/lang/Exceptionjava/util/ArrayList  $servlet_context  require 'rack/handler/servlet' #org/jruby/exceptions/RaiseException*org/jruby/rack/RackInitializationException J klrun JRuby::Rack::ErrorsApp.new.org/jruby/rack/DefaultRackApplicationFactory$23Warning: error application could not be initialized .org/jruby/rack/DefaultRackApplicationFactory$3 Jjava/lang/StringBuilderload 'jruby/rack/boot/rack.rb' JRuby::Rack::Bootstrap.instance.change_to_root_directory Rack::Handler::Servlet.new(Rack::Builder.new {(  )}.to_app) \].org/jruby/rack/DefaultRackApplicationFactory$4 J ,org/jruby/rack/DefaultRackApplicationFactoryjava/lang/Object%org/jruby/rack/RackApplicationFactoryEorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactoryjavax/servlet/ServletContextgetInitParameter&(Ljava/lang/String;)Ljava/lang/String;java/lang/Thread currentThread()Ljava/lang/Thread;getContextClassLoader()Ljava/lang/ClassLoader;$org/jruby/javasupport/JavaEmbedUtilscreateClassCache4(Ljava/lang/ClassLoader;)Lorg/jruby/util/ClassCache;1(Lorg/jruby/rack/DefaultRackApplicationFactory;)Vorg/jruby/rack/RackApplication setClassCache(Lorg/jruby/util/ClassCache;)Vjava/lang/Class getResource"(Ljava/lang/String;)Ljava/net/URL; java/net/URLtoURI()Ljava/net/URI; java/net/URIgetSchemeSpecificPart()Ljava/lang/String;java/lang/Stringlength()I substring(II)Ljava/lang/String; setJRubyHome(Ljava/lang/String;)V initialize@(Ljava/util/List;Lorg/jruby/RubyInstanceConfig;)Lorg/jruby/Ruby;org/jruby/RubygetGlobalVariables.()Lorg/jruby/internal/runtime/GlobalVariables; javaToRubyK(Lorg/jruby/Ruby;Ljava/lang/Object;)Lorg/jruby/runtime/builtin/IRubyObject;*org/jruby/internal/runtime/GlobalVariablessetb(Ljava/lang/String;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; evalScriptlet;(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;((Lorg/jruby/exceptions/RaiseException;)Vlog*(Ljava/lang/String;Ljava/lang/Throwable;)VF(Lorg/jruby/rack/DefaultRackApplicationFactory;Ljava/lang/Exception;)Vappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString(Lorg/jruby/rack/DefaultRackApplicationFactory;Lorg/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory;Lorg/jruby/Ruby;)V getMessage!<=>BCDEFGHIJKL3*M N OPQRLv.*+*+* * ** M"#$&%'-)N.OP.DESTL7 * Y* M,N  OPU'VTLI *L++M45 6N OPWIU'XYL?+M :;NOPWIZTL/* M>N OP[KLA* * MB CDN OP\]LdYL+* M+,, dMY+M, !,*"#W,$%W,L'Y+(/2YZ&M. HIKM/N3O?PQRXSZT[UN>^C3_`Rab?cd[ efdOPU'ghL> *+*)MZN OP cdihL<*+*)M^NOPcdjTL,*+Y*,L++L*-+./Y*+0Mc ijkl"nN  WI_`,OPklL[+1Y234,4546%MN OPcdmCnoL*7M8Y*+,9M,M'Y,('&MN4 cdpq efOPrsU'tuLg+,%:N-; M N* _`OPcdvCwYL>*+ M NOPWIxyA*?<@ +/8PK:{86l *org/jruby/rack/DefaultRackDispatcher.class 1t : ; < = >? @A BC DE FGH IJK FL IM NO PQRS ITUVWservletContextLjavax/servlet/ServletContext;!(Ljavax/servlet/ServletContext;)VCodeLineNumberTableLocalVariableTablethis&Lorg/jruby/rack/DefaultRackDispatcher;processR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)VreLjava/lang/Exception;request'Ljavax/servlet/http/HttpServletRequest;response(Ljavax/servlet/http/HttpServletResponse; rackFactory'Lorg/jruby/rack/RackApplicationFactory;app Lorg/jruby/rack/RackApplication; ExceptionsXYgetRackFactory)()Lorg/jruby/rack/RackApplicationFactory;handleException(Ljava/lang/Exception;Lorg/jruby/rack/RackApplicationFactory;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)VerrorAppe SourceFileDefaultRackDispatcher.java Z  23 [\] ^_` ab cdjava/lang/Exception 45 rack.factorye fg%org/jruby/rack/RackApplicationFactoryh ij0Error: Couldn't handle error: response committed kl mZ n\rack.exceptiono pqException caughtError: Couldn't handle error rs$org/jruby/rack/DefaultRackDispatcherjava/lang/Objectorg/jruby/rack/RackDispatcherjavax/servlet/ServletExceptionjava/io/IOException()VgetApplication"()Lorg/jruby/rack/RackApplication;org/jruby/rack/RackApplicationcall=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;org/jruby/rack/RackResponserespond+(Ljavax/servlet/http/HttpServletResponse;)VfinishedWithApplication#(Lorg/jruby/rack/RackApplication;)Vjavax/servlet/ServletContext getAttribute&(Ljava/lang/String;)Ljava/lang/Object;&javax/servlet/http/HttpServletResponse isCommitted()Zlog*(Ljava/lang/String;Ljava/lang/Throwable;)VresetgetErrorApplication%javax/servlet/http/HttpServletRequest setAttribute'(Ljava/lang/String;Ljava/lang/Object;)V sendError(I)V!F **+   !" #$\*N:-:+,;-0:*-+,  -: -.I.9IIKI6  $#%.!0"9$>%I$P%[( >0 %&\!"\'(\)*W+,T-./01239*  + !"45g *+,:-+*+-:*JM6 2 3469&:/;;<J@M=O>\?fA H&$6.O7&g!"g%&g+,g'(g)*/0189PK:{8org/jruby/rack/merb/PK:{8X5#4org/jruby/rack/PoolingRackApplicationFactory$1.class1g 2 3 4 56 578 9 0: 5; 0<= 4> ? 5@ A B CD EFG CHIJKval$appsLjava/util/Queue;this$0.Lorg/jruby/rack/PoolingRackApplicationFactory;B(Lorg/jruby/rack/PoolingRackApplicationFactory;Ljava/util/Queue;)VCodeLineNumberTableLocalVariableTablethis InnerClasses0Lorg/jruby/rack/PoolingRackApplicationFactory$1;run()Vapp Lorg/jruby/rack/RackApplication;ex,Lorg/jruby/rack/RackInitializationException; SourceFile"PoolingRackApplicationFactory.javaEnclosingMethodL MN   (O PQ RSorg/jruby/rack/RackApplication T( UV WX YZjava/lang/StringBuilder.Info: add application to the pool. size now = [\ ]^ [_ `ab cd e(*org/jruby/rack/RackInitializationException'Error: unable to initialize application cf.org/jruby/rack/PoolingRackApplicationFactory$1java/lang/Objectjava/lang/Runnable,org/jruby/rack/PoolingRackApplicationFactorylaunchInitializerThreads(Ljava/util/Queue;)Vjava/util/QueueisEmpty()Zremove()Ljava/lang/Object;init access$000A(Lorg/jruby/rack/PoolingRackApplicationFactory;)Ljava/util/Queue;add(Ljava/lang/Object;)Z access$100N(Lorg/jruby/rack/PoolingRackApplicationFactory;)Ljavax/servlet/ServletContext;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;size()I(I)Ljava/lang/StringBuilder;toString()Ljava/lang/String;javax/servlet/ServletContextlog(Ljava/lang/String;)V notifyAll*(Ljava/lang/String;Ljava/lang/Throwable;)V  9*+*,*!" #&'( TL*YM*,ç{*L,çN,-+*YM*+ W* Y  **,ç :,qL* + ,),,/,A!F '17AOy" )*+,#&-./01% PK:{8Grw2org/jruby/rack/PoolingRackApplicationFactory.classt17 X X Y  X X Z X U     X X X X U  X X X  #  Z  Z ( X Xu0 X U ;  : : Z B Yg X  U UDEFAULT_TIMEOUTI ConstantValueservletContextLjavax/servlet/ServletContext; realFactory'Lorg/jruby/rack/RackApplicationFactory;applicationPoolLjava/util/Queue; Signature3Ljava/util/Queue;initialLjava/lang/Integer;maximumtimeoutJpermits Ljava/util/concurrent/Semaphore;*(Lorg/jruby/rack/RackApplicationFactory;)VCodeLineNumberTableLocalVariableTablethis.Lorg/jruby/rack/PoolingRackApplicationFactory;factoryinit!(Ljavax/servlet/ServletContext;)VspecifiedTimeout ExceptionsnewApplication"()Lorg/jruby/rack/RackApplication;getApplicationex Ljava/lang/InterruptedException;finishedWithApplication#(Lorg/jruby/rack/RackApplication;)Vapp Lorg/jruby/rack/RackApplication;getErrorApplicationdestroy()Vi$Ljava/util/Iterator;getApplicationPool()Ljava/util/Collection;:()Ljava/util/Collection;fillInitialPoolappsLocalVariableTypeTablelaunchInitializerThreads(Ljava/util/Queue;)Vi numThreads6(Ljava/util/Queue;)VcreateApplications()Ljava/util/Queue;,Lorg/jruby/rack/RackInitializationException;5()Ljava/util/Queue;waitForNextAvailable(J)V getInitial()Ljava/lang/Integer; getMaximum getRangeValue9(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Integer;endLjava/lang/String;gsValuevgetPositiveInteger'(Ljava/lang/String;)Ljava/lang/Integer;eLjava/lang/Exception;string access$000A(Lorg/jruby/rack/PoolingRackApplicationFactory;)Ljava/util/Queue;x0 access$100N(Lorg/jruby/rack/PoolingRackApplicationFactory;)Ljavax/servlet/ServletContext; SourceFile"PoolingRackApplicationFactory.java _` cd njava/util/LinkedList jk ab vwjruby.runtime.timeout.sec java/lang/StringBuilder$Info: using runtime pool timeout of    seconds     gh ih java/util/concurrent/Semaphore n lm |{  java/lang/InterruptedException*org/jruby/rack/RackInitializationExceptiontimeout: all listeners busy n  org/jruby/rack/RackApplication   ! { "#$ % & ' () !jruby.runtime.initializer.threads *+java/lang/Thread.org/jruby/rack/PoolingRackApplicationFactory$1 InnerClasses n,JRuby-Rack-App-Init- - n. / z{javax/servlet/ServletException,Error: unable to create application for pool 0minIdle max maxActivejruby. .runtimes jruby.pool. Warning: no  runtimes specified.Info: received  runtimes = 1 23 45java/lang/Integer n6java/lang/Exception,org/jruby/rack/PoolingRackApplicationFactoryjava/lang/Object%org/jruby/rack/RackApplicationFactory longValue()Jappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;(J)Ljava/lang/StringBuilder;toString()Ljava/lang/String;javax/servlet/ServletContextlog(Ljava/lang/String;)VintValue()I(IZ)Vjava/util/concurrent/TimeUnitSECONDSLjava/util/concurrent/TimeUnit; tryAcquire#(JLjava/util/concurrent/TimeUnit;)Z*(Ljava/lang/String;Ljava/lang/Throwable;)Vjava/util/QueueisEmpty()Zremove()Ljava/lang/Object;sizeadd(Ljava/lang/Object;)Zreleaseiterator()Ljava/util/Iterator;java/util/IteratorhasNextnextjava/util/CollectionsunmodifiableCollection.(Ljava/util/Collection;)Ljava/util/Collection;valueOf(I)Ljava/lang/Integer;B(Lorg/jruby/rack/PoolingRackApplicationFactory;Ljava/util/Queue;)V(I)Ljava/lang/StringBuilder;)(Ljava/lang/Runnable;Ljava/lang/String;)Vstartwait-(Ljava/lang/Object;)Ljava/lang/StringBuilder;getInitParameter&(Ljava/lang/String;)Ljava/lang/String;parseInt(Ljava/lang/String;)I(I)V!XYZ[\]^_`abcdefghihjklmnop`**Y**+ q/*,01rstubvwp*+* + * M, *, +Y******6*** ***Y***q>45789";C=K>S?Z@rAzCEFHr st_`xhyBz{p/*qKr sty#|{p[*!** !WL#Y$+%*YL*&*'(+ð+çM+,* )",FLGILLOLq* OQTRS%V,W8XGZQ\r }~[sty#pH*YM****,ñ*++W* *,,çN,-#B$?BBEBq"`a!b$d/e6f=hGirHstH{p4 * -qlr  stp:*YL*.M,/,0(N-1+ç :+/2262qpq$r-t9ur $:stp2*2qyr step/*3L*+4*YM*& *57,çN,-&)),)q $.r/st*d *fyBpG*8 M,9M>,/:Y;Y*+<Y=>?@ϱq @Fr*4\GstGd@h Gfep<YL=*(+* A+WNBYC-D+%(#q"%()4:r*) } 0\<st4d 4fyBep *YN*E-ç :-N"qr }~ st jkp3 *FGHqr  stp3 *IJHqr  stp*YK+L N-*YM, N-'*YN+O(*YP+Q-R-q!9=ar*stkhp!*+ST= UYVMWqr* \!st!p/*q%r tp/*q%r t ;PK:{8k@;$org/jruby/rack/RackApplication.class;1  init()V Exceptionscall=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;destroy SourceFileRackApplication.javaorg/jruby/rack/RackApplicationjava/lang/Object*org/jruby/rack/RackInitializationException   PK:{8"+org/jruby/rack/RackApplicationFactory.class1init!(Ljavax/servlet/ServletContext;)V ExceptionsnewApplication"()Lorg/jruby/rack/RackApplication;getApplicationfinishedWithApplication#(Lorg/jruby/rack/RackApplication;)VgetErrorApplicationdestroy()V SourceFileRackApplicationFactory.java%org/jruby/rack/RackApplicationFactoryjava/lang/Objectjavax/servlet/ServletException*org/jruby/rack/RackInitializationException     PK:{8V^#org/jruby/rack/RackDispatcher.class-1 EXCEPTIONLjava/lang/String; ConstantValueDYNAMIC_REQS_ONLYprocessR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V Exceptions SourceFileRackDispatcher.javaorg/jruby/rack/RackDispatcherjava/lang/Objectrack.exceptionrack.dynamic.requests.onlyjavax/servlet/ServletExceptionjava/io/IOException   PK:{8uGr!org/jruby/rack/RackFilter$1.class 11  ! " # $% &'(this$0Lorg/jruby/rack/RackFilter;E(Lorg/jruby/rack/RackFilter;Ljavax/servlet/http/HttpServletRequest;)VCodeLineNumberTableLocalVariableTablethis InnerClassesLorg/jruby/rack/RackFilter$1;x0'Ljavax/servlet/http/HttpServletRequest; getPathInfo()Ljava/lang/String; SourceFileRackFilter.javaEnclosingMethod) *+ ,java/lang/StringBuilder -  ./.html 0org/jruby/rack/RackFilter$1,javax/servlet/http/HttpServletRequestWrapperorg/jruby/rack/RackFiltermaybeAppendHtmlToPathG(Ljavax/servlet/ServletRequest;)Ljavax/servlet/http/HttpServletRequest;*(Ljavax/servlet/http/HttpServletRequest;)V()Vappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString   ? *+*,t  AY*u   PK:{8̏!org/jruby/rack/RackFilter$2.class11  ! " # $% &'(this$0Lorg/jruby/rack/RackFilter;E(Lorg/jruby/rack/RackFilter;Ljavax/servlet/http/HttpServletRequest;)VCodeLineNumberTableLocalVariableTablethis InnerClassesLorg/jruby/rack/RackFilter$2;x0'Ljavax/servlet/http/HttpServletRequest;getServletPath()Ljava/lang/String; SourceFileRackFilter.javaEnclosingMethod) *+ ,java/lang/StringBuilder -  ./.html 0org/jruby/rack/RackFilter$2,javax/servlet/http/HttpServletRequestWrapperorg/jruby/rack/RackFiltermaybeAppendHtmlToPathG(Ljavax/servlet/ServletRequest;)Ljavax/servlet/http/HttpServletRequest;*(Ljavax/servlet/http/HttpServletRequest;)V()Vappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString   ? *+*,{  AY*|   PK:{8R`_Z5org/jruby/rack/RackFilter$ResponseStatusCapture.classZ17 + , - . / 0 134statusI+(Ljavax/servlet/http/HttpServletResponse;)VCodeLineNumberTableLocalVariableTablethisResponseStatusCapture InnerClasses1Lorg/jruby/rack/RackFilter$ResponseStatusCapture;response(Ljavax/servlet/http/HttpServletResponse; sendError(ILjava/lang/String;)VmessageLjava/lang/String; Exceptions5(I)V sendRedirect(Ljava/lang/String;)Vpath setStatus flushBuffer()VisError()Z access$0004(Lorg/jruby/rack/RackFilter$ResponseStatusCapture;)Zx0 SourceFileRackFilter.java $%  ! ! "#6/org/jruby/rack/RackFilter$ResponseStatusCapture-javax/servlet/http/HttpServletResponseWrapperjava/io/IOExceptionorg/jruby/rack/RackFilter    I *+*ȵ>; ?  H* BC  >* FG I *.*+JK L  !R***OP QS !]** *,VW XZ  "#> **]^ `  $%:*c &'/*: ()* 2 PK:{8@l org/jruby/rack/RackFilter.class 71 K LM NO P QRS T UV W XY Z[ \]^ _` a bc K d e fgh jk jlmnResponseStatusCapture InnerClasses dispatcherLorg/jruby/rack/RackDispatcher;()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/rack/RackFilter;"(Lorg/jruby/rack/RackDispatcher;)Vdispinit(Ljavax/servlet/FilterConfig;)VconfigLjavax/servlet/FilterConfig; ExceptionsodoFilter[(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)VrequestLjavax/servlet/ServletRequest;responseLjavax/servlet/ServletResponse;chainLjavax/servlet/FilterChain; httpRequest'Ljavax/servlet/http/HttpServletRequest; httpResponse(Ljavax/servlet/http/HttpServletResponse;capture1Lorg/jruby/rack/RackFilter$ResponseStatusCapture;pdestroymaybeAppendHtmlToPathG(Ljavax/servlet/ServletRequest;)Ljavax/servlet/http/HttpServletRequest; servletPathLjava/lang/String;pathInfouri SourceFileRackFilter.java $% "#$org/jruby/rack/DefaultRackDispatcherq rs $t CD&javax/servlet/http/HttpServletResponse/org/jruby/rack/RackFilter$ResponseStatusCapture $uv 3w xy z%rack.dynamic.requests.only{ |}~ %javax/servlet/http/HttpServletRequest java/lang/StringBuilder  org/jruby/rack/RackFilter$1 $org/jruby/rack/RackFilter$2org/jruby/rack/RackFilterjava/lang/Objectjavax/servlet/Filterjavax/servlet/ServletExceptionjava/io/IOExceptionjavax/servlet/FilterConfiggetServletContext ()Ljavax/servlet/ServletContext;!(Ljavax/servlet/ServletContext;)V+(Ljavax/servlet/http/HttpServletResponse;)Vjavax/servlet/FilterChain@(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V access$0004(Lorg/jruby/rack/RackFilter$ResponseStatusCapture;)Zresetjava/lang/BooleanTRUELjava/lang/Boolean;javax/servlet/ServletRequest setAttribute'(Ljava/lang/String;Ljava/lang/Object;)Vorg/jruby/rack/RackDispatcherprocessR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)VgetServletPath()Ljava/lang/String; getPathInfoappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toStringjava/lang/String lastIndexOf(I)IE(Lorg/jruby/rack/RackFilter;Ljavax/servlet/http/HttpServletRequest;)V!"#$%&3*' ( )*$+&F **+'!" #( )* ,#-.&J*Y+' '(()*/01234&L*+:,:Y :-  $ + *+'& ,- ./"0*112<3K5(HL)*L56L78L9:E;< ?=>4?@1A2B%&+'8( )*CD&a+M,N,:-:Y:./Y*,M Y*,M,'. hi jkmn2pCqHrUy_(>a)*a56\;< UEFMGFJHFIJ! PK:{8~E0org/jruby/rack/RackInitializationException.classx1D ( )* + ,- ./ 012 +3 4 .5 / /67((Lorg/jruby/exceptions/RaiseException;)VCodeLineNumberTableLocalVariableTablethis,Lorg/jruby/rack/RackInitializationException;re%Lorg/jruby/exceptions/RaiseException;exceptionMessage9(Lorg/jruby/exceptions/RaiseException;)Ljava/lang/String;stLjava/lang/StringBuilder;bLjava/io/ByteArrayOutputStream;*(Ljava/lang/String;Ljava/lang/Throwable;)VmsgLjava/lang/String;exLjava/lang/Throwable; SourceFile RackInitializationException.java  !java/lang/StringBuilder 89 :;< => ?@ java/io/ByteArrayOutputStreamjava/io/PrintStream A BC*org/jruby/rack/RackInitializationExceptionjava/lang/Exception()V#org/jruby/exceptions/RaiseException getException()Lorg/jruby/RubyException;org/jruby/RubyExceptiontoString()Ljava/lang/String;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;(Ljava/io/OutputStream;)VprintBacktrace(Ljava/io/PrintStream;)V!B *++     D*AYL+*W Y M* Y, +,W+" %4=B  6% D!I*+,  ! "#$%&'PK:{8u9w)$!org/jruby/rack/RackResponse.class$1  getStatus()I getHeaders()Ljava/util/Map;getBody()Ljava/lang/String;respond+(Ljavax/servlet/http/HttpServletResponse;)V SourceFileRackResponse.javaorg/jruby/rack/RackResponsejava/lang/Object   PK:{819 org/jruby/rack/RackServlet.classn19 $ %& '( )*+ ,-./ dispatcherLorg/jruby/rack/RackDispatcher;()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/rack/RackServlet;"(Lorg/jruby/rack/RackDispatcher;)Vinit (Ljavax/servlet/ServletConfig;)VconfigLjavax/servlet/ServletConfig;service@(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)VrequestLjavax/servlet/ServletRequest;responseLjavax/servlet/ServletResponse; Exceptions01 SourceFileRackServlet.java  $org/jruby/rack/DefaultRackDispatcher2 34 5%javax/servlet/http/HttpServletRequest&javax/servlet/http/HttpServletResponse6 78org/jruby/rack/RackServletjavax/servlet/http/HttpServletjavax/servlet/ServletExceptionjava/io/IOExceptionjavax/servlet/ServletConfiggetServletContext ()Ljavax/servlet/ServletContext;!(Ljavax/servlet/ServletContext;)Vorg/jruby/rack/RackDispatcherprocessR(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V!   3*   F **+   J*Y+ $%T*+, *+  !"#PK:{8/org/jruby/rack/RackServletContextListener.class1W 2 3 45 67 89 :;< 8= 8>? @ 8ABC 2 DEFG FACTORY_KEYLjava/lang/String; ConstantValuefactory'Lorg/jruby/rack/RackApplicationFactory;()VCodeLineNumberTableLocalVariableTablethis+Lorg/jruby/rack/RackServletContextListener;*(Lorg/jruby/rack/RackApplicationFactory;)VfactoryForTestcontextInitialized&(Ljavax/servlet/ServletContextEvent;)VexLjava/lang/Exception;ctxEvent#Ljavax/servlet/ServletContextEvent;ctxLjavax/servlet/ServletContext;faccontextDestroyednewApplicationFactory)()Lorg/jruby/rack/RackApplicationFactory; SourceFileRackServletContextListener.java  H IJ ./ rack.factoryK LM NOjava/lang/Exception(Error: application initialization failed PQ RS%org/jruby/rack/RackApplicationFactory T UV+org/jruby/rack/SharedRackApplicationFactory,org/jruby/rack/DefaultRackApplicationFactory ")org/jruby/rack/RackServletContextListenerjava/lang/Object$javax/servlet/ServletContextListener!javax/servlet/ServletContextEventgetServletContext ()Ljavax/servlet/ServletContext;javax/servlet/ServletContext setAttribute'(Ljava/lang/String;Ljava/lang/Object;)Vinit!(Ljavax/servlet/ServletContext;)Vlog*(Ljava/lang/String;Ljava/lang/Throwable;)V getAttribute&(Ljava/lang/String;)Ljava/lang/Object;destroyremoveAttribute(Ljava/lang/String;)V!< **   !"F **+  ! #$%*+M*N,--,:,  ""# $&)'()*4 &'* !*()%*+ ,-%$+M,  N-- ,-.012#4*$ !$()*+,./M**YY78 ;  !01PK:{8M4/org/jruby/rack/RackTag$1.class/1= & '() * $+ ,- $. /01this$0Lorg/jruby/rack/RackTag;B(Lorg/jruby/rack/RackTag;Ljavax/servlet/http/HttpServletRequest;)VCodeLineNumberTableLocalVariableTablethis InnerClassesLorg/jruby/rack/RackTag$1;x0'Ljavax/servlet/http/HttpServletRequest; getMethod()Ljava/lang/String; getRequestURI getPathInfogetQueryStringgetServletPath SourceFile RackTag.javaEnclosingMethod2 34  5GETjava/lang/StringBuilder 6 78 9:? ;8 <org/jruby/rack/RackTag$1,javax/servlet/http/HttpServletRequestWrapperorg/jruby/rack/RackTagdoEndTag()I*(Ljavax/servlet/http/HttpServletRequest;)V()V access$000,(Lorg/jruby/rack/RackTag;)Ljava/lang/String;append-(Ljava/lang/String;)Ljava/lang/StringBuilder; access$100toString ? *+*,!  - N$Y**   $2* 2*    - ! !"#$%  PK:{8ձ|c ^ org/jruby/rack/RackTag.class^ 1p 8 9 : ; <=> ?@A BC <FG H IJ <K LM NO PQR STUpathLjava/lang/String;params()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/rack/RackTag;setPath(Ljava/lang/String;)V setParamsdoEndTag()Irequest'Ljavax/servlet/http/HttpServletRequest;resultLorg/jruby/rack/RackResponse;factory'Lorg/jruby/rack/RackApplicationFactory;app Lorg/jruby/rack/RackApplication;eLjava/lang/Exception; Exceptions access$000,(Lorg/jruby/rack/RackTag;)Ljava/lang/String;x0 access$100 SourceFile RackTag.java    VWX YZ rack.factory[ \]%org/jruby/rack/RackApplicationFactory ^_org/jruby/rack/RackTag$1 InnerClasses `a%javax/servlet/http/HttpServletRequest bc de fgh ijk l# mnjava/lang/Exceptionjavax/servlet/jsp/JspException oorg/jruby/rack/RackTag#javax/servlet/jsp/tagext/TagSupport pageContextLjavax/servlet/jsp/PageContext;javax/servlet/jsp/PageContextgetServletContext ()Ljavax/servlet/ServletContext;javax/servlet/ServletContext getAttribute&(Ljava/lang/String;)Ljava/lang/Object;getApplication"()Lorg/jruby/rack/RackApplication; getRequest ()Ljavax/servlet/ServletRequest;B(Lorg/jruby/rack/RackTag;Ljavax/servlet/http/HttpServletRequest;)Vorg/jruby/rack/RackApplicationcall=(Ljavax/servlet/ServletRequest;)Lorg/jruby/rack/RackResponse;getOut()Ljavax/servlet/jsp/JspWriter;org/jruby/rack/RackResponsegetBody()Ljava/lang/String;javax/servlet/jsp/JspWriterwritefinishedWithApplication#(Lorg/jruby/rack/RackApplication;)V(Ljava/lang/Throwable;)V!/*  !"#>*+   !$#>*+  !%& l*L+ M Y** N,-:*+,:+, LY+FPPRP\_2 ,#5$F&M'P&\*_(`)i+>,'(5)*J+,C-.` /0l !123/* 4!53/* 4!67E  PK:{8org/jruby/rack/rails/PK:{8<1org/jruby/rack/SharedRackApplicationFactory.class1E / 0 1 2 345 678 9 2 : ;<=>? realFactory'Lorg/jruby/rack/RackApplicationFactory; application Lorg/jruby/rack/RackApplication;*(Lorg/jruby/rack/RackApplicationFactory;)VCodeLineNumberTableLocalVariableTablethis-Lorg/jruby/rack/SharedRackApplicationFactory;factoryinit!(Ljavax/servlet/ServletContext;)Vex,Lorg/jruby/rack/RackInitializationException;servletContextLjavax/servlet/ServletContext; ExceptionsnewApplication"()Lorg/jruby/rack/RackApplication;getApplicationfinishedWithApplication#(Lorg/jruby/rack/RackApplication;)VappgetErrorApplicationdestroy()V SourceFile!SharedRackApplicationFactory.java ,   &% *org/jruby/rack/RackInitializationException,unable to create shared application instance@ ABjavax/servlet/ServletException C *%D +,+org/jruby/rack/SharedRackApplicationFactoryjava/lang/Object%org/jruby/rack/RackApplicationFactoryjavax/servlet/ServletContextlog*(Ljava/lang/String;Ljava/lang/Throwable;)V(Ljava/lang/Throwable;)Vorg/jruby/rack/RackApplication!F **+   .*+**M+, Y,  $-   ..!"# $%/* # #&%/*' #'(5+)*%4 * .  +,8 *  2 3  -.PK:{8S4id4org/jruby/rack/merb/MerbRackApplicationFactory.classd1"   ()VCodeLineNumberTableLocalVariableTablethis0Lorg/jruby/rack/merb/MerbRackApplicationFactory;createApplicationObject9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;runtimeLorg/jruby/Ruby; SourceFileMerbRackApplicationFactory.java  load 'jruby/rack/boot/merb.rb'  run JRuby::Rack::MerbFactory.new !.org/jruby/rack/merb/MerbRackApplicationFactory,org/jruby/rack/DefaultRackApplicationFactoryorg/jruby/Ruby evalScriptlet;(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;createRackServletWrapperK(Lorg/jruby/Ruby;Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;!  /*    G+W*+   PK:{8ڔơ4org/jruby/rack/merb/MerbServletContextListener.classc1   ()VCodeLineNumberTableLocalVariableTablethis0Lorg/jruby/rack/merb/MerbServletContextListener;newApplicationFactory)()Lorg/jruby/rack/RackApplicationFactory; SourceFileMerbServletContextListener.java  +org/jruby/rack/SharedRackApplicationFactory.org/jruby/rack/merb/MerbRackApplicationFactory .org/jruby/rack/merb/MerbServletContextListener)org/jruby/rack/RackServletContextListener*(Lorg/jruby/rack/RackApplicationFactory;)V!  /*    9YY   PK:{8¼Dpk6org/jruby/rack/rails/RailsRackApplicationFactory.classk1"   ()VCodeLineNumberTableLocalVariableTablethis2Lorg/jruby/rack/rails/RailsRackApplicationFactory;createApplicationObject9(Lorg/jruby/Ruby;)Lorg/jruby/runtime/builtin/IRubyObject;runtimeLorg/jruby/Ruby; SourceFile RailsRackApplicationFactory.java  load 'jruby/rack/boot/rails.rb' !run JRuby::Rack::RailsFactory.new !0org/jruby/rack/rails/RailsRackApplicationFactory,org/jruby/rack/DefaultRackApplicationFactoryorg/jruby/Ruby evalScriptlet;(Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;createRackServletWrapperK(Lorg/jruby/Ruby;Ljava/lang/String;)Lorg/jruby/runtime/builtin/IRubyObject;!  /*    G+W*+   PK:{8ގ6org/jruby/rack/rails/RailsServletContextListener.class[1   ()VCodeLineNumberTableLocalVariableTablethis2Lorg/jruby/rack/rails/RailsServletContextListener;newApplicationFactory)()Lorg/jruby/rack/RackApplicationFactory; SourceFile RailsServletContextListener.java  ,org/jruby/rack/PoolingRackApplicationFactory0org/jruby/rack/rails/RailsRackApplicationFactory 0org/jruby/rack/rails/RailsServletContextListener)org/jruby/rack/RackServletContextListener*(Lorg/jruby/rack/RackApplicationFactory;)V!  /*    9YY   PK:{8_3."org/jruby/webapp/FileServlet.class.1  ()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/webapp/FileServlet; SourceFileFileServlet.java org/jruby/webapp/FileServletorg/jruby/rack/RackServlet!/*     PK:{8d_+org/jruby/webapp/RailsContextListener.class_1  ()VCodeLineNumberTableLocalVariableTablethis'Lorg/jruby/webapp/RailsContextListener; SourceFileRailsContextListener.java %org/jruby/webapp/RailsContextListener0org/jruby/rack/rails/RailsServletContextListener!/*     PK:{861#org/jruby/webapp/RailsServlet.class11  ()VCodeLineNumberTableLocalVariableTablethisLorg/jruby/webapp/RailsServlet; SourceFileRailsServlet.java org/jruby/webapp/RailsServletorg/jruby/rack/RackServlet!/*     PK:{8cgi/PK:{8jruby/PK:{8rack/PK:{8qo( # rack.rb# # Copyright (C) 2007, 2008 Christian Neukirchen # # Rack is freely distributable under the terms of an MIT-style license. # See COPYING or http://www.opensource.org/licenses/mit-license.php. $: << File.expand_path(File.dirname(__FILE__)) # The Rack main module, serving as a namespace for all core Rack # modules and classes. # # All modules meant for use in your application are autoloaded here, # so it should be enough just to require rack.rb in your code. module Rack # The Rack protocol version number implemented. VERSION = [0,1] # Return the Rack protocol version as a dotted string. def self.version VERSION.join(".") end autoload :Builder, "rack/builder" autoload :Cascade, "rack/cascade" autoload :CommonLogger, "rack/commonlogger" autoload :File, "rack/file" autoload :ForwardRequest, "rack/recursive" autoload :Lint, "rack/lint" autoload :Recursive, "rack/recursive" autoload :Reloader, "rack/reloader" autoload :ShowExceptions, "rack/showexceptions" autoload :ShowStatus, "rack/showstatus" autoload :Static, "rack/static" autoload :URLMap, "rack/urlmap" autoload :Utils, "rack/utils" autoload :MockRequest, "rack/mock" autoload :MockResponse, "rack/mock" autoload :Request, "rack/request" autoload :Response, "rack/response" module Auth autoload :Basic, "rack/auth/basic" autoload :AbstractRequest, "rack/auth/abstract/request" autoload :AbstractHandler, "rack/auth/abstract/handler" autoload :OpenID, "rack/auth/openid" module Digest autoload :MD5, "rack/auth/digest/md5" autoload :Nonce, "rack/auth/digest/nonce" autoload :Params, "rack/auth/digest/params" autoload :Request, "rack/auth/digest/request" end end module Session autoload :Cookie, "rack/session/cookie" autoload :Pool, "rack/session/pool" autoload :Memcache, "rack/session/memcache" end # *Adapters* connect Rack with third party web frameworks. # # Rack includes an adapter for Camping, see README for other # frameworks supporting Rack in their code bases. # # Refer to the submodules for framework-specific calling details. module Adapter autoload :Camping, "rack/adapter/camping" end # *Handlers* connect web servers with Rack. # # Rack includes Handlers for Mongrel, WEBrick, FastCGI, CGI, SCGI # and LiteSpeed. # # Handlers usually are activated by calling MyHandler.run(myapp). # A second optional hash can be passed to include server-specific # configuration. module Handler autoload :CGI, "rack/handler/cgi" autoload :FastCGI, "rack/handler/fastcgi" autoload :Mongrel, "rack/handler/mongrel" autoload :WEBrick, "rack/handler/webrick" autoload :LSWS, "rack/handler/lsws" autoload :SCGI, "rack/handler/scgi" end end PK:{8 cgi/session/PK:{85n !cgi/session/java_servlet_store.rb class CGI #:nodoc:all class Session class JavaServletStore RAILS_SESSION_KEY = "__current_rails_session" def initialize(session, option=nil) @java_request = option["java_servlet_request"] if option unless @java_request raise 'JavaServletStore requires that HttpServletRequest is made available to the session' end @digest = option['digest'] || 'SHA1' @session_data = {} end # Restore session state from the Java session def restore @session_data = {} java_session = @java_request.getSession(false) if java_session java_session.getAttributeNames.each do |k| if k == RAILS_SESSION_KEY marshalled_bytes = java_session.getAttribute(RAILS_SESSION_KEY) if marshalled_bytes data = Marshal.load(String.from_java_bytes(marshalled_bytes)) @session_data.update data if Hash === data end else @session_data[k] = java_session.getAttribute(k) end end end @session_data end # Save session state to the Java session def update java_session = @java_request.getSession(true) hash = @session_data.dup hash.delete_if do |k,v| if String === k case v when String, Numeric, true, false, nil java_session.setAttribute k, v true else if v.respond_to?(:java_object) java_session.setAttribute k, v true else false end end end end unless hash.empty? marshalled_string = Marshal.dump(hash) marshalled_bytes = marshalled_string.to_java_bytes java_session.setAttribute(RAILS_SESSION_KEY, marshalled_bytes) end end # Update and close the Java session entry def close update end # Delete the Java session entry def delete java_session = @java_request.getSession(false) java_session.invalidate if java_session end def generate_digest(data) java_session = @java_request.getSession(true) @secret ||= java_session.getAttribute("__rails_secret") unless @secret @secret = java_session.getId + java_session.getLastAccessedTime.to_s java_session.setAttribute("__rails_secret", @secret) end OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@digest), @secret, data) end # The session state def data @session_data end def []=(k, v) @session_data[k] = v end def [](k) @session_data[k] end def each(&b) @session_data.each(&b) end private # Attempts to redirect any messages to the data object. def method_missing(name, *args, &block) @session_data.send(name, *args, &block) end end end end PK:{8 jruby/rack/PK:{8B750 jruby/rack.rb0#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'rack' require 'time' # some of rack uses Time#rfc822 but doesn't pull this in require 'jruby/rack/servlet_helper' require 'jruby/rack/servlet_ext'PK:{8jruby/rack/boot/PK:{8 3 jruby/rack/merb.rb [require 'jruby/rack' require 'cgi/session/java_servlet_store' module JRuby module Rack class MerbServletHelper < ::JRuby::Rack::ServletHelper attr_reader :merb_environment, :merb_root def initialize(servlet_context = nil) super @merb_root = @servlet_context.getInitParameter('merb.root') @merb_root ||= '/WEB-INF' @merb_root = expand_root_path @merb_root @merb_environment = @servlet_context.getInitParameter('merb.environment') @merb_environment ||= 'production' end def load_environment load_merb setup_adapter setup_sessions start_merb end def load_merb framework = File.expand_path(File.join(@merb_root, 'framework')) if File.directory?(framework) logger.debug("Trying to load Merb from #{framework}") core = File.join(framework, 'merb-core') if File.directory?(core) $LOAD_PATH.push File.join(core, 'lib') end more = File.join(framework, 'merb-more') if File.directory?(more) Dir.new(more).select {|d| d =~ /merb-/}.each do |d| $LOAD_PATH.push File.join(more, d, 'lib') end end plugins = File.join(framework, 'merb-plugins') if File.directory?(plugins) Dir.new(plugins).select {|d| d =~ /merb_/}.each do |d| $LOAD_PATH.push File.join(plugins, d, 'lib') end end else logger.debug("Didn't find a framework/ directory, falling back to Rubygems") require 'rubygems' end require 'merb-core' require 'merb-core/rack' Merb.frozen! end def setup_adapter logger.debug('Registering Merb servlet adapter') Merb::Rack::Adapter.register %w{servlet}, :Servlet end def setup_sessions logger.debug('Registering Merb servlet sessions') Merb.register_session_type 'servlet', 'jruby/rack/merb', 'Using Java servlet sessions' end def start_merb logger.debug('Starting Merb') Merb.start :merb_root => merb_root, :environment => merb_environment, :adapter => 'servlet' end end class MerbFactory def self.new MerbServletHelper.instance.load_environment ::Rack::Builder.new { run ::Merb::Config[:app] }.to_app end end end end # Merb likes to hardcode things into the Merb:: namespace. module Merb module Rack class Servlet def self.start(opts={}) Merb.logger.info("Using Java servlet adapter") if self == Merb::Rack::Servlet Merb.logger.flush end end end module SessionMixin def setup_session Merb.logger.info("Setting Up Java servlet session") opts = {'java_servlet_request' => request.env['java.servlet_request']} request.session = CGI::Session::JavaServletStore.new(nil, opts) request.session.restore end def finalize_session Merb.logger.info("Finalizing Java servlet session") request.session.update end def session_store_type "servlet" end end end PK:{8tHqtojruby/rack/rails.rbo#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'jruby/rack' module JRuby module Rack class RailsServletHelper < ServletHelper attr_accessor :rails_env, :rails_root def initialize(servlet_context = nil) super @rails_root = @servlet_context.getInitParameter 'rails.root' @rails_root ||= '/WEB-INF' @rails_root = expand_root_path @rails_root @rails_env = @servlet_context.getInitParameter 'rails.env' @rails_env ||= 'production' ENV['RAILS_ROOT'] = @rails_root ENV['RAILS_ENV'] = @rails_env silence_warnings { Object.const_set("PUBLIC_ROOT", public_root) } end def load_environment require 'cgi/session/java_servlet_store' require 'jruby/rack/rails_boot' load File.join(rails_root, 'config', 'environment.rb') require 'dispatcher' require 'jruby/rack/rails_ext' setup_sessions setup_logger end # This hook method is called back from within the mechanism installed # by rails_boot above. We're setting appropriate defaults for the # servlet environment here that can still be overridden (if desired) in # the application's environment files. def boot_for_servlet_environment(initializer) initializer_class = initializer.class initializer_class.module_eval do alias_method :require_frameworks_without_servlet_env, :require_frameworks def require_frameworks_with_servlet_env JRuby::Rack::RailsServletHelper.instance.before_require_frameworks require_frameworks_without_servlet_env JRuby::Rack::RailsServletHelper.instance.setup_actionpack end alias_method :require_frameworks, :require_frameworks_with_servlet_env end end def before_require_frameworks Rails.public_path = PUBLIC_ROOT if defined?(Rails.public_path) end def setup_actionpack ActionController::Base.session_store = :java_servlet_store unless defined?(Rails.public_path) ActionController::Base.page_cache_directory = PUBLIC_ROOT silence_warnings do asset_tag_helper = ActionView::Helpers::AssetTagHelper asset_tag_helper.const_set("ASSETS_DIR", PUBLIC_ROOT) asset_tag_helper.const_set("JAVASCRIPTS_DIR", "#{PUBLIC_ROOT}/javascripts") asset_tag_helper.const_set("STYLESHEETS_DIR", "#{PUBLIC_ROOT}/stylesheets") end end end def setup_sessions if default_sessions? session_options[:database_manager] = java_servlet_store end # Turn off default cookies when using Java sessions if java_sessions? session_options[:no_cookies] = true end end def setup_logger if defined?(::RAILS_DEFAULT_LOGGER) class << ::RAILS_DEFAULT_LOGGER # Make these accessible to wire in the log device public :instance_variable_get, :instance_variable_set end # use config.logger? if defined?(ActiveSupport::BufferedLogger) # Rails 2.x old_device = ::RAILS_DEFAULT_LOGGER.instance_variable_get "@log" old_device.close rescue nil ::RAILS_DEFAULT_LOGGER.instance_variable_set "@log", logdev else # Rails 1.x old_device = ::RAILS_DEFAULT_LOGGER.instance_variable_get "@logdev" old_device.close rescue nil ::RAILS_DEFAULT_LOGGER.instance_variable_set "@logdev", Logger::LogDevice.new(logdev) end end end def session_options @session_options ||= SESSION_OPTIONS end def session_options_for_request(env) options = session_options.dup options[:java_servlet_request] = env['java.servlet_request'] options end def java_sessions? session_options[:database_manager] == java_servlet_store end def default_sessions? session_options[:database_manager] == default_store end def default_store defined?(::CGI::Session::PStore) && CGI::Session::PStore end def java_servlet_store CGI::Session::JavaServletStore end def options {:public => public_root, :root => rails_root, :environment => rails_env} end end Bootstrap = RailsServletHelper class RailsSetup def initialize(app, servlet_helper) @app = app @servlet_helper = servlet_helper end def call(env) env['rails.session_options'] = @servlet_helper.session_options_for_request(env) env['RAILS_RELATIVE_URL_ROOT'] = env['java.servlet_request'].getContextPath env['HTTPS'] = 'on' if env['rack.url_scheme'] == 'https' @app.call(env) end end class RailsFactory def self.new helper = RailsServletHelper.instance helper.load_environment ::Rack::Builder.new { use RailsSetup, helper run ::Rack::Adapter::Rails.new(helper.options) }.to_app end end end endPK:{8jruby/rack/rails_boot.rb#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ module Rails # This hook code exists to allow us to hook into the Rails boot sequence so # that we can set some additional defaults that are more friendly to the servlet # environment, but still can be overridden by the application in the Rails # initializer. # # Only for Rails 2.0, unfortunately. This code is mildly evil, but we're hoping # the Rails booter code won't change too much. class BootHook def initialize(real_boot) @real_boot = real_boot end def run result = @real_boot.run JRuby::Rack::RailsServletHelper.instance.boot_for_servlet_environment(result) result end def custom_boot end end class Boot # Hook into methods added for Rails::Boot, and redefine Rails.pick_boot. # Only needs to be done once, so remove the method_added hook when done. def self.method_added(meth) class << ::Rails alias_method :original_pick_boot, :pick_boot def pick_boot BootHook.new(original_pick_boot) end end class << self; remove_method :method_added; end end end endPK:{86(#jruby/rack/rails_ext.rb##-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'action_controller' module ActionController class CgiRequest #:nodoc: # Replace session_options writer to merge session options # With ones passed into request (so we can preserve the # java servlet request) def session_options=(opts) if opts == false @session_options = false elsif @session_options @session_options.update(opts) else @session_options = opts end end end class Base def servlet_request request.env['java.servlet_request'] end def forward_to(url) @performed_render = true req = servlet_request response.headers['Forward'] = proc do |resp| req.getRequestDispatcher(url).forward(req, resp) end end end module Rescue # Rails 2.0 static rescue files def render_optional_error_file(status_code) #:nodoc: status = interpret_status(status_code) path = "#{PUBLIC_ROOT}/#{status[0,3]}.html" if File.exists?(path) render :file => path, :status => status else head status end end def rescue_action_in_public(exception) #:nodoc: if respond_to?(:render_optional_error_file) # Rails 2 render_optional_error_file response_code_for_rescue(exception) else # Rails 1 case exception when RoutingError, UnknownAction render_text(IO.read(File.join(PUBLIC_ROOT, '404.html')), "404 Not Found") else render_text(IO.read(File.join(PUBLIC_ROOT, '500.html')), "500 Internal Error") end end end end end module JRuby::Rack SESSION_OPTIONS = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS end PK:{8~ŭjruby/rack/servlet_ext.rbz#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ # Ruby-friendly extensions to the servlet API. module Java::JavaxServletHttp::HttpServletRequest # Fetch an attribute from the servlet request. def [](key) getAttribute(key.to_s) end # Set an attribute in the servlet request. def []=(key, val) setAttribute(key.to_s, val) end # Retrieve all the attribute names (keys) from the servlet request. def keys getAttributeNames.to_a end end module Java::JavaxServletHttp::HttpSession # Fetch an attribute from the session. def [](key) getAttribute(key.to_s) end # Set an attribute in the session. def []=(key, val) setAttribute(key.to_s, val) end # Retrieve all the attribute names (keys) from the session. def keys getAttributeNames.to_a end end PK:{8}zVjruby/rack/servlet_helper.rb#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ module JRuby module Rack def self.silence_warnings oldv, $VERBOSE = $VERBOSE, nil begin yield ensure $VERBOSE = oldv end end class Response include Java::org.jruby.rack.RackResponse def initialize(arr) @status, @headers, @body = *arr end def getStatus @status end def getHeaders @headers end def getBody b = "" @body.each {|part| b << part } b end def respond(response) if fwd = @headers["Forward"] fwd.call(response) else write_status(response) write_headers(response) write_body(response) end end def write_status(response) response.setStatus(@status.to_i) end def write_headers(response) @headers.each do |k,v| case k when /^Content-Type$/i response.setContentType(v.to_s) when /^Content-Length$/i response.setContentLength(v.to_i) else if v.respond_to?(:each) v.each {|val| response.addHeader(k.to_s, val) } else case v when Numeric response.addIntHeader(k.to_s, v.to_i) when Time response.addDateHeader(k.to_s, v.to_i * 1000) else response.addHeader(k.to_s, v.to_s) end end end end end def write_body(response) stream = response.getOutputStream begin @body.each do |el| stream.write(el.to_java_bytes) end rescue LocalJumpError => e # HACK: deal with objects that don't comply with Rack specification @body = [@body.to_s] retry end end end class ServletLog def initialize(context = $servlet_context) @context = context end def puts(msg) write msg.to_s end def write(msg) @context.log(msg) end def flush; end def close; end end class ServletHelper attr_reader :public_root, :gem_path def initialize(servlet_context = nil) @servlet_context = servlet_context || $servlet_context @public_root = @servlet_context.getInitParameter 'public.root' @public_root ||= @servlet_context.getInitParameter 'files.prefix' # Goldspike @public_root ||= '/WEB-INF/public' @public_root = "/#{@public_root}" unless @public_root =~ %r{^/} @public_root = expand_root_path @public_root @public_root = @public_root.chomp("/") $0 = File.join(root_path, "web.xml") @gem_path = @servlet_context.getInitParameter 'gem.path' @gem_path ||= '/WEB-INF/gems' @gem_path = expand_root_path @gem_path setup_gems ServletHelper.instance = self end def root_path @root_path ||= real_path('/WEB-INF') end def real_path(path) @servlet_context.getRealPath(path) end def expand_root_path(path) if path =~ %r{^/WEB-INF} path.sub(%r{^/WEB-INF}, root_path) else real_path path end end def logdev @logdev ||= ServletLog.new @servlet_context end def logger @logger ||= begin; require 'logger'; Logger.new(logdev); end end def setup_gems $LOAD_PATH << 'META-INF/jruby.home/lib/ruby/site_ruby/1.8' ENV['GEM_PATH'] = @gem_path end def change_to_root_directory Dir.chdir(root_path) end def silence_warnings(&block) JRuby::Rack.silence_warnings(&block) end def self.instance @instance ||= self.new end def self.instance=(inst) @instance = inst end end class Errors EXCEPTION = org.jruby.rack.RackDispatcher::EXCEPTION def initialize(file_server) @file_server = file_server end def call(env) [code = response_code(env), *response_content(env, code)] end def response_code(env) exc = env[EXCEPTION] if exc env['rack.showstatus.detail'] = exc.getMessage if exc.getCause.kind_of?(Java::JavaLang::InterruptedException) 503 else 500 end else 500 end end def response_content(env, code) @responses ||= Hash.new do |h,k| env["PATH_INFO"] = "/#{code}.html" response = @file_server.call(env) body = response[2] unless Array === body newbody = "" body.each do |chunk| newbody << chunk end response[2] = [newbody] end h[k] = response end response = @responses[code] if response[0] != 404 env["rack.showstatus.detail"] = nil response[1..2] else [{}, []] end end end class ErrorsApp def self.new ::Rack::Builder.new { use ::Rack::ShowStatus run Errors.new(::Rack::File.new(ServletHelper.instance.public_root)) }.to_app end end end endPK:{8˟ojruby/rack/boot/merb.rb#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'jruby/rack/merb' module JRuby::Rack silence_warnings do const_set('Bootstrap', MerbServletHelper) end end PK:{8/Sjruby/rack/boot/rack.rb#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ module JRuby::Rack Bootstrap = ServletHelper unless defined?(Bootstrap) endPK:{8pjruby/rack/boot/rails.rb#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'rack/adapter/rails' module JRuby::Rack silence_warnings do const_set('Bootstrap', RailsServletHelper) end end PK:{8 rack/adapter/PK:{8 rack/auth/PK:{8p^rack/builder.rbmodule Rack # Rack::Builder implements a small DSL to iteratively construct Rack # applications. # # Example: # # app = Rack::Builder.new { # use Rack::CommonLogger # use Rack::ShowExceptions # map "/lobster" do # use Rack::Lint # run Rack::Lobster.new # end # } # # +use+ adds a middleware to the stack, +run+ dispatches to an application. # You can use +map+ to construct a Rack::URLMap in a convenient way. class Builder def initialize(&block) @ins = [] instance_eval(&block) end def use(middleware, *args, &block) @ins << if block_given? lambda { |app| middleware.new(app, *args, &block) } else lambda { |app| middleware.new(app, *args) } end end def run(app) @ins << app #lambda { |nothing| app } end def map(path, &block) if @ins.last.kind_of? Hash @ins.last[path] = Rack::Builder.new(&block).to_app else @ins << {} map(path, &block) end end def to_app @ins[-1] = Rack::URLMap.new(@ins.last) if Hash === @ins.last inner_app = @ins.last @ins[0...-1].reverse.inject(inner_app) { |a, e| e.call(a) } end def call(env) to_app.call(env) end end end PK:{8;Ak8kfrack/cascade.rbfmodule Rack # Rack::Cascade tries an request on several apps, and returns the # first response that is not 404 (or in a list of configurable # status codes). class Cascade attr_reader :apps def initialize(apps, catch=404) @apps = apps @catch = [*catch] end def call(env) status = headers = body = nil raise ArgumentError, "empty cascade" if @apps.empty? @apps.each { |app| begin status, headers, body = app.call(env) break unless @catch.include?(status.to_i) end } [status, headers, body] end end end PK:{8;ķrack/commonlogger.rb]module Rack # Rack::CommonLogger forwards every request to an +app+ given, and # logs a line in the Apache common log format to the +logger+, or # rack.errors by default. class CommonLogger def initialize(app, logger=nil) @app = app @logger = logger end def call(env) dup._call(env) end def _call(env) @env = env @logger ||= self @time = Time.now @status, @header, @body = @app.call(env) [@status, @header, self] end # By default, log to rack.errors. def <<(str) @env["rack.errors"].write(str) @env["rack.errors"].flush end def each length = 0 @body.each { |part| length += part.size yield part } @now = Time.now # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common # lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 - # %{%s - %s [%s] "%s %s%s %s" %d %s\n} % @logger << %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n} % [@env["REMOTE_ADDR"] || "-", @env["REMOTE_USER"] || "-", @now.strftime("%d/%b/%Y %H:%M:%S"), @env["REQUEST_METHOD"], @env["PATH_INFO"], @env["QUERY_STRING"].empty? ? "" : "?"+@env["QUERY_STRING"], @env["HTTP_VERSION"], @status.to_s[0..3], (length.zero? ? "-" : length.to_s), @now - @time ] end end end PK:{8GO rack/file.rb Dmodule Rack # Rack::File serves files below the +root+ given, according to the # path info of the Rack request. # # Handlers can detect if bodies are a Rack::File, and use mechanisms # like sendfile on the +path+. class File attr_accessor :root attr_accessor :path def initialize(root) @root = root end def call(env) dup._call(env) end F = ::File def _call(env) if env["PATH_INFO"].include? ".." return [403, {"Content-Type" => "text/plain"}, ["Forbidden\n"]] end @path = F.join(@root, Utils.unescape(env["PATH_INFO"])) ext = F.extname(@path)[1..-1] if F.file?(@path) && F.readable?(@path) [200, { "Last-Modified" => F.mtime(@path).rfc822, "Content-Type" => MIME_TYPES[ext] || "text/plain", "Content-Length" => F.size(@path).to_s }, self] else return [404, {"Content-Type" => "text/plain"}, ["File not found: #{env["PATH_INFO"]}\n"]] end end def each F.open(@path, "rb") { |file| while part = file.read(8192) yield part end } end # :stopdoc: # From WEBrick. MIME_TYPES = { "ai" => "application/postscript", "asc" => "text/plain", "avi" => "video/x-msvideo", "bin" => "application/octet-stream", "bmp" => "image/bmp", "class" => "application/octet-stream", "cer" => "application/pkix-cert", "crl" => "application/pkix-crl", "crt" => "application/x-x509-ca-cert", #"crl" => "application/x-pkcs7-crl", "css" => "text/css", "dms" => "application/octet-stream", "doc" => "application/msword", "dvi" => "application/x-dvi", "eps" => "application/postscript", "etx" => "text/x-setext", "exe" => "application/octet-stream", "gif" => "image/gif", "htm" => "text/html", "html" => "text/html", "jpe" => "image/jpeg", "jpeg" => "image/jpeg", "jpg" => "image/jpeg", "js" => "text/javascript", "lha" => "application/octet-stream", "lzh" => "application/octet-stream", "mov" => "video/quicktime", "mpe" => "video/mpeg", "mpeg" => "video/mpeg", "mpg" => "video/mpeg", "pbm" => "image/x-portable-bitmap", "pdf" => "application/pdf", "pgm" => "image/x-portable-graymap", "png" => "image/png", "pnm" => "image/x-portable-anymap", "ppm" => "image/x-portable-pixmap", "ppt" => "application/vnd.ms-powerpoint", "ps" => "application/postscript", "qt" => "video/quicktime", "ras" => "image/x-cmu-raster", "rb" => "text/plain", "rd" => "text/plain", "rtf" => "application/rtf", "sgm" => "text/sgml", "sgml" => "text/sgml", "tif" => "image/tiff", "tiff" => "image/tiff", "txt" => "text/plain", "xbm" => "image/x-xbitmap", "xls" => "application/vnd.ms-excel", "xml" => "text/xml", "xpm" => "image/x-xpixmap", "xwd" => "image/x-xwindowdump", "zip" => "application/zip", } # :startdoc: end end PK:{8 rack/handler/PK:{8X:S: rack/lint.rbS:module Rack # Rack::Lint validates your application and the requests and # responses according to the Rack spec. class Lint def initialize(app) @app = app end # :stopdoc: class LintError < RuntimeError; end module Assertion def assert(message, &block) unless block.call raise LintError, message end end end include Assertion ## This specification aims to formalize the Rack protocol. You ## can (and should) use Rack::Lint to enforce it. ## ## When you develop middleware, be sure to add a Lint before and ## after to catch all mistakes. ## = Rack applications ## A Rack application is an Ruby object (not a class) that ## responds to +call+. def call(env=nil) ## It takes exactly one argument, the *environment* assert("No env given") { env } check_env env env['rack.input'] = InputWrapper.new(env['rack.input']) env['rack.errors'] = ErrorWrapper.new(env['rack.errors']) ## and returns an Array of exactly three values: status, headers, @body = @app.call(env) ## The *status*, check_status status ## the *headers*, check_headers headers ## and the *body*. check_content_type status, headers [status, headers, self] end ## == The Environment def check_env(env) ## The environment must be an true instance of Hash (no ## subclassing allowed) that includes CGI-like headers. ## The application is free to modify the environment. assert("env #{env.inspect} is not a Hash, but #{env.class}") { env.instance_of? Hash } ## ## The environment is required to include these variables ## (adopted from PEP333), except when they'd be empty, but see ## below. ## REQUEST_METHOD:: The HTTP request method, such as ## "GET" or "POST". This cannot ever ## be an empty string, and so is ## always required. ## SCRIPT_NAME:: The initial portion of the request ## URL's "path" that corresponds to the ## application object, so that the ## application knows its virtual ## "location". This may be an empty ## string, if the application corresponds ## to the "root" of the server. ## PATH_INFO:: The remainder of the request URL's ## "path", designating the virtual ## "location" of the request's target ## within the application. This may be an ## empty string, if the request URL targets ## the application root and does not have a ## trailing slash. ## QUERY_STRING:: The portion of the request URL that ## follows the ?, if any. May be ## empty, but is always required! ## SERVER_NAME, SERVER_PORT:: When combined with SCRIPT_NAME and PATH_INFO, these variables can be used to complete the URL. Note, however, that HTTP_HOST, if present, should be used in preference to SERVER_NAME for reconstructing the request URL. SERVER_NAME and SERVER_PORT can never be empty strings, and so are always required. ## HTTP_ Variables:: Variables corresponding to the ## client-supplied HTTP request ## headers (i.e., variables whose ## names begin with HTTP_). The ## presence or absence of these ## variables should correspond with ## the presence or absence of the ## appropriate HTTP header in the ## request. ## In addition to this, the Rack environment must include these ## Rack-specific variables: ## rack.version:: The Array [0,1], representing this version of Rack. ## rack.url_scheme:: +http+ or +https+, depending on the request URL. ## rack.input:: See below, the input stream. ## rack.errors:: See below, the error stream. ## rack.multithread:: true if the application object may be simultaneously invoked by another thread in the same process, false otherwise. ## rack.multiprocess:: true if an equivalent application object may be simultaneously invoked by another process, false otherwise. ## rack.run_once:: true if the server expects (but does not guarantee!) that the application will only be invoked this one time during the life of its containing process. Normally, this will only be true for a server based on CGI (or something similar). ## The server or the application can store their own data in the ## environment, too. The keys must contain at least one dot, ## and should be prefixed uniquely. The prefix rack. ## is reserved for use with the Rack core distribution and must ## not be used otherwise. ## %w[REQUEST_METHOD SERVER_NAME SERVER_PORT QUERY_STRING rack.version rack.input rack.errors rack.multithread rack.multiprocess rack.run_once].each { |header| assert("env missing required key #{header}") { env.include? header } } ## The environment must not contain the keys ## HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH ## (use the versions without HTTP_). %w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header| assert("env contains #{header}, must use #{header[5,-1]}") { not env.include? header } } ## The CGI keys (named without a period) must have String values. env.each { |key, value| next if key.include? "." # Skip extensions assert("env variable #{key} has non-string value #{value.inspect}") { value.instance_of? String } } ## ## There are the following restrictions: ## * rack.version must be an array of Integers. assert("rack.version must be an Array, was #{env["rack.version"].class}") { env["rack.version"].instance_of? Array } ## * rack.url_scheme must either be +http+ or +https+. assert("rack.url_scheme unknown: #{env["rack.url_scheme"].inspect}") { %w[http https].include? env["rack.url_scheme"] } ## * There must be a valid input stream in rack.input. check_input env["rack.input"] ## * There must be a valid error stream in rack.errors. check_error env["rack.errors"] ## * The REQUEST_METHOD must be one of +GET+, +POST+, +PUT+, ## +DELETE+, +HEAD+, +OPTIONS+, +TRACE+. assert("REQUEST_METHOD unknown: #{env["REQUEST_METHOD"]}") { %w[GET POST PUT DELETE HEAD OPTIONS TRACE].include?(env["REQUEST_METHOD"]) } ## * The SCRIPT_NAME, if non-empty, must start with / assert("SCRIPT_NAME must start with /") { !env.include?("SCRIPT_NAME") || env["SCRIPT_NAME"] == "" || env["SCRIPT_NAME"] =~ /\A\// } ## * The PATH_INFO, if non-empty, must start with / assert("PATH_INFO must start with /") { !env.include?("PATH_INFO") || env["PATH_INFO"] == "" || env["PATH_INFO"] =~ /\A\// } ## * The CONTENT_LENGTH, if given, must consist of digits only. assert("Invalid CONTENT_LENGTH: #{env["CONTENT_LENGTH"]}") { !env.include?("CONTENT_LENGTH") || env["CONTENT_LENGTH"] =~ /\A\d+\z/ } ## * One of SCRIPT_NAME or PATH_INFO must be ## set. PATH_INFO should be / if ## SCRIPT_NAME is empty. assert("One of SCRIPT_NAME or PATH_INFO must be set (make PATH_INFO '/' if SCRIPT_NAME is empty)") { env["SCRIPT_NAME"] || env["PATH_INFO"] } ## SCRIPT_NAME never should be /, but instead be empty. assert("SCRIPT_NAME cannot be '/', make it '' and PATH_INFO '/'") { env["SCRIPT_NAME"] != "/" } end ## === The Input Stream def check_input(input) ## The input stream must respond to +gets+, +each+ and +read+. [:gets, :each, :read].each { |method| assert("rack.input #{input} does not respond to ##{method}") { input.respond_to? method } } end class InputWrapper include Assertion def initialize(input) @input = input end ## * +gets+ must be called without arguments and return a string, ## or +nil+ on EOF. def gets(*args) assert("rack.input#gets called with arguments") { args.size == 0 } v = @input.gets assert("rack.input#gets didn't return a String") { v.nil? or v.instance_of? String } v end ## * +read+ must be called without or with one integer argument ## and return a string, or +nil+ on EOF. def read(*args) assert("rack.input#read called with too many arguments") { args.size <= 1 } if args.size == 1 assert("rack.input#read called with non-integer argument") { args.first.kind_of? Integer } end v = @input.read(*args) assert("rack.input#read didn't return a String") { v.nil? or v.instance_of? String } v end ## * +each+ must be called without arguments and only yield Strings. def each(*args) assert("rack.input#each called with arguments") { args.size == 0 } @input.each { |line| assert("rack.input#each didn't yield a String") { line.instance_of? String } yield line } end ## * +close+ must never be called on the input stream. def close(*args) assert("rack.input#close must not be called") { false } end end ## === The Error Stream def check_error(error) ## The error stream must respond to +puts+, +write+ and +flush+. [:puts, :write, :flush].each { |method| assert("rack.error #{error} does not respond to ##{method}") { error.respond_to? method } } end class ErrorWrapper include Assertion def initialize(error) @error = error end ## * +puts+ must be called with a single argument that responds to +to_s+. def puts(str) @error.puts str end ## * +write+ must be called with a single argument that is a String. def write(str) assert("rack.errors#write not called with a String") { str.instance_of? String } @error.write str end ## * +flush+ must be called without arguments and must be called ## in order to make the error appear for sure. def flush @error.flush end ## * +close+ must never be called on the error stream. def close(*args) assert("rack.errors#close must not be called") { false } end end ## == The Response ## === The Status def check_status(status) ## The status, if parsed as integer (+to_i+), must be bigger than 100. assert("Status must be >100 seen as integer") { status.to_i > 100 } end ## === The Headers def check_headers(header) ## The header must respond to each, and yield values of key and value. assert("header should respond to #each") { header.respond_to? :each } header.each { |key, value| ## The header keys must be Strings. assert("header key must be a string, was #{key.class}") { key.instance_of? String } ## The header must not contain a +Status+ key, assert("header must not contain Status") { key.downcase != "status" } ## contain keys with : or newlines in their name, assert("header names must not contain : or \\n") { key !~ /[:\n]/ } ## contain keys names that end in - or _, assert("header names must not end in - or _") { key !~ /[-_]\z/ } ## but only contain keys that consist of ## letters, digits, _ or - and start with a letter. assert("invalid header name: #{key}") { key =~ /\A[a-zA-Z][a-zA-Z0-9_-]*\z/ } ## ## The values of the header must respond to #each. assert("header values must respond to #each") { value.respond_to? :each } value.each { |item| ## The values passed on #each must be Strings assert("header values must consist of Strings") { item.instance_of?(String) } ## and not contain characters below 037. assert("invalid header value #{key}: #{item.inspect}") { item !~ /[\000-\037]/ } } } end ## === The Content-Type def check_content_type(status, headers) headers.each { |key, value| ## There must be a Content-Type, except when the ## +Status+ is 204 or 304, in which case there must be none ## given. if key.downcase == "content-type" assert("Content-Type header found in #{status} response, not allowed"){ not [204, 304].include? status.to_i } return end } assert("No Content-Type header found") { [201, 204, 304].include? status.to_i } end ## === The Body def each @closed = false ## The Body must respond to #each @body.each { |part| ## and must only yield String values. assert("Body yielded non-string value #{part.inspect}") { part.instance_of? String } yield part } ## ## If the Body responds to #close, it will be called after iteration. # XXX howto: assert("Body has not been closed") { @closed } ## ## The Body commonly is an Array of Strings, the application ## instance itself, or a File-like object. end def close @closed = true @body.close if @body.respond_to?(:close) end # :startdoc: end end ## == Thanks ## Some parts of this specification are adopted from PEP333: Python ## Web Server Gateway Interface ## v1.0 (http://www.python.org/dev/peps/pep-0333/). I'd like to thank ## everyone involved in that effort. PK:{8brack/lobster.rbrequire 'zlib' require 'rack/request' require 'rack/response' module Rack # Paste has a Pony, Rack has a Lobster! class Lobster LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2 P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0 t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0]) LambdaLobster = lambda { |env| if env["QUERY_STRING"].include?("flip") lobster = LobsterString.split("\n"). map { |line| line.ljust(42).reverse }. join("\n") href = "?" else lobster = LobsterString href = "?flip" end [200, {"Content-Type" => "text/html"}, ["Lobstericious!", "
", lobster, "
", "flip!"] ] } def call(env) req = Request.new(env) if req.GET["flip"] == "left" lobster = LobsterString.split("\n"). map { |line| line.ljust(42).reverse }. join("\n") href = "?flip=right" elsif req.GET["flip"] == "crash" raise "Lobster crashed" else lobster = LobsterString href = "?flip=left" end Response.new.finish do |res| res.write "Lobstericious!" res.write "
"
        res.write lobster
        res.write "
" res.write "

flip!

" res.write "

crash!

" end end end end if $0 == __FILE__ require 'rack' require 'rack/showexceptions' Rack::Handler::WEBrick.run \ Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), :Port => 9292 end PK:{83Ixs rack/mock.rbsrequire 'uri' require 'stringio' require 'rack/lint' require 'rack/utils' require 'rack/response' module Rack # Rack::MockRequest helps testing your Rack application without # actually using HTTP. # # After performing a request on a URL with get/post/put/delete, it # returns a MockResponse with useful helper methods for effective # testing. # # You can pass a hash with additional configuration to the # get/post/put/delete. # :input:: A String or IO-like to be used as rack.input. # :fatal:: Raise a FatalWarning if the app writes to rack.errors. # :lint:: If true, wrap the application in a Rack::Lint. class MockRequest class FatalWarning < RuntimeError end class FatalWarner def puts(warning) raise FatalWarning, warning end def write(warning) raise FatalWarning, warning end def flush end def string "" end end DEFAULT_ENV = { "rack.version" => [0,1], "rack.input" => StringIO.new, "rack.errors" => StringIO.new, "rack.multithread" => true, "rack.multiprocess" => true, "rack.run_once" => false, } def initialize(app) @app = app end def get(uri, opts={}) request("GET", uri, opts) end def post(uri, opts={}) request("POST", uri, opts) end def put(uri, opts={}) request("PUT", uri, opts) end def delete(uri, opts={}) request("DELETE", uri, opts) end def request(method="GET", uri="", opts={}) env = self.class.env_for(uri, opts.merge(:method => method)) if opts[:lint] app = Rack::Lint.new(@app) else app = @app end errors = env["rack.errors"] MockResponse.new(*(app.call(env) + [errors])) end # Return the Rack environment used for a request to +uri+. def self.env_for(uri="", opts={}) uri = URI(uri) env = DEFAULT_ENV.dup env["REQUEST_METHOD"] = opts[:method] || "GET" env["SERVER_NAME"] = uri.host || "example.org" env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80" env["QUERY_STRING"] = uri.query.to_s env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path env["rack.url_scheme"] = uri.scheme || "http" env["SCRIPT_NAME"] = opts[:script_name] || "" if opts[:fatal] env["rack.errors"] = FatalWarner.new else env["rack.errors"] = StringIO.new end opts[:input] ||= "" if String === opts[:input] env["rack.input"] = StringIO.new(opts[:input]) else env["rack.input"] = opts[:input] end opts.each { |field, value| env[field] = value if String === field } env end end # Rack::MockResponse provides useful helpers for testing your apps. # Usually, you don't create the MockResponse on your own, but use # MockRequest. class MockResponse def initialize(status, headers, body, errors=StringIO.new("")) @status = status.to_i @original_headers = headers @headers = Rack::Utils::HeaderHash.new headers.each { |field, values| values.each { |value| @headers[field] = value } } @body = "" body.each { |part| @body << part } @errors = errors.string end # Status attr_reader :status # Headers attr_reader :headers, :original_headers def [](field) headers[field] end # Body attr_reader :body def =~(other) @body =~ other end def match(other) @body.match other end # Errors attr_accessor :errors include Response::Helpers end end PK:{8yN<rack/recursive.rbOrequire 'uri' module Rack # Rack::ForwardRequest gets caught by Rack::Recursive and redirects # the current request to the app at +url+. # # raise ForwardRequest.new("/not-found") # class ForwardRequest < Exception attr_reader :url, :env def initialize(url, env={}) @url = URI(url) @env = env @env["PATH_INFO"] = @url.path @env["QUERY_STRING"] = @url.query if @url.query @env["HTTP_HOST"] = @url.host if @url.host @env["HTTP_PORT"] = @url.port if @url.port @env["rack.url_scheme"] = @url.scheme if @url.scheme super "forwarding to #{url}" end end # Rack::Recursive allows applications called down the chain to # include data from other applications (by using # rack['rack.recursive.include'][...] or raise a # ForwardRequest to redirect internally. class Recursive def initialize(app) @app = app end def call(env) @script_name = env["SCRIPT_NAME"] @app.call(env.merge('rack.recursive.include' => method(:include))) rescue ForwardRequest => req call(env.merge(req.env)) end def include(env, path) unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ || path[@script_name.size].nil?) raise ArgumentError, "can only include below #{@script_name}, not #{path}" end env = env.merge("PATH_INFO" => path, "SCRIPT_NAME" => @script_name, "REQUEST_METHOD" => "GET", "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "", "rack.input" => StringIO.new("")) @app.call(env) end end end PK:{8.rack/reloader.rb require 'thread' module Rack # Rack::Reloader checks on every request, but at most every +secs+ # seconds, if a file loaded changed, and reloads it, logging to # rack.errors. # # It is recommended you use ShowExceptions to catch SyntaxErrors etc. class Reloader def initialize(app, secs=10) @app = app @secs = secs # reload every @secs seconds max @last = Time.now end def call(env) if Time.now > @last + @secs Thread.exclusive { reload!(env['rack.errors']) @last = Time.now } end @app.call(env) end def reload!(stderr=STDERR) need_reload = $LOADED_FEATURES.find_all { |loaded| begin if loaded =~ /\A[.\/]/ # absolute filename or 1.9 abs = loaded else abs = $LOAD_PATH.map { |path| ::File.join(path, loaded) }. find { |file| ::File.exist? file } end if abs ::File.mtime(abs) > @last - @secs rescue false else false end end } need_reload.each { |l| $LOADED_FEATURES.delete l } need_reload.each { |to_load| begin if require to_load stderr.puts "#{self.class}: reloaded `#{to_load}'" end rescue LoadError, SyntaxError => e raise e # Possibly ShowExceptions end } stderr.flush need_reload end end end PK:{8Ewrack/request.rbFrequire 'rack/utils' module Rack # Rack::Request provides a convenient interface to a Rack # environment. It is stateless, the environment +env+ passed to the # constructor will be directly modified. # # req = Rack::Request.new(env) # req.post? # req.params["data"] class Request # The environment of the request. attr_reader :env def initialize(env) @env = env end def body; @env["rack.input"] end def scheme; @env["rack.url_scheme"] end def script_name; @env["SCRIPT_NAME"].to_s end def path_info; @env["PATH_INFO"].to_s end def port; @env["SERVER_PORT"].to_i end def request_method; @env["REQUEST_METHOD"] end def query_string; @env["QUERY_STRING"].to_s end def host # Remove port number. (@env["HTTP_HOST"] || @env["SERVER_NAME"]).gsub(/:\d+\z/, '') end def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end def path_info=(s); @env["PATH_INFO"] = s.to_s end def get?; request_method == "GET" end def post?; request_method == "POST" end def put?; request_method == "PUT" end def delete?; request_method == "DELETE" end # Returns the data recieved in the query string. def GET if @env["rack.request.query_string"] == query_string @env["rack.request.query_hash"] else @env["rack.request.query_string"] = query_string @env["rack.request.query_hash"] = Utils.parse_query(query_string) end end # Returns the data recieved in the request body. # # This method support both application/x-www-form-urlencoded and # multipart/form-data. def POST if @env["rack.request.form_input"] == @env["rack.input"] @env["rack.request.form_hash"] else @env["rack.request.form_input"] = @env["rack.input"] unless @env["rack.request.form_hash"] = Utils::Multipart.parse_multipart(env) @env["rack.request.form_vars"] = @env["rack.input"].read @env["rack.request.form_hash"] = Utils.parse_query(@env["rack.request.form_vars"]) end @env["rack.request.form_hash"] end end # The union of GET and POST data. def params self.GET.update(self.POST) end # shortcut for request.params[key] def [](key) params[key.to_s] end # shortcut for request.params[key] = value def []=(key, value) params[key.to_s] = value end # like Hash#values_at def values_at(*keys) keys.map{|key| params[key] } end # the referer of the client or '/' def referer @env['HTTP_REFERER'] || '/' end alias referrer referer def cookies return {} unless @env["HTTP_COOKIE"] if @env["rack.request.cookie_string"] == @env["HTTP_COOKIE"] @env["rack.request.cookie_hash"] else @env["rack.request.cookie_string"] = @env["HTTP_COOKIE"] # According to RFC 2109: # If multiple cookies satisfy the criteria above, they are ordered in # the Cookie header such that those with more specific Path attributes # precede those with less specific. Ordering with respect to other # attributes (e.g., Domain) is unspecified. @env["rack.request.cookie_hash"] = Utils.parse_query(@env["rack.request.cookie_string"], ';,').inject({}) {|h,(k,v)| h[k] = Array === v ? v.first : v h } end end def xhr? @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" end # Tries to return a remake of the original request URL as a string. def url url = scheme + "://" url << host if scheme == "https" && port != 443 || scheme == "http" && port != 80 url << ":#{port}" end url << fullpath url end def fullpath path = script_name + path_info path << "?" << query_string unless query_string.empty? path end end end PK:{8@h?:rack/response.rb:require 'rack/request' require 'rack/utils' module Rack # Rack::Response provides a convenient interface to create a Rack # response. # # It allows setting of headers and cookies, and provides useful # defaults (a OK response containing HTML). # # You can use Response#write to iteratively generate your response, # but note that this is buffered by Rack::Response until you call # +finish+. +finish+ however can take a block inside which calls to # +write+ are syncronous with the Rack response. # # Your application's +call+ should end returning Response#finish. class Response def initialize(body=[], status=200, header={}, &block) @status = status @header = Utils::HeaderHash.new({"Content-Type" => "text/html"}. merge(header)) @writer = lambda { |x| @body << x } @block = nil @body = [] if body.respond_to? :to_str write body.to_str elsif body.respond_to?(:each) body.each { |part| write part.to_s } else raise TypeError, "stringable or iterable required" end yield self if block_given? end attr_reader :header attr_accessor :status, :body def [](key) header[key] end def []=(key, value) header[key] = value end def set_cookie(key, value) case value when Hash domain = "; domain=" + value[:domain] if value[:domain] path = "; path=" + value[:path] if value[:path] # According to RFC 2109, we need dashes here. # N.B.: cgi.rb uses spaces... expires = "; expires=" + value[:expires].clone.gmtime. strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires] value = value[:value] end value = [value] unless Array === value cookie = Utils.escape(key) + "=" + value.map { |v| Utils.escape v }.join("&") + "#{domain}#{path}#{expires}" case self["Set-Cookie"] when Array self["Set-Cookie"] << cookie when String self["Set-Cookie"] = [self["Set-Cookie"], cookie] when nil self["Set-Cookie"] = cookie end end def delete_cookie(key, value={}) unless Array === self["Set-Cookie"] self["Set-Cookie"] = [self["Set-Cookie"]].compact end self["Set-Cookie"].reject! { |cookie| cookie =~ /\A#{Utils.escape(key)}=/ } set_cookie(key, {:value => '', :path => nil, :domain => nil, :expires => Time.at(0) }.merge(value)) end def finish(&block) @block = block if [204, 304].include?(status.to_i) header.delete "Content-Type" [status.to_i, header.to_hash, []] else [status.to_i, header.to_hash, self] end end alias to_a finish # For *response def each(&callback) @body.each(&callback) @writer = callback @block.call(self) if @block end def write(str) @writer.call str.to_s str end def close body.close if body.respond_to?(:close) end def empty? @block == nil && @body.empty? end alias headers header module Helpers def invalid?; @status < 100 || @status >= 600; end def informational?; @status >= 100 && @status < 200; end def successful?; @status >= 200 && @status < 300; end def redirection?; @status >= 300 && @status < 400; end def client_error?; @status >= 400 && @status < 500; end def server_error?; @status >= 500 && @status < 600; end def ok?; @status == 200; end def forbidden?; @status == 403; end def not_found?; @status == 404; end def redirect?; [301, 302, 303, 307].include? @status; end def empty?; [201, 204, 304].include? @status; end # Headers attr_reader :headers, :original_headers def include?(header) !!headers[header] end def content_type headers["Content-Type"] end def content_length cl = headers["Content-Length"] cl ? cl.to_i : cl end def location headers["Location"] end end include Helpers end end PK:{8 rack/session/PK:{8+**rack/showexceptions.rb*Qrequire 'ostruct' require 'erb' require 'rack/request' module Rack # Rack::ShowExceptions catches all exceptions raised from the app it # wraps. It shows a useful backtrace with the sourcefile and # clickable context, the whole Rack environment and the request # data. # # Be careful when you use this on public-facing sites as it could # reveal information helpful to attackers. class ShowExceptions CONTEXT = 7 def initialize(app) @app = app @template = ERB.new(TEMPLATE) end def call(env) @app.call(env) rescue StandardError, LoadError, SyntaxError => e [500, {"Content-Type" => "text/html"}, pretty(env, e)] end def pretty(env, exception) req = Rack::Request.new(env) path = (req.script_name + req.path_info).squeeze("/") frames = exception.backtrace.map { |line| frame = OpenStruct.new if line =~ /(.*?):(\d+)(:in `(.*)')?/ frame.filename = $1 frame.lineno = $2.to_i frame.function = $4 begin lineno = frame.lineno-1 lines = ::File.readlines(frame.filename) frame.pre_context_lineno = [lineno-CONTEXT, 0].max frame.pre_context = lines[frame.pre_context_lineno...lineno] frame.context_line = lines[lineno].chomp frame.post_context_lineno = [lineno+CONTEXT, lines.size].min frame.post_context = lines[lineno+1..frame.post_context_lineno] rescue end frame else nil end }.compact env["rack.errors"].puts "#{exception.class}: #{exception.message}" env["rack.errors"].puts exception.backtrace.map { |l| "\t" + l } env["rack.errors"].flush [@template.result(binding)] end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end # :stopdoc: # adapted from Django # Copyright (c) 2005, the Lawrence Journal-World # Used under the modified BSD license: # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 TEMPLATE = <<'HTML' <%=h exception.class %> at <%=h path %>

<%=h exception.class %> at <%=h path %>

<%=h exception.message %>

Ruby <%=h frames.first.filename %>: in <%=h frames.first.function %>, line <%=h frames.first.lineno %>
Web <%=h req.request_method %> <%=h(req.host + path)%>

Jump to:

Traceback (innermost first)

    <% frames.each { |frame| %>
  • <%=h frame.filename %>: in <%=h frame.function %> <% if frame.context_line %>
    <% if frame.pre_context %>
      <% frame.pre_context.each { |line| %>
    1. <%=h line %>
    2. <% } %>
    <% end %>
    1. <%=h frame.context_line %>...
    <% if frame.post_context %>
      <% frame.post_context.each { |line| %>
    1. <%=h line %>
    2. <% } %>
    <% end %>
    <% end %>
  • <% } %>

Request information

GET

<% unless req.GET.empty? %> <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

No GET data.

<% end %>

POST

<% unless req.POST.empty? %> <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

No POST data.

<% end %> <% unless req.cookies.empty? %> <% req.cookies.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

No cookie data.

<% end %>

Rack ENV

<% env.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val %>

You're seeing this error because you use Rack::ShowException.

HTML # :startdoc: end end PK:{8( rack/showstatus.rb require 'erb' require 'rack/request' require 'rack/utils' module Rack # Rack::ShowStatus catches all empty responses the app it wraps and # replaces them with a site explaining the error. # # Additional details can be put into rack.showstatus.detail # and will be shown as HTML. If such details exist, the error page # is always rendered, even if the reply was not empty. class ShowStatus def initialize(app) @app = app @template = ERB.new(TEMPLATE) end def call(env) status, headers, body = @app.call(env) # client or server error, or explicit message if status.to_i >= 400 && (body.empty? rescue false) || env["rack.showstatus.detail"] req = Rack::Request.new(env) message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s detail = env["rack.showstatus.detail"] || message [status, headers.merge("Content-Type" => "text/html"), [@template.result(binding)]] else [status, headers, body] end end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end # :stopdoc: # adapted from Django # Copyright (c) 2005, the Lawrence Journal-World # Used under the modified BSD license: # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 TEMPLATE = <<'HTML' <%=h message %> at <%=h req.script_name + req.path_info %>

<%=h message %> (<%= status.to_i %>)

Request Method: <%=h req.request_method %>
Request URL: <%=h req.url %>

<%= detail %>

You're seeing this error because you use Rack::ShowStatus.

HTML # :startdoc: end end PK:{8cbrack/static.rbtmodule Rack # The Rack::Static middleware intercepts requests for static files # (javascript files, images, stylesheets, etc) based on the url prefixes # passed in the options, and serves them using a Rack::File object. This # allows a Rack stack to serve both static and dynamic content. # # Examples: # use Rack::Static, :urls => ["/media"] # will serve all requests beginning with /media from the "media" folder # located in the current directory (ie media/*). # # use Rack::Static, :urls => ["/css", "/images"], :root => "public" # will serve all requests beginning with /css or /images from the folder # "public" in the current directory (ie public/css/* and public/images/*) class Static def initialize(app, options={}) @app = app @urls = options[:urls] || ["/favicon.ico"] root = options[:root] || Dir.pwd @file_server = Rack::File.new(root) end def call(env) path = env["PATH_INFO"] can_serve = @urls.any? { |url| path.index(url) == 0 } if can_serve @file_server.call(env) else @app.call(env) end end end end PK:{8Ve prack/urlmap.rbKmodule Rack # Rack::URLMap takes a hash mapping urls or paths to apps, and # dispatches accordingly. Support for HTTP/1.1 host names exists if # the URLs start with http:// or https://. # # URLMap modifies the SCRIPT_NAME and PATH_INFO such that the part # relevant for dispatch is in the SCRIPT_NAME, and the rest in the # PATH_INFO. This should be taken care of when you need to # reconstruct the URL in order to create links. # # URLMap dispatches in such a way that the longest paths are tried # first, since they are most specific. class URLMap def initialize(map) @mapping = map.map { |location, app| if location =~ %r{\Ahttps?://(.*?)(/.*)} host, location = $1, $2 else host = nil end location = "" if location == "/" [host, location, app] }.sort_by { |(h, l, a)| -l.size } # Longest path first end def call(env) path = env["PATH_INFO"].to_s.squeeze("/") hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT') @mapping.each { |host, location, app| if (hHost == host || sName == host \ || (host.nil? && (hHost == sName || hHost == sName+':'+sPort))) \ and location == path[0, location.size] \ and (path[location.size] == nil || path[location.size] == ?/) env["SCRIPT_NAME"] += location.dup env["PATH_INFO"] = path[location.size..-1] env["PATH_INFO"].gsub!(/\/\z/, '') env["PATH_INFO"] = "/" if env["PATH_INFO"].empty? return app.call(env) end } [404, {"Content-Type" => "text/plain"}, ["Not Found: #{path}"]] end end end PK:{8< rack/utils.rbrequire 'tempfile' module Rack # Rack::Utils contains a grab-bag of useful methods for writing web # applications adopted from all kinds of Ruby libraries. module Utils # Performs URI escaping so that you can construct proper # query strings faster. Use this rather than the cgi.rb # version since it's faster. (Stolen from Camping). def escape(s) s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) { '%'+$1.unpack('H2'*$1.size).join('%').upcase }.tr(' ', '+') end module_function :escape # Unescapes a URI escaped string. (Stolen from Camping). def unescape(s) s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){ [$1.delete('%')].pack('H*') } end module_function :unescape # Stolen from Mongrel: # Parses a query string by breaking it up at the '&' # and ';' characters. You can also use this to parse # cookies by changing the characters used in the second # parameter (which defaults to '&;'). def parse_query(qs, d = '&;') params = {} (qs||'').split(/[#{d}] */n).inject(params) { |h,p| k, v=unescape(p).split('=',2) if cur = params[k] if cur.class == Array params[k] << v else params[k] = [cur, v] end else params[k] = v end } return params end module_function :parse_query # Escape ampersands, brackets and quotes to their HTML/XML entities. def escape_html(string) string.to_s.gsub("&", "&"). gsub("<", "<"). gsub(">", ">"). gsub("'", "'"). gsub('"', """) end module_function :escape_html class Context < Proc def initialize app_f=nil, app_r=nil @for, @app = app_f, app_r end alias_method :old_inspect, :inspect def inspect "#{old_inspect} ==> #{@for.inspect} ==> #{@app.inspect}" end def pretty_print pp pp.text old_inspect pp.nest 1 do pp.breakable pp.text '=for> ' pp.pp @for pp.breakable pp.text '=app> ' pp.pp @app end end end # A case-normalizing Hash, adjusting on [] and []=. class HeaderHash < Hash def initialize(hash={}) hash.each { |k, v| self[k] = v } end def to_hash {}.replace(self) end def [](k) super capitalize(k) end def []=(k, v) super capitalize(k), v end def capitalize(k) k.to_s.downcase.gsub(/^.|[-_\s]./) { |x| x.upcase } end end # Every standard HTTP code mapped to the appropriate message. # Stolen from Mongrel. HTTP_STATUS_CODES = { 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Moved Temporarily', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported' } # A multipart form data parser, adapted from IOWA. # # Usually, Rack::Request#POST takes care of calling this. module Multipart EOL = "\r\n" def self.parse_multipart(env) unless env['CONTENT_TYPE'] =~ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n nil else boundary = "--#{$1}" params = {} buf = "" content_length = env['CONTENT_LENGTH'].to_i input = env['rack.input'] boundary_size = boundary.size + EOL.size bufsize = 16384 content_length -= boundary_size status = input.read(boundary_size) raise EOFError, "bad content body" unless status == boundary + EOL rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/ loop { head = nil body = '' filename = content_type = name = nil until head && buf =~ rx if !head && i = buf.index("\r\n\r\n") head = buf.slice!(0, i+2) # First \r\n buf.slice!(0, 2) # Second \r\n filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1] content_type = head[/Content-Type: (.*)\r\n/ni, 1] name = head[/Content-Disposition:.* name="?([^\";]*)"?/ni, 1] body = Tempfile.new("RackMultipart") if filename next end # Save the read body part. if head && (boundary_size+4 < buf.size) body << buf.slice!(0, buf.size - (boundary_size+4)) end c = input.read(bufsize < content_length ? bufsize : content_length) raise EOFError, "bad content body" if c.nil? || c.empty? buf << c content_length -= c.size end # Save the rest. if i = buf.index(rx) body << buf.slice!(0, i) buf.slice!(0, boundary_size+2) content_length = -1 if $1 == "--" end if filename body.rewind data = {:filename => filename, :type => content_type, :name => name, :tempfile => body, :head => head} else data = body end if name if name =~ /\[\]\z/ params[name] ||= [] params[name] << data else params[name] = data end end break if buf.empty? || content_length == -1 } params end end end end end PK:{8{J6rack/adapter/camping.rb#module Rack module Adapter class Camping def initialize(app) @app = app end def call(env) env["PATH_INFO"] ||= "" env["SCRIPT_NAME"] ||= "" controller = @app.run(env['rack.input'], env) h = controller.headers h.each_pair do |k,v| if v.kind_of? URI h[k] = v.to_s end end [controller.status, controller.headers, controller.body] end end end end PK:{8'urack/adapter/rails.rbwrequire 'cgi' require 'jruby/rack/rails' # Based on http://github.com/macournoyer/thin/tree/master/lib/rack/adapter/rails.rb # Adapter to run a Rails app with any supported Rack handler. # By default it will try to load the Rails application in the # current directory in the development environment. # Options: # root: Root directory of the Rails app # env: Rails environment to run in (development, production or test) # Based on http://fuzed.rubyforge.org/ Rails adapter module Rack module Adapter class Rails def initialize(options={}) @root = options[:root] || Dir.pwd @env = options[:environment] || 'production' @public = options[:public] || ::File.join(@root, "public") @file_server = Rack::File.new(@public) end # TODO refactor this in File#can_serve?(path) ?? def file_exist?(path) full_path = ::File.join(@file_server.root, Utils.unescape(path)) ::File.file?(full_path) && ::File.readable?(full_path) end def serve_file(env) @file_server.call(env) end def serve_rails(env) request = Request.new(env) response = Response.new cgi = CGIWrapper.new(request, response) Dispatcher.dispatch(cgi, session_options(env), response) response.finish end def call(env) if env['rack.dynamic.requests.only'] serve_rails(env) else path = env['PATH_INFO'].chomp('/') cached_path = (path.empty? ? 'index' : path) + ActionController::Base.page_cache_extension if file_exist?(path) # Serve the file if it's there serve_file(env) elsif file_exist?(cached_path) # Serve the page cache if it's there env['PATH_INFO'] = cached_path serve_file(env) else # No static file, let Rails handle it serve_rails(env) end end end def session_options(env) env['rails.session_options'] || ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS end protected class CGIWrapper < ::CGI def initialize(request, response, *args) @request = request @response = response @args = *args @input = request.body super(*args) end def header(options = "text/html") if options.is_a?(String) @response['Content-Type'] = options unless @response['Content-Type'] else @response['Content-Length'] = options.delete('Content-Length').to_s if options['Content-Length'] @response['Content-Type'] = options.delete('type') || "text/html" @response['Content-Type'] += "; charset=" + options.delete('charset') if options['charset'] @response['Content-Language'] = options.delete('language') if options['language'] @response['Expires'] = options.delete('expires') if options['expires'] @response.status = options.delete('Status') if options['Status'] # Convert 'cookie' header to 'Set-Cookie' headers. # Because Set-Cookie header can appear more the once in the response body, # we store it in a line break seperated string that will be translated to # multiple Set-Cookie header by the handler. if cookie = options.delete('cookie') cookies = [] case cookie when Array then cookie.each { |c| cookies << c.to_s } when Hash then cookie.each { |_, c| cookies << c.to_s } else cookies << cookie.to_s end @output_cookies.each { |c| cookies << c.to_s } if @output_cookies @response['Set-Cookie'] = cookies unless cookies.empty? end options.each { |k,v| @response[k] = v } end "" end def params @params ||= @request.params end def cookies @request.cookies end def query_string @request.query_string end # Used to wrap the normal args variable used inside CGI. def args @args end # Used to wrap the normal env_table variable used inside CGI. def env_table @request.env end # Used to wrap the normal stdinput variable used inside CGI. def stdinput @input end def stdoutput STDERR.puts "stdoutput should not be used." @response.body end end end end end PK:{8rack/auth/abstract/PK:{8Wrack/auth/basic.rb[require 'rack/auth/abstract/handler' require 'rack/auth/abstract/request' module Rack module Auth # Rack::Auth::Basic implements HTTP Basic Authentication, as per RFC 2617. # # Initialize with the Rack application that you want protecting, # and a block that checks if a username and password pair are valid. # # See also: example/protectedlobster.rb class Basic < AbstractHandler def call(env) auth = Basic::Request.new(env) return unauthorized unless auth.provided? return bad_request unless auth.basic? if valid?(auth) env['REMOTE_USER'] = auth.username return @app.call(env) end unauthorized end private def challenge 'Basic realm="%s"' % realm end def valid?(auth) @authenticator.call(*auth.credentials) end class Request < Auth::AbstractRequest def basic? :basic == scheme end def credentials @credentials ||= params.unpack("m*").first.split(/:/, 2) end def username credentials.first end end end end end PK:{8rack/auth/digest/PK:{8Fd50rack/auth/openid.rb0# AUTHOR: blink ; blink#ruby-lang@irc.freenode.net require 'rack/auth/abstract/handler' require 'openid' module Rack module Auth # Rack::Auth::OpenID provides a simple method for permitting openid # based logins. It requires the ruby-openid lib from janrain to operate, # as well as some method of session management of a Hash type. # # After a transaction, the response status object is stored in the # environment at rack.auth.openid.status, which can be used in the # followup block or in a wrapping application to accomplish # additional data maniipulation. # # NOTE: Due to the amount of data that ruby-openid stores in the session, # Rack::Session::Cookie may fault. # # A hash of data is stored in the session hash at the key of :openid. # The fully canonicalized identity url is stored within at 'identity'. # Extension data from 'openid.sreg.nickname' would be stored as # { 'nickname' => value }. # # NOTE: To my knowledge there is no collision at this point from storage # of this manner, if there is please let me know so I may adjust this app # to cope. class OpenID < AbstractHandler # Required for ruby-openid OIDStore = ::OpenID::MemoryStore.new # A Hash of options is taken as it's single initializing # argument. String keys are taken to be openid protocol # extension namespaces. # # For example: 'sreg' => { 'required' => # 'nickname' } # # Other keys are taken as options for Rack::Auth::OpenID, normally Symbols. # Only :return is required. :trust is highly recommended to be set. # # * :return defines the url to return to after the client authenticates # with the openid service provider. Should point to where this app is # mounted. (ex: 'http://mysite.com/openid') # * :trust defines the url identifying the site they are actually logging # into. (ex: 'http://mysite.com/') # * :session_key defines the key to the session hash in the env. # (by default it uses 'rack.session') def initialize(options={}) raise ArgumentError, 'No return url provided.' unless options[:return] warn 'No trust url provided.' unless options[:trust] options[:trust] ||= options[:return] @options = { :session_key => 'rack.session' }.merge(options) end def call(env) request = Rack::Request.new env return no_session unless session = request.env[@options[:session_key]] resp = if request.GET['openid.mode'] finish session, request.GET, env elsif request.GET['openid_url'] check session, request.GET['openid_url'], env else bad_request end end def check(session, oid_url, env) consumer = ::OpenID::Consumer.new session, OIDStore oid = consumer.begin oid_url return auth_fail unless oid.status == ::OpenID::SUCCESS @options.each do |ns,s| next unless ns.is_a? String s.each {|k,v| oid.add_extension_arg(ns, k, v) } end r_url = @options.fetch :return do |k| request.url end t_url = @options.fetch :trust env['rack.auth.openid.status'] = oid return 303, {'Location'=>oid.redirect_url( t_url, r_url )}, [] end def finish(session, params, env) consumer = ::OpenID::Consumer.new session, OIDStore oid = consumer.complete params return bad_login unless oid.status == ::OpenID::SUCCESS session[:openid] = {'identity' => oid.identity_url} @options.each do |ns,s| next unless ns.is_a? String oid.extension_response(ns).each{|k,v| session[k]=v } end env['rack.auth.openid.status'] = oid return 303, {'Location'=>@options[:trust]}, [] end def no_session @options. fetch :no_session, [500,{'Content-Type'=>'text/plain'},'No session available.'] end def auth_fail @options. fetch :auth_fail, [500, {'Content-Type'=>'text/plain'},'Foreign server failure.'] end def bad_login @options. fetch :bad_login, [401, {'Content-Type'=>'text/plain'},'Identification has failed.'] end end end end PK:{8+&rack/auth/abstract/handler.rb&module Rack module Auth # Rack::Auth::AbstractHandler implements common authentication functionality. # # +realm+ should be set for all handlers. class AbstractHandler attr_accessor :realm def initialize(app, &authenticator) @app, @authenticator = app, authenticator end private def unauthorized(www_authenticate = challenge) return [ 401, { 'WWW-Authenticate' => www_authenticate.to_s }, [] ] end def bad_request [ 400, {}, [] ] end end end end PK:{8brack/auth/abstract/request.rbumodule Rack module Auth class AbstractRequest def initialize(env) @env = env end def provided? !authorization_key.nil? end def parts @parts ||= @env[authorization_key].split(' ', 2) end def scheme @scheme ||= parts.first.downcase.to_sym end def params @params ||= parts.last end private AUTHORIZATION_KEYS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION'] def authorization_key @authorization_key ||= AUTHORIZATION_KEYS.detect { |key| @env.has_key?(key) } end end end end PK:{81r0 + rack/auth/digest/md5.rb+ require 'rack/auth/abstract/handler' require 'rack/auth/digest/request' require 'rack/auth/digest/params' require 'rack/auth/digest/nonce' require 'digest/md5' module Rack module Auth module Digest # Rack::Auth::Digest::MD5 implements the MD5 algorithm version of # HTTP Digest Authentication, as per RFC 2617. # # Initialize with the [Rack] application that you want protecting, # and a block that looks up a plaintext password for a given username. # # +opaque+ needs to be set to a constant base64/hexadecimal string. # class MD5 < AbstractHandler attr_accessor :opaque attr_writer :passwords_hashed def initialize(app) super @passwords_hashed = nil end def passwords_hashed? !!@passwords_hashed end def call(env) auth = Request.new(env) unless auth.provided? return unauthorized end if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth) return bad_request end if valid?(auth) if auth.nonce.stale? return unauthorized(challenge(:stale => true)) else env['REMOTE_USER'] = auth.username return @app.call(env) end end unauthorized end private QOP = 'auth'.freeze def params(hash = {}) Params.new do |params| params['realm'] = realm params['nonce'] = Nonce.new.to_s params['opaque'] = H(opaque) params['qop'] = QOP hash.each { |k, v| params[k] = v } end end def challenge(hash = {}) "Digest #{params(hash)}" end def valid?(auth) valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth) end def valid_qop?(auth) QOP == auth.qop end def valid_opaque?(auth) H(opaque) == auth.opaque end def valid_nonce?(auth) auth.nonce.valid? end def valid_digest?(auth) digest(auth, @authenticator.call(auth.username)) == auth.response end def md5(data) ::Digest::MD5.hexdigest(data) end alias :H :md5 def KD(secret, data) H([secret, data] * ':') end def A1(auth, password) [ auth.username, auth.realm, password ] * ':' end def A2(auth) [ auth.method, auth.uri ] * ':' end def digest(auth, password) password_hash = passwords_hashed? ? password : H(A1(auth, password)) KD(password_hash, [ auth.nonce, auth.nc, auth.cnonce, QOP, H(A2(auth)) ] * ':') end end end end end PK:{8rack/auth/digest/nonce.rb8require 'digest/md5' module Rack module Auth module Digest # Rack::Auth::Digest::Nonce is the default nonce generator for the # Rack::Auth::Digest::MD5 authentication handler. # # +private_key+ needs to set to a constant string. # # +time_limit+ can be optionally set to an integer (number of seconds), # to limit the validity of the generated nonces. class Nonce class << self attr_accessor :private_key, :time_limit end def self.parse(string) new(*string.unpack("m*").first.split(' ', 2)) end def initialize(timestamp = Time.now, given_digest = nil) @timestamp, @given_digest = timestamp.to_i, given_digest end def to_s [([ @timestamp, digest ] * ' ')].pack("m*").strip end def digest ::Digest::MD5.hexdigest([ @timestamp, self.class.private_key ] * ':') end def valid? digest == @given_digest end def stale? !self.class.time_limit.nil? && (@timestamp - Time.now.to_i) < self.class.time_limit end def fresh? !stale? end end end end end PK:{8hUrack/auth/digest/params.rbKmodule Rack module Auth module Digest class Params < Hash def self.parse(str) split_header_value(str).inject(new) do |header, param| k, v = param.split('=', 2) header[k] = dequote(v) header end end def self.dequote(str) # From WEBrick::HTTPUtils ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup ret.gsub!(/\\(.)/, "\\1") ret end def self.split_header_value(str) # From WEBrick::HTTPUtils str.scan(/((?:"(?:\\.|[^"])+?"|[^",]+)+)(?:,\s*|\Z)/n).collect{ |v| v[0] } end def initialize super yield self if block_given? end def [](k) super k.to_s end def []=(k, v) super k.to_s, v.to_s end UNQUOTED = ['qop', 'nc', 'stale'] def to_s inject([]) do |parts, (k, v)| parts << "#{k}=" + (UNQUOTED.include?(k) ? v.to_s : quote(v)) parts end.join(', ') end def quote(str) # From WEBrick::HTTPUtils '"' << str.gsub(/[\\\"]/o, "\\\1") << '"' end end end end end PK:{8 9rack/auth/digest/request.rb$require 'rack/auth/abstract/request' require 'rack/auth/digest/params' require 'rack/auth/digest/nonce' module Rack module Auth module Digest class Request < Auth::AbstractRequest def method @env['REQUEST_METHOD'] end def digest? :digest == scheme end def correct_uri? @env['PATH_INFO'] == uri end def nonce @nonce ||= Nonce.parse(params['nonce']) end def params @params ||= Params.parse(parts.last) end def method_missing(sym) if params.has_key? key = sym.to_s return params[key] end super end end end end end PK:{8nrack/handler/cgi.rbjmodule Rack module Handler class CGI def self.run(app, options=nil) serve app end def self.serve(app) env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], "rack.input" => STDIN, "rack.errors" => STDERR, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => true, "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" }) env["QUERY_STRING"] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" status, headers, body = app.call(env) begin send_headers status, headers send_body body ensure body.close if body.respond_to? :close end end def self.send_headers(status, headers) STDOUT.print "Status: #{status}\r\n" headers.each { |k, vs| vs.each { |v| STDOUT.print "#{k}: #{v}\r\n" } } STDOUT.print "\r\n" STDOUT.flush end def self.send_body(body) body.each { |part| STDOUT.print part STDOUT.flush } end end end end PK:{85ipkrack/handler/fastcgi.rbkrequire 'fcgi' module Rack module Handler class FastCGI def self.run(app, options={}) file = options[:File] and STDIN.reopen(UNIXServer.new(file)) port = options[:Port] and STDIN.reopen(TCPServer.new(port)) FCGI.each { |request| serve request, app } end module ProperStream # :nodoc: def each # This is missing by default. while line = gets yield line end end def read(*args) if args.empty? super || "" # Empty string on EOF. else super end end end def self.serve(request, app) env = request.env env.delete "HTTP_CONTENT_LENGTH" request.in.extend ProperStream env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], "rack.input" => request.in, "rack.errors" => request.err, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) env["QUERY_STRING"] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" env.delete "PATH_INFO" if env["PATH_INFO"] == "" status, headers, body = app.call(env) begin send_headers request.out, status, headers send_body request.out, body ensure body.close if body.respond_to? :close request.finish end end def self.send_headers(out, status, headers) out.print "Status: #{status}\r\n" headers.each { |k, vs| vs.each { |v| out.print "#{k}: #{v}\r\n" } } out.print "\r\n" out.flush end def self.send_body(out, body) body.each { |part| out.print part out.flush } end end end end PK:{8@rack/handler/lsws.rb@require 'lsapi' #require 'cgi' module Rack module Handler class LSWS def self.run(app, options=nil) while LSAPI.accept != nil serve app end end def self.serve(app) env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], "rack.input" => STDIN, "rack.errors" => STDERR, "rack.multithread" => false, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" }) env["QUERY_STRING"] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" status, headers, body = app.call(env) begin send_headers status, headers send_body body ensure body.close if body.respond_to? :close end end def self.send_headers(status, headers) print "Status: #{status}\r\n" headers.each { |k, vs| vs.each { |v| print "#{k}: #{v}\r\n" } } print "\r\n" STDOUT.flush end def self.send_body(body) body.each { |part| print part STDOUT.flush } end end end end PK:{8͝QLrack/handler/mongrel.rbLrequire 'mongrel' require 'stringio' module Rack module Handler class Mongrel < ::Mongrel::HttpHandler def self.run(app, options={}) server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0', options[:Port] || 8080) server.register('/', Rack::Handler::Mongrel.new(app)) yield server if block_given? server.run.join end def initialize(app) @app = app end def process(request, response) env = {}.replace(request.params) env.delete "HTTP_CONTENT_TYPE" env.delete "HTTP_CONTENT_LENGTH" env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" env.update({"rack.version" => [0,1], "rack.input" => request.body || StringIO.new(""), "rack.errors" => STDERR, "rack.multithread" => true, "rack.multiprocess" => false, # ??? "rack.run_once" => false, "rack.url_scheme" => "http", }) env["QUERY_STRING"] ||= "" env.delete "PATH_INFO" if env["PATH_INFO"] == "" status, headers, body = @app.call(env) begin response.status = status.to_i headers.each { |k, vs| vs.each { |v| response.header[k] = v } } body.each { |part| response.body << part } response.finished ensure body.close if body.respond_to? :close end end end end end PK:{8Q$rack/handler/scgi.rbrequire 'scgi' require 'stringio' module Rack module Handler class SCGI < ::SCGI::Processor attr_accessor :app def self.run(app, options=nil) new(options.merge(:app=>app, :host=>options[:Host], :port=>options[:Port], :socket=>options[:Socket])).listen end def initialize(settings = {}) @app = settings[:app] @log = Object.new def @log.info(*args); end def @log.error(*args); end super(settings) end def process_request(request, input_body, socket) env = {}.replace(request) env.delete "HTTP_CONTENT_TYPE" env.delete "HTTP_CONTENT_LENGTH" env["REQUEST_PATH"], env["QUERY_STRING"] = env["REQUEST_URI"].split('?', 2) env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["PATH_INFO"] = env["REQUEST_PATH"] env["QUERY_STRING"] ||= "" env["SCRIPT_NAME"] = "" env.update({"rack.version" => [0,1], "rack.input" => StringIO.new(input_body), "rack.errors" => STDERR, "rack.multithread" => true, "rack.multiprocess" => true, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) status, headers, body = app.call(env) begin socket.write("Status: #{status}\r\n") headers.each do |k, vs| vs.each {|v| socket.write("#{k}: #{v}\r\n")} end socket.write("\r\n") body.each {|s| socket.write(s)} ensure body.close if body.respond_to? :close end end end end end PK:{8G/*rack/handler/servlet.rb*#-- # Copyright 2007-2008 Sun Microsystems, Inc. # This source code is available under the MIT license. # See the file LICENSE.txt for details. #++ require 'jruby/rack' module Rack module Handler class Servlet def initialize(rack_app) @rack_app = rack_app end def call(servlet_env) JRuby::Rack::Response.new(@rack_app.call(create_env(servlet_env))) end def create_env(servlet_env) Env.new(servlet_env).to_hash end def create_lazy_env(servlet_env) LazyEnv.new(servlet_env).to_hash end end class Env BUILTINS = %w(rack.version rack.multithread rack.multiprocess rack.run_once rack.input rack.errors rack.url_scheme java.servlet_request java.servlet_context) REQUEST = %w(CONTENT_TYPE CONTENT_LENGTH REQUEST_METHOD SCRIPT_NAME REQUEST_URI PATH_INFO QUERY_STRING SERVER_NAME REMOTE_HOST REMOTE_ADDR REMOTE_USER SERVER_PORT) def initialize(servlet_env) @env = populate(LazyEnv.new(servlet_env).to_hash) end def populate(lazy_hash) hash = {} (BUILTINS + REQUEST).each {|k| lazy_hash[k]} # load builtins and request vars lazy_hash['HTTP_'] # load headers lazy_hash.keys.each {|k| hash[k] = lazy_hash[k]} hash end def to_hash @env end end class LazyEnv def initialize(servlet_env) @env = Hash.new {|h,k| load_env_key(h,k)} @servlet_env = servlet_env load_servlet_request_attributes end def to_hash @env end def load_env_key(env, key) if respond_to?("load__#{key}") send("load__#{key}", env) elsif key =~ /^(rack|java)/ load_builtin(env, key) elsif key =~ /^HTTP_/ load_headers(env, key) end end def load_servlet_request_attributes @servlet_env.getAttributeNames.each do |k| v = @servlet_env.getAttribute(k) case k when "SERVER_PORT", "CONTENT_LENGTH" @env[k] = v.to_s if v.to_i >= 0 when "CONTENT_TYPE" @env[k] = v if v else if v @env[k] = v else @env[k] = "" end end end end def load_headers(env, key) unless @headers_added @headers_added = true @servlet_env.getHeaderNames.each do |h| next if h =~ /^Content-(Type|Length)$/i k = "HTTP_#{h.upcase.gsub(/-/, '_')}" env[k] = @servlet_env.getHeader(h) unless env.has_key?(k) end end if env.has_key?(key) env[key] else nil end end def load_builtin(env, key) case key when 'rack.version' then env[key] = Rack::VERSION when 'rack.multithread' then env[key] = true when 'rack.multiprocess' then env[key] = false when 'rack.run_once' then env[key] = false when 'rack.input' then env[key] = @servlet_env.to_io when 'rack.errors' then env[key] = JRuby::Rack::ServletLog.new when 'rack.url_scheme' then env[key] = @servlet_env.getScheme when 'java.servlet_request' then env[key] = @servlet_env when 'java.servlet_context' then env[key] = $servlet_context else nil end end def load__CONTENT_TYPE(env) content_type = @servlet_env.getContentType env["CONTENT_TYPE"] = content_type if content_type end def load__CONTENT_LENGTH(env) content_length = @servlet_env.getContentLength env["CONTENT_LENGTH"] = content_length.to_s if content_length >= 0 end def load__REQUEST_METHOD(env) env["REQUEST_METHOD"] = @servlet_env.getMethod || "GET" end def load__SCRIPT_NAME(env) context_path = @servlet_env.getContextPath || "" env["SCRIPT_NAME"] = "#{context_path}#{@servlet_env.getServletPath}" end def load__REQUEST_URI(env) env["REQUEST_URI"] = @servlet_env.getRequestURI || "" env["REQUEST_URI"] += "?#{@servlet_env.getQueryString}" if @servlet_env.getQueryString env["REQUEST_URI"] end def load__PATH_INFO(env) path_info = @servlet_env.getServletPath || "" path_info += @servlet_env.getPathInfo if @servlet_env.getPathInfo env["PATH_INFO"] = path_info end def load__QUERY_STRING(env) env["QUERY_STRING"] = @servlet_env.getQueryString || "" end def load__SERVER_NAME(env) env["SERVER_NAME"] = @servlet_env.getServerName || "" end def load__REMOTE_HOST(env) env["REMOTE_HOST"] = @servlet_env.getRemoteHost || "" end def load__REMOTE_ADDR(env) env["REMOTE_ADDR"] = @servlet_env.getRemoteAddr || "" end def load__REMOTE_USER(env) env["REMOTE_USER"] = @servlet_env.getRemoteUser || "" end def load__SERVER_PORT(env) env["SERVER_PORT"] = @servlet_env.getServerPort.to_s end end end end PK:{8orack/handler/webrick.rbrequire 'webrick' require 'stringio' module Rack module Handler class WEBrick < WEBrick::HTTPServlet::AbstractServlet def self.run(app, options={}) server = ::WEBrick::HTTPServer.new(options) server.mount "/", Rack::Handler::WEBrick, app trap(:INT) { server.shutdown } yield server if block_given? server.start end def initialize(server, app) super server @app = app end def service(req, res) env = req.meta_vars env.delete_if { |k, v| v.nil? } env.update({"rack.version" => [0,1], "rack.input" => StringIO.new(req.body.to_s), "rack.errors" => STDERR, "rack.multithread" => true, "rack.multiprocess" => false, "rack.run_once" => false, "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" }) env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["QUERY_STRING"] ||= "" env["REQUEST_PATH"] ||= "/" env.delete "PATH_INFO" if env["PATH_INFO"] == "" status, headers, body = @app.call(env) begin res.status = status.to_i headers.each { |k, vs| vs.each { |v| res[k] = v } } body.each { |part| res.body << part } ensure body.close if body.respond_to? :close end end end end end PK:{8޴]Xrack/session/cookie.rbXmodule Rack module Session # Rack::Session::Cookie provides simple cookie based session management. # The session is a Ruby Hash stored as base64 encoded marshalled data # set to :key (default: rack.session). # # Example: # # use Rack::Session::Cookie, :key => 'rack.session', # :domain => 'foo.com', # :path => '/', # :expire_after => 2592000 # # All parameters are optional. class Cookie def initialize(app, options={}) @app = app @key = options[:key] || "rack.session" @default_options = {:domain => nil, :path => "/", :expire_after => nil}.merge(options) end def call(env) load_session(env) status, headers, body = @app.call(env) commit_session(env, status, headers, body) end private def load_session(env) request = Rack::Request.new(env) session_data = request.cookies[@key] begin session_data = session_data.unpack("m*").first session_data = Marshal.load(session_data) env["rack.session"] = session_data rescue env["rack.session"] = Hash.new end env["rack.session.options"] = @default_options.dup end def commit_session(env, status, headers, body) session_data = Marshal.dump(env["rack.session"]) session_data = [session_data].pack("m*") if session_data.size > (4096 - @key.size) env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K. Content dropped.") [status, headers, body] else options = env["rack.session.options"] cookie = Hash.new cookie[:value] = session_data cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil? response = Rack::Response.new(body, status, headers) response.set_cookie(@key, cookie.merge(options)) response.to_a end end end end end PK:{8g/ rack/session/pool.rb # AUTHOR: blink ; blink#ruby-lang@irc.freenode.net module Rack module Session # Rack::Session::Pool provides simple cookie based session management. # Session data is stored in a hash held by @pool. The corresponding # session key sent to the client. # The pool is unmonitored and unregulated, which means that over # prolonged use the session pool will be very large. # # Example: # # use Rack::Session::Pool, :key => 'rack.session', # :domain => 'foo.com', # :path => '/', # :expire_after => 2592000 # # All parameters are optional. class Pool attr_reader :pool, :key def initialize(app, options={}) @app = app @key = options[:key] || "rack.session" @default_options = {:domain => nil, :path => "/", :expire_after => nil}.merge(options) @pool = Hash.new @default_context = context app, &nil end def call(env) @default_context.call(env) end def context(app, &block) Rack::Utils::Context.new self, app do |env| load_session env block[env] if block response = app.call(env) commit_session env, response response end end private def load_session(env) sess_id = env.fetch('HTTP_COOKIE','')[/#{@key}=([^,;]+)/,1] begin sess_id = Array.new(8){rand(16).to_s(16)}*'' end while @pool.key? sess_id if sess_id.nil? or !@pool.key? sess_id session = @pool.fetch sess_id, {} session.instance_variable_set '@dat', [sess_id, Time.now] @pool.store sess_id, env['rack.session'] = session env["rack.session.options"] = @default_options.dup end def commit_session(env, response) session = env['rack.session'] options = env['rack.session.options'] sdat = session.instance_variable_get '@dat' cookie = Utils.escape(@key)+'='+Utils.escape(sdat[0]) cookie<< "; domain=#{options[:domain]}" if options[:domain] cookie<< "; path=#{options[:path]}" if options[:path] cookie<< "; expires=#{sdat[1]+options[:expires_after]}" if options[:expires_after] case a = (h = response[1])['Set-Cookie'] when Array then a << cookie when String then h['Set-Cookie'] = [a, cookie] when nil then h['Set-Cookie'] = cookie end end end end end PK:{8 META-INF/PK:{8HM˨META-INF/jruby-rack.tld\ 1.0 jruby-rack urn:org.jruby.rack rails org.jruby.rack.RackTag empty Makes requests to the rails application and renders the results to the page path true true java.lang.String params false true java.lang.String rack org.jruby.rack.RackTag empty Makes requests to the rack application and renders the results to the page path true true java.lang.String params false true java.lang.String PK:{8|META-INF/MANIFEST.MFjManifest-Version: 1.0 Created-By: Buildr Build-By: nicksieger Build-Jdk: 1.5.0_13 Implementation-Title: JRuby Rack adapter Implementation-Version: PK4:{8 AMETA-INF/PK4:{8|META-INF/MANIFEST.MFPK4:{8HM˨META-INF/jruby-rack.tldPK4:{8Acgi/PK4:{8 Acgi/session/PK4:{85n !cgi/session/java_servlet_store.rbPK4:{8Ajruby/PK4:{8B750 7jruby/rack.rbPK4:{8 A jruby/rack/PK4:{8Ajruby/rack/boot/PK4:{8˟oA9jruby/rack/boot/merb.rbPK4:{8/S:jruby/rack/boot/rack.rbPK4:{8p;jruby/rack/boot/rails.rbPK4:{8 3 jruby/rack/merb.rbPK4:{8tHqtojruby/rack/rails.rbPK4:{8Hjruby/rack/rails_boot.rbPK4:{86(#ejruby/rack/rails_ext.rbPK4:{8~ŭjruby/rack/servlet_ext.rbPK4:{8}zV#jruby/rack/servlet_helper.rbPK4:{8Aorg/PK4:{8 A'org/jruby/PK4:{8ATorg/jruby/rack/PK4:{8D2MH-org/jruby/rack/DefaultRackApplication$1.classPK4:{8%n* % +Rorg/jruby/rack/DefaultRackApplication.classPK4:{84org/jruby/rack/DefaultRackApplicationFactory$1.classPK4:{84org/jruby/rack/DefaultRackApplicationFactory$2.classPK4:{8;L#6org/jruby/rack/DefaultRackApplicationFactory$3$1.classPK4:{8 '4 !org/jruby/rack/DefaultRackApplicationFactory$3.classPK4:{8M4d&org/jruby/rack/DefaultRackApplicationFactory$4.classPK4:{8~qlK-org/jruby/rack/DefaultRackApplicationFactory$ApplicationObjectFactory.classPK4:{8ycu2/org/jruby/rack/DefaultRackApplicationFactory.classPK4:{86l *Gorg/jruby/rack/DefaultRackDispatcher.classPK4:{8X5#48Sorg/jruby/rack/PoolingRackApplicationFactory$1.classPK4:{8Grw2[org/jruby/rack/PoolingRackApplicationFactory.classPK4:{8k@;$worg/jruby/rack/RackApplication.classPK4:{8"+yorg/jruby/rack/RackApplicationFactory.classPK4:{8V^#p{org/jruby/rack/RackDispatcher.classPK4:{8uGr!}org/jruby/rack/RackFilter$1.classPK4:{8̏!org/jruby/rack/RackFilter$2.classPK4:{8R`_Z5org/jruby/rack/RackFilter$ResponseStatusCapture.classPK4:{8@l org/jruby/rack/RackFilter.classPK4:{8~E0org/jruby/rack/RackInitializationException.classPK4:{8u9w)$!org/jruby/rack/RackResponse.classPK4:{819 org/jruby/rack/RackServlet.classPK4:{8/Ѧorg/jruby/rack/RackServletContextListener.classPK4:{8M4/4org/jruby/rack/RackTag$1.classPK4:{8ձ|c ^ org/jruby/rack/RackTag.classPK4:{8<1yorg/jruby/rack/SharedRackApplicationFactory.classPK4:{8ASorg/jruby/rack/merb/PK4:{8S4id4org/jruby/rack/merb/MerbRackApplicationFactory.classPK4:{8ڔơ4org/jruby/rack/merb/MerbServletContextListener.classPK4:{8AAorg/jruby/rack/rails/PK4:{8¼Dpk6yorg/jruby/rack/rails/RailsRackApplicationFactory.classPK4:{8ގ6=org/jruby/rack/rails/RailsServletContextListener.classPK4:{8Aorg/jruby/webapp/PK4:{8_3.":org/jruby/webapp/FileServlet.classPK4:{8d_+org/jruby/webapp/RailsContextListener.classPK4:{861#Zorg/jruby/webapp/RailsServlet.classPK4:{8qo( # Irack.rbPK4:{8A!rack/PK4:{8 A<rack/adapter/PK4:{8{J64rack/adapter/camping.rbPK4:{8'u6rack/adapter/rails.rbPK4:{8 A(=rack/auth/PK4:{8AIrack/auth/abstract/PK4:{8+&T`rack/auth/abstract/handler.rbPK4:{8bbrack/auth/abstract/request.rbPK4:{8WIrack/auth/basic.rbPK4:{8ANrack/auth/digest/PK4:{81r0 + erack/auth/digest/md5.rbPK4:{8prack/auth/digest/nonce.rbPK4:{8hUurack/auth/digest/params.rbPK4:{8 9zrack/auth/digest/request.rbPK4:{8Fd50Nrack/auth/openid.rbPK4:{8p^U=rack/builder.rbPK4:{8;Ak8kfBrack/cascade.rbPK4:{8;ķ!Erack/commonlogger.rbPK4:{8GO Jrack/file.rbPK4:{8 AWrack/handler/PK4:{8n}rack/handler/cgi.rbPK4:{85ipkrack/handler/fastcgi.rbPK4:{8@frack/handler/lsws.rbPK4:{8͝QL\rack/handler/mongrel.rbPK4:{8Q$rack/handler/scgi.rbPK4:{8G/*8rack/handler/servlet.rbPK4:{8orack/handler/webrick.rbPK4:{8X:S: Xrack/lint.rbPK4:{8brack/lobster.rbPK4:{83Ixs rack/mock.rbPK4:{8yN<arack/recursive.rbPK4:{8.Erack/reloader.rbPK4:{8Ewjrack/request.rbPK4:{8@h?:Urack/response.rbPK4:{8 Arack/session/PK4:{8޴]Xrack/session/cookie.rbPK4:{8g/ zrack/session/pool.rbPK4:{8+**rack/showexceptions.rbPK4:{8( rack/showstatus.rbPK4:{8cb rack/static.rbPK4:{8Ve prack/urlmap.rbPK4:{8< rack/utils.rbPKee