about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorzedshaw <zedshaw@19e92222-5c0b-0410-8929-a290d50e31e9>2006-01-28 19:03:53 +0000
committerzedshaw <zedshaw@19e92222-5c0b-0410-8929-a290d50e31e9>2006-01-28 19:03:53 +0000
commit004dec2c2f44a0db510dfd65e5ffd8c9fc4ff83e (patch)
treea8b7de6debeb447af5479bf156706d09fe748ab4
parentb6d34b2a4191a3118c7c70ea49349e89e581ed91 (diff)
downloadunicorn-004dec2c2f44a0db510dfd65e5ffd8c9fc4ff83e.tar.gz
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@4 19e92222-5c0b-0410-8929-a290d50e31e9
-rw-r--r--COPYING504
-rw-r--r--LICENSE504
-rw-r--r--README52
-rw-r--r--Rakefile30
-rw-r--r--doc/rdoc/classes/Mongrel.html130
-rw-r--r--doc/rdoc/classes/Mongrel/Error404Handler.html171
-rw-r--r--doc/rdoc/classes/Mongrel/Error404Handler.src/M000019.html18
-rw-r--r--doc/rdoc/classes/Mongrel/Error404Handler.src/M000020.html18
-rw-r--r--doc/rdoc/classes/Mongrel/HttpHandler.html159
-rw-r--r--doc/rdoc/classes/Mongrel/HttpHandler.src/M000017.html17
-rw-r--r--doc/rdoc/classes/Mongrel/HttpParser.html265
-rw-r--r--doc/rdoc/classes/Mongrel/HttpParser.src/M000001.html28
-rw-r--r--doc/rdoc/classes/Mongrel/HttpParser.src/M000002.html29
-rw-r--r--doc/rdoc/classes/Mongrel/HttpParser.src/M000003.html29
-rw-r--r--doc/rdoc/classes/Mongrel/HttpParser.src/M000004.html33
-rw-r--r--doc/rdoc/classes/Mongrel/HttpParser.src/M000005.html27
-rw-r--r--doc/rdoc/classes/Mongrel/HttpParser.src/M000006.html27
-rw-r--r--doc/rdoc/classes/Mongrel/HttpParser.src/M000007.html28
-rw-r--r--doc/rdoc/classes/Mongrel/HttpRequest.html177
-rw-r--r--doc/rdoc/classes/Mongrel/HttpRequest.src/M000021.html30
-rw-r--r--doc/rdoc/classes/Mongrel/HttpResponse.html159
-rw-r--r--doc/rdoc/classes/Mongrel/HttpResponse.src/M000018.html18
-rw-r--r--doc/rdoc/classes/Mongrel/HttpServer.html300
-rw-r--r--doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html19
-rw-r--r--doc/rdoc/classes/Mongrel/HttpServer.src/M000009.html59
-rw-r--r--doc/rdoc/classes/Mongrel/HttpServer.src/M000010.html22
-rw-r--r--doc/rdoc/classes/Mongrel/HttpServer.src/M000011.html18
-rw-r--r--doc/rdoc/classes/Mongrel/HttpServer.src/M000012.html18
-rw-r--r--doc/rdoc/classes/Mongrel/URIClassifier.html257
-rw-r--r--doc/rdoc/classes/Mongrel/URIClassifier.src/M000013.html54
-rw-r--r--doc/rdoc/classes/Mongrel/URIClassifier.src/M000014.html50
-rw-r--r--doc/rdoc/classes/Mongrel/URIClassifier.src/M000015.html36
-rw-r--r--doc/rdoc/classes/Mongrel/URIClassifier.src/M000016.html73
-rw-r--r--doc/rdoc/created.rid1
-rw-r--r--doc/rdoc/files/COPYING.html756
-rw-r--r--doc/rdoc/files/LICENSE.html756
-rw-r--r--doc/rdoc/files/README.html170
-rw-r--r--doc/rdoc/files/ext/http11/http11_c.html101
-rw-r--r--doc/rdoc/files/lib/mongrel_rb.html110
-rw-r--r--doc/rdoc/fr_class_index.html34
-rw-r--r--doc/rdoc/fr_file_index.html31
-rw-r--r--doc/rdoc/fr_method_index.html47
-rw-r--r--doc/rdoc/index.html24
-rw-r--r--doc/rdoc/rdoc-style.css208
-rw-r--r--examples/simpletest.rb15
-rw-r--r--examples/tepee.rb178
-rw-r--r--examples/webrick_compare.rb20
-rw-r--r--ext/http11/MANIFEST0
-rw-r--r--ext/http11/ext_help.h14
-rw-r--r--ext/http11/extconf.rb6
-rw-r--r--ext/http11/http11.c429
-rw-r--r--ext/http11/http11_parser.c918
-rw-r--r--ext/http11/http11_parser.h37
-rw-r--r--ext/http11/http11_parser.rl162
-rw-r--r--ext/http11/tst.h40
-rw-r--r--ext/http11/tst_cleanup.c24
-rw-r--r--ext/http11/tst_delete.c146
-rw-r--r--ext/http11/tst_grow_node_free_list.c38
-rw-r--r--ext/http11/tst_init.c41
-rw-r--r--ext/http11/tst_insert.c192
-rw-r--r--ext/http11/tst_search.c54
-rw-r--r--lib/mongrel.rb191
-rw-r--r--setup.rb1360
-rw-r--r--test/.test_ws.rb.swpbin0 -> 12288 bytes
-rw-r--r--test/test_http11.rb31
-rw-r--r--test/test_uriclassifier.rb104
-rw-r--r--test/test_ws.rb33
-rw-r--r--tools/rakehelp.rb99
68 files changed, 9729 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..b1e3f5a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,504 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b1e3f5a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,504 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/README b/README
new file mode 100644
index 0000000..7a8f954
--- /dev/null
+++ b/README
@@ -0,0 +1,52 @@
+== Mongrel:  Simple Fast Mostly Ruby Web Server
+
+Mongrel is a small library that provides a very fast HTTP 1.1 server for Ruby
+web applications.  It is not particular to any framework, and is intended to
+be just enough to get a web application running behind a more complete and robust
+web server.
+
+What makes Mongrel so fast is the careful use of a C extension to provide fast
+HTTP 1.1 protocol parsing and fast URI lookup.  This combination makes the server
+very fast without too many portability issues.
+
+== Status
+
+Mongrel is still very ALPHA work, but you can see how it's used with the
+Camping framework (version 1.2) and take a look at how you might use it.
+Right now it handles HTTP requests well and process the responses fast, but
+you have to "roll your own" response code.
+
+The next release of Mongrel will have improved IO handling, much more stability,
+and should have a better Mongrel::HttpResponse object with more useful features.
+
+== Install
+
+You can install it via source from http://www.zedshaw.com/downloads/mongrel/
+or you can gram a RubyGem at http://www.zedshaw.com/downloads/mongrel/
+and install that manually.  I'm working on setting up a RubyForge project.
+
+It doesn't explicitly require Camping, but if you want to run the examples/tepee.rb
+example then you'll need to install Camping 1.2 at least (and redcloth I think).  
+These are all available from RubyGems.
+
+The library consists of a C extension so you'll need a C compiler or at least a friend
+who can build it for you.
+
+
+Finally, the source include a setup.rb for those who hate RubyGems.
+
+== Usage
+
+Best place to look for usage examples right now is the examples/ directory.
+
+== Speed
+
+This 0.1.2 release will not be as fast as the 0.1.1 release since I've temporarily
+removed threads as a test.  There were many stability issues related to handling
+each request in a thread, especially on OSX.  I've taken them out for now to
+make things stable.  Even with this removed Mongrel is still pretty fast compared
+to WEBrick.
+
+== Contact
+
+E-mail zedshaw at zedshaw.com and I'll help.  Comments about the API are welcome.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..01557f4
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,30 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/clean'
+require 'rake/gempackagetask'
+require 'rake/rdoctask'
+require 'tools/rakehelp'
+require 'fileutils'
+include FileUtils
+
+setup_tests
+setup_clean ["ext/http11/Makefile", "pkg", "lib/*.bundle", "ext/http11/*.bundle"]
+setup_rdoc ['README', 'LICENSE', 'COPYING', 'lib/*.rb',
+            'doc/**/*.rdoc', 'ext/http11/http11.c']
+
+desc "Does a full compile, test run"
+task :default => [:compile, :test]
+
+desc "Compiles all extensions"
+task :compile => [:http11]
+task :package => [:clean]
+
+task :ragel do
+        sh %{/usr/local/bin/ragel ext/http11/http11_parser.rl | /usr/local/bin/rlcodegen -G2 -o ext/http11/http11_parser.c}
+end
+
+setup_extension("http11", "http11")
+
+summary = "An experimental fast simple web server for Ruby."
+test_file = "test/test_ws.rb"
+setup_gem("mongrel", "0.1.2",  "Zed A. Shaw", summary, [], test_file)
diff --git a/doc/rdoc/classes/Mongrel.html b/doc/rdoc/classes/Mongrel.html
new file mode 100644
index 0000000..72cd9be
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel.html
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Module: Mongrel</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>Module</strong></td>
+          <td class="class-name-in-header">Mongrel</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+                <a href="../files/lib/mongrel_rb.html">
+                lib/mongrel.rb
+                </a>
+        <br />
+                <a href="../files/ext/http11/http11_c.html">
+                ext/http11/http11.c
+                </a>
+        <br />
+            </td>
+        </tr>
+
+        </table>
+    </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <p>
+<a href="Mongrel.html">Mongrel</a> module containing all of the classes
+(include C extensions) for running a <a href="Mongrel.html">Mongrel</a> web
+server. It contains a minimalist HTTP server with just enough functionality
+to service web application requests fast as possible.
+</p>
+
+    </div>
+
+
+   </div>
+
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+    <div id="class-list">
+      <h3 class="section-bar">Classes and Modules</h3>
+
+      Class <a href="Mongrel/Error404Handler.html" class="link">Mongrel::Error404Handler</a><br />
+Class <a href="Mongrel/HttpHandler.html" class="link">Mongrel::HttpHandler</a><br />
+Class <a href="Mongrel/HttpParser.html" class="link">Mongrel::HttpParser</a><br />
+Class <a href="Mongrel/HttpRequest.html" class="link">Mongrel::HttpRequest</a><br />
+Class <a href="Mongrel/HttpResponse.html" class="link">Mongrel::HttpResponse</a><br />
+Class <a href="Mongrel/HttpServer.html" class="link">Mongrel::HttpServer</a><br />
+Class <a href="Mongrel/URIClassifier.html" class="link">Mongrel::URIClassifier</a><br />
+
+    </div>
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/Error404Handler.html b/doc/rdoc/classes/Mongrel/Error404Handler.html
new file mode 100644
index 0000000..a227f40
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/Error404Handler.html
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Class: Mongrel::Error404Handler</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>Class</strong></td>
+          <td class="class-name-in-header">Mongrel::Error404Handler</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+                <a href="../../files/lib/mongrel_rb.html">
+                lib/mongrel.rb
+                </a>
+        <br />
+            </td>
+        </tr>
+
+        <tr class="top-aligned-row">
+            <td><strong>Parent:</strong></td>
+            <td>
+                <a href="HttpHandler.html">
+                HttpHandler
+               </a>
+            </td>
+        </tr>
+        </table>
+    </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <p>
+The server normally returns a 404 response if a URI is requested, but it
+also returns a lame empty message. This lets you do a 404 response with a
+custom message for special URIs.
+</p>
+
+    </div>
+
+
+   </div>
+
+    <div id="method-list">
+      <h3 class="section-bar">Methods</h3>
+
+      <div class="name-list">
+      <a href="#M000019">new</a>&nbsp;&nbsp;
+      <a href="#M000020">process</a>&nbsp;&nbsp;
+      </div>
+    </div>
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+    <div id="methods">
+      <h3 class="section-bar">Public Class methods</h3>
+
+      <div id="method-M000019" class="method-detail">
+        <a name="M000019"></a>
+
+        <div class="method-heading">
+          <a href="Error404Handler.src/M000019.html" target="Code" class="method-signature"
+            onclick="popupCode('Error404Handler.src/M000019.html');return false;">
+          <span class="method-name">new</span><span class="method-args">(msg)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Sets the message to return. This is constructed once for the handler so
+it&#8217;s pretty efficient.
+</p>
+        </div>
+      </div>
+
+      <h3 class="section-bar">Public Instance methods</h3>
+
+      <div id="method-M000020" class="method-detail">
+        <a name="M000020"></a>
+
+        <div class="method-heading">
+          <a href="Error404Handler.src/M000020.html" target="Code" class="method-signature"
+            onclick="popupCode('Error404Handler.src/M000020.html');return false;">
+          <span class="method-name">process</span><span class="method-args">(request, response)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Just kicks back the standard 404 response with your special message.
+</p>
+        </div>
+      </div>
+
+
+    </div>
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/Error404Handler.src/M000019.html b/doc/rdoc/classes/Mongrel/Error404Handler.src/M000019.html
new file mode 100644
index 0000000..6cb8774
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/Error404Handler.src/M000019.html
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>new (Mongrel::Error404Handler)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>    <span class="ruby-comment cmt"># File lib/mongrel.rb, line 75</span>
+75:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">msg</span>)
+76:       <span class="ruby-ivar">@response</span> = <span class="ruby-constant">HttpServer</span><span class="ruby-operator">::</span><span class="ruby-constant">ERROR_404_RESPONSE</span> <span class="ruby-operator">+</span> <span class="ruby-identifier">msg</span>
+77:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/Error404Handler.src/M000020.html b/doc/rdoc/classes/Mongrel/Error404Handler.src/M000020.html
new file mode 100644
index 0000000..76d5a15
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/Error404Handler.src/M000020.html
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>process (Mongrel::Error404Handler)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>    <span class="ruby-comment cmt"># File lib/mongrel.rb, line 80</span>
+80:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">process</span>(<span class="ruby-identifier">request</span>, <span class="ruby-identifier">response</span>)
+81:       <span class="ruby-identifier">response</span>.<span class="ruby-identifier">socket</span>.<span class="ruby-identifier">write</span>(<span class="ruby-ivar">@response</span>)
+82:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpHandler.html b/doc/rdoc/classes/Mongrel/HttpHandler.html
new file mode 100644
index 0000000..55f6f3a
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpHandler.html
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Class: Mongrel::HttpHandler</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>Class</strong></td>
+          <td class="class-name-in-header">Mongrel::HttpHandler</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+                <a href="../../files/lib/mongrel_rb.html">
+                lib/mongrel.rb
+                </a>
+        <br />
+            </td>
+        </tr>
+
+        <tr class="top-aligned-row">
+            <td><strong>Parent:</strong></td>
+            <td>
+                Object
+            </td>
+        </tr>
+        </table>
+    </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <p>
+You implement your application handler with this. It&#8217;s very light
+giving just the minimum necessary for you to handle a request and shoot
+back a response. Look at the <a href="HttpRequest.html">HttpRequest</a> and
+<a href="HttpResponse.html">HttpResponse</a> objects for how to use them.
+</p>
+
+    </div>
+
+
+   </div>
+
+    <div id="method-list">
+      <h3 class="section-bar">Methods</h3>
+
+      <div class="name-list">
+      <a href="#M000017">process</a>&nbsp;&nbsp;
+      </div>
+    </div>
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+    <div id="attribute-list">
+      <h3 class="section-bar">Attributes</h3>
+
+      <div class="name-list">
+        <table>
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">script_name</td>
+          <td class="context-item-value">&nbsp;[RW]&nbsp;</td>
+          <td class="context-item-desc"></td>
+        </tr>
+        </table>
+      </div>
+    </div>
+      
+
+
+    <!-- if method_list -->
+    <div id="methods">
+      <h3 class="section-bar">Public Instance methods</h3>
+
+      <div id="method-M000017" class="method-detail">
+        <a name="M000017"></a>
+
+        <div class="method-heading">
+          <a href="HttpHandler.src/M000017.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpHandler.src/M000017.html');return false;">
+          <span class="method-name">process</span><span class="method-args">(request, response)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+        </div>
+      </div>
+
+
+    </div>
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpHandler.src/M000017.html b/doc/rdoc/classes/Mongrel/HttpHandler.src/M000017.html
new file mode 100644
index 0000000..9b5f53c
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpHandler.src/M000017.html
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>process (Mongrel::HttpHandler)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>    <span class="ruby-comment cmt"># File lib/mongrel.rb, line 64</span>
+64:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">process</span>(<span class="ruby-identifier">request</span>, <span class="ruby-identifier">response</span>)
+65:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpParser.html b/doc/rdoc/classes/Mongrel/HttpParser.html
new file mode 100644
index 0000000..13cc01c
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpParser.html
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Class: Mongrel::HttpParser</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>Class</strong></td>
+          <td class="class-name-in-header">Mongrel::HttpParser</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+                <a href="../../files/ext/http11/http11_c.html">
+                ext/http11/http11.c
+                </a>
+        <br />
+            </td>
+        </tr>
+
+        <tr class="top-aligned-row">
+            <td><strong>Parent:</strong></td>
+            <td>
+                Object
+            </td>
+        </tr>
+        </table>
+    </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+
+
+   </div>
+
+    <div id="method-list">
+      <h3 class="section-bar">Methods</h3>
+
+      <div class="name-list">
+      <a href="#M000005">error?</a>&nbsp;&nbsp;
+      <a href="#M000004">execute</a>&nbsp;&nbsp;
+      <a href="#M000003">finish</a>&nbsp;&nbsp;
+      <a href="#M000006">finished?</a>&nbsp;&nbsp;
+      <a href="#M000001">new</a>&nbsp;&nbsp;
+      <a href="#M000007">nread</a>&nbsp;&nbsp;
+      <a href="#M000002">reset</a>&nbsp;&nbsp;
+      </div>
+    </div>
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+    <div id="methods">
+      <h3 class="section-bar">Public Class methods</h3>
+
+      <div id="method-M000001" class="method-detail">
+        <a name="M000001"></a>
+
+        <div class="method-heading">
+          <a href="HttpParser.src/M000001.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpParser.src/M000001.html');return false;">
+          <span class="method-name">parser.new &rarr; parser<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Creates a new parser.
+</p>
+        </div>
+      </div>
+
+      <h3 class="section-bar">Public Instance methods</h3>
+
+      <div id="method-M000005" class="method-detail">
+        <a name="M000005"></a>
+
+        <div class="method-heading">
+          <a href="HttpParser.src/M000005.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpParser.src/M000005.html');return false;">
+          <span class="method-name">parser.error? &rarr; true/false<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Tells you whether the parser is in an error state.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000004" class="method-detail">
+        <a name="M000004"></a>
+
+        <div class="method-heading">
+          <a href="HttpParser.src/M000004.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpParser.src/M000004.html');return false;">
+          <span class="method-name">parser.execute(req_hash, data) &rarr; Integer<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Takes a Hash and a String of data, parses the String of data filling in the
+Hash returning an Integer to indicate how much of the data has been read.
+No matter what the return value, you should call HttpParser#finished? and
+HttpParser#error? to figure out if it&#8217;s done parsing or there was an
+error.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000003" class="method-detail">
+        <a name="M000003"></a>
+
+        <div class="method-heading">
+          <a href="HttpParser.src/M000003.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpParser.src/M000003.html');return false;">
+          <span class="method-name">parser.finish &rarr; true/false<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Finishes a parser early which could put in a &quot;good&quot; or bad state.
+You should call reset after finish it or bad things will happen.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000006" class="method-detail">
+        <a name="M000006"></a>
+
+        <div class="method-heading">
+          <a href="HttpParser.src/M000006.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpParser.src/M000006.html');return false;">
+          <span class="method-name">parser.finished? &rarr; true/false<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Tells you whether the parser is finished or not and in a good state.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000007" class="method-detail">
+        <a name="M000007"></a>
+
+        <div class="method-heading">
+          <a href="HttpParser.src/M000007.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpParser.src/M000007.html');return false;">
+          <span class="method-name">parser.nread &rarr; Integer<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Returns the amount of data processed so far during this processing cycle.
+It is set to 0 on initialize or reset calls and is incremented each time
+execute is called.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000002" class="method-detail">
+        <a name="M000002"></a>
+
+        <div class="method-heading">
+          <a href="HttpParser.src/M000002.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpParser.src/M000002.html');return false;">
+          <span class="method-name">parser.reset &rarr; nil<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Resets the parser to it&#8217;s initial state so that you can reuse it
+rather than making new ones.
+</p>
+        </div>
+      </div>
+
+
+    </div>
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpParser.src/M000001.html b/doc/rdoc/classes/Mongrel/HttpParser.src/M000001.html
new file mode 100644
index 0000000..47326b1
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpParser.src/M000001.html
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>new (Mongrel::HttpParser)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    parser.new -&gt; parser
+ *
+ * Creates a new parser.
+ */
+VALUE HttpParser_init(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  http_parser_init(http);
+  
+  return self;
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpParser.src/M000002.html b/doc/rdoc/classes/Mongrel/HttpParser.src/M000002.html
new file mode 100644
index 0000000..5ff567b
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpParser.src/M000002.html
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>reset (Mongrel::HttpParser)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    parser.reset -&gt; nil
+ *
+ * Resets the parser to it's initial state so that you can reuse it
+ * rather than making new ones.
+ */
+VALUE HttpParser_reset(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  http_parser_init(http);
+  
+  return Qnil;
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpParser.src/M000003.html b/doc/rdoc/classes/Mongrel/HttpParser.src/M000003.html
new file mode 100644
index 0000000..7dfc546
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpParser.src/M000003.html
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>finish (Mongrel::HttpParser)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    parser.finish -&gt; true/false
+ *
+ * Finishes a parser early which could put in a &quot;good&quot; or bad state.
+ * You should call reset after finish it or bad things will happen.
+ */
+VALUE HttpParser_finish(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  http_parser_finish(http);
+  
+  return http_parser_is_finished(http) ? Qtrue : Qfalse;
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpParser.src/M000004.html b/doc/rdoc/classes/Mongrel/HttpParser.src/M000004.html
new file mode 100644
index 0000000..9ee1f57
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpParser.src/M000004.html
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>execute (Mongrel::HttpParser)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    parser.execute(req_hash, data) -&gt; Integer
+ *
+ * Takes a Hash and a String of data, parses the String of data filling in the Hash
+ * returning an Integer to indicate how much of the data has been read.  No matter
+ * what the return value, you should call HttpParser#finished? and HttpParser#error?
+ * to figure out if it's done parsing or there was an error.
+ */
+VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+
+  http-&gt;data = (void *)req_hash;
+  http_parser_execute(http, RSTRING(data)-&gt;ptr, RSTRING(data)-&gt;len);
+  
+  return INT2FIX(http_parser_nread(http));
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpParser.src/M000005.html b/doc/rdoc/classes/Mongrel/HttpParser.src/M000005.html
new file mode 100644
index 0000000..e8ebe0e
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpParser.src/M000005.html
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>error? (Mongrel::HttpParser)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    parser.error? -&gt; true/false
+ *
+ * Tells you whether the parser is in an error state.
+ */
+VALUE HttpParser_has_error(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  
+  return http_parser_has_error(http) ? Qtrue : Qfalse;
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpParser.src/M000006.html b/doc/rdoc/classes/Mongrel/HttpParser.src/M000006.html
new file mode 100644
index 0000000..a279344
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpParser.src/M000006.html
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>finished? (Mongrel::HttpParser)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    parser.finished? -&gt; true/false
+ *
+ * Tells you whether the parser is finished or not and in a good state.
+ */
+VALUE HttpParser_is_finished(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  
+  return http_parser_is_finished(http) ? Qtrue : Qfalse;
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpParser.src/M000007.html b/doc/rdoc/classes/Mongrel/HttpParser.src/M000007.html
new file mode 100644
index 0000000..2cfaca7
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpParser.src/M000007.html
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>nread (Mongrel::HttpParser)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    parser.nread -&gt; Integer
+ *
+ * Returns the amount of data processed so far during this processing cycle.  It is
+ * set to 0 on initialize or reset calls and is incremented each time execute is called.
+ */
+VALUE HttpParser_nread(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  
+  return INT2FIX(http-&gt;nread);
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpRequest.html b/doc/rdoc/classes/Mongrel/HttpRequest.html
new file mode 100644
index 0000000..525ed90
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpRequest.html
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Class: Mongrel::HttpRequest</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>Class</strong></td>
+          <td class="class-name-in-header">Mongrel::HttpRequest</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+                <a href="../../files/lib/mongrel_rb.html">
+                lib/mongrel.rb
+                </a>
+        <br />
+            </td>
+        </tr>
+
+        <tr class="top-aligned-row">
+            <td><strong>Parent:</strong></td>
+            <td>
+                Object
+            </td>
+        </tr>
+        </table>
+    </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <p>
+When a handler is found for a registered URI then this class is constructed
+and passed to your HttpHandler::process method. You should assume that
+<b>one</b> handler processes all requests. Included in the HttpReqeust is a
+HttpRequest.params Hash that matches common CGI params, and a
+HttpRequest.body which is a string containing the request body (raw for
+now).
+</p>
+<p>
+<a href="../Mongrel.html">Mongrel</a> really only support small-ish request
+bodies right now since really huge ones have to be completely read off the
+wire and put into a string. Later there will be several options for
+efficiently handling large file uploads.
+</p>
+
+    </div>
+
+
+   </div>
+
+    <div id="method-list">
+      <h3 class="section-bar">Methods</h3>
+
+      <div class="name-list">
+      <a href="#M000021">new</a>&nbsp;&nbsp;
+      </div>
+    </div>
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+    <div id="attribute-list">
+      <h3 class="section-bar">Attributes</h3>
+
+      <div class="name-list">
+        <table>
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">body</td>
+          <td class="context-item-value">&nbsp;[R]&nbsp;</td>
+          <td class="context-item-desc"></td>
+        </tr>
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">params</td>
+          <td class="context-item-value">&nbsp;[R]&nbsp;</td>
+          <td class="context-item-desc"></td>
+        </tr>
+        </table>
+      </div>
+    </div>
+      
+
+
+    <!-- if method_list -->
+    <div id="methods">
+      <h3 class="section-bar">Public Class methods</h3>
+
+      <div id="method-M000021" class="method-detail">
+        <a name="M000021"></a>
+
+        <div class="method-heading">
+          <a href="HttpRequest.src/M000021.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpRequest.src/M000021.html');return false;">
+          <span class="method-name">new</span><span class="method-args">(params, initial_body, socket)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+You don&#8217;t really call this. It&#8217;s made for you. Main thing it
+does is hook up the params, and store any remaining body data into the
+HttpRequest.body attribute.
+</p>
+        </div>
+      </div>
+
+
+    </div>
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpRequest.src/M000021.html b/doc/rdoc/classes/Mongrel/HttpRequest.src/M000021.html
new file mode 100644
index 0000000..39c1d18
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpRequest.src/M000021.html
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>new (Mongrel::HttpRequest)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>    <span class="ruby-comment cmt"># File lib/mongrel.rb, line 27</span>
+27:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">params</span>, <span class="ruby-identifier">initial_body</span>, <span class="ruby-identifier">socket</span>)
+28:       <span class="ruby-ivar">@body</span> = <span class="ruby-identifier">initial_body</span> <span class="ruby-operator">||</span> <span class="ruby-value str">&quot;&quot;</span>
+29:       <span class="ruby-ivar">@params</span> = <span class="ruby-identifier">params</span>
+30:       <span class="ruby-ivar">@socket</span> = <span class="ruby-identifier">socket</span>
+31:
+32:       <span class="ruby-comment cmt"># fix up the CGI requirements</span>
+33:       <span class="ruby-identifier">params</span>[<span class="ruby-value str">'CONTENT_LENGTH'</span>] = <span class="ruby-identifier">params</span>[<span class="ruby-value str">'HTTP_CONTENT_LENGTH'</span>] <span class="ruby-operator">||</span> <span class="ruby-value">0</span>
+34:
+35:       <span class="ruby-comment cmt"># now, if the initial_body isn't long enough for the content length we have to fill it</span>
+36:       <span class="ruby-comment cmt"># TODO: adapt for big ass stuff by writing to a temp file</span>
+37:       <span class="ruby-identifier">clen</span> = <span class="ruby-identifier">params</span>[<span class="ruby-value str">'HTTP_CONTENT_LENGTH'</span>].<span class="ruby-identifier">to_i</span>
+38:       <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@body</span>.<span class="ruby-identifier">length</span> <span class="ruby-operator">&lt;</span> <span class="ruby-identifier">clen</span>
+39:         <span class="ruby-ivar">@body</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-ivar">@socket</span>.<span class="ruby-identifier">read</span>(<span class="ruby-identifier">clen</span> <span class="ruby-operator">-</span> <span class="ruby-ivar">@body</span>.<span class="ruby-identifier">length</span>)
+40:       <span class="ruby-keyword kw">end</span>
+41:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpResponse.html b/doc/rdoc/classes/Mongrel/HttpResponse.html
new file mode 100644
index 0000000..89832b0
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpResponse.html
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Class: Mongrel::HttpResponse</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>Class</strong></td>
+          <td class="class-name-in-header">Mongrel::HttpResponse</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+                <a href="../../files/lib/mongrel_rb.html">
+                lib/mongrel.rb
+                </a>
+        <br />
+            </td>
+        </tr>
+
+        <tr class="top-aligned-row">
+            <td><strong>Parent:</strong></td>
+            <td>
+                Object
+            </td>
+        </tr>
+        </table>
+    </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <p>
+Very very simple response object. You basically write your stuff raw to the
+HttpResponse.socket variable. This will be made <b>much</b> easier in
+future releases allowing you to set status and request headers prior to
+sending the response.
+</p>
+
+    </div>
+
+
+   </div>
+
+    <div id="method-list">
+      <h3 class="section-bar">Methods</h3>
+
+      <div class="name-list">
+      <a href="#M000018">new</a>&nbsp;&nbsp;
+      </div>
+    </div>
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+    <div id="attribute-list">
+      <h3 class="section-bar">Attributes</h3>
+
+      <div class="name-list">
+        <table>
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">socket</td>
+          <td class="context-item-value">&nbsp;[R]&nbsp;</td>
+          <td class="context-item-desc"></td>
+        </tr>
+        </table>
+      </div>
+    </div>
+      
+
+
+    <!-- if method_list -->
+    <div id="methods">
+      <h3 class="section-bar">Public Class methods</h3>
+
+      <div id="method-M000018" class="method-detail">
+        <a name="M000018"></a>
+
+        <div class="method-heading">
+          <a href="HttpResponse.src/M000018.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpResponse.src/M000018.html');return false;">
+          <span class="method-name">new</span><span class="method-args">(socket)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+        </div>
+      </div>
+
+
+    </div>
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpResponse.src/M000018.html b/doc/rdoc/classes/Mongrel/HttpResponse.src/M000018.html
new file mode 100644
index 0000000..9086679
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpResponse.src/M000018.html
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>new (Mongrel::HttpResponse)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>    <span class="ruby-comment cmt"># File lib/mongrel.rb, line 51</span>
+51:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">socket</span>)
+52:       <span class="ruby-ivar">@socket</span> = <span class="ruby-identifier">socket</span>
+53:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpServer.html b/doc/rdoc/classes/Mongrel/HttpServer.html
new file mode 100644
index 0000000..f3632cc
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpServer.html
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Class: Mongrel::HttpServer</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>Class</strong></td>
+          <td class="class-name-in-header">Mongrel::HttpServer</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+                <a href="../../files/lib/mongrel_rb.html">
+                lib/mongrel.rb
+                </a>
+        <br />
+            </td>
+        </tr>
+
+        <tr class="top-aligned-row">
+            <td><strong>Parent:</strong></td>
+            <td>
+                Object
+            </td>
+        </tr>
+        </table>
+    </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <p>
+This is the main driver of <a href="../Mongrel.html">Mongrel</a>, while the
+Mognrel::HttpParser and <a
+href="URIClassifier.html">Mongrel::URIClassifier</a> make up the majority
+of how the server functions. It&#8217;s a very simple class that just has a
+thread accepting connections and a simple <a
+href="HttpServer.html#M000009">HttpServer.process_client</a> function to do
+the heavy lifting with the IO and Ruby.
+</p>
+<p>
+*NOTE:* The <a href="HttpServer.html#M000009">process_client</a> function
+used threads at one time but that proved to have stability issues on Mac
+OSX. Actually, Ruby in general has stability issues on Mac OSX.
+</p>
+<p>
+You use it by doing the following:
+</p>
+<pre>
+  server = HttpServer.new(&quot;0.0.0.0&quot;, 3000)
+  server.register(&quot;/stuff&quot;, MyNifterHandler.new)
+  server.run.join
+</pre>
+<p>
+The last line can be just server.run if you don&#8217;t want to join the
+thread used. If you don&#8217;t though Ruby will mysteriously just exit on
+you.
+</p>
+
+    </div>
+
+
+   </div>
+
+    <div id="method-list">
+      <h3 class="section-bar">Methods</h3>
+
+      <div class="name-list">
+      <a href="#M000008">new</a>&nbsp;&nbsp;
+      <a href="#M000009">process_client</a>&nbsp;&nbsp;
+      <a href="#M000011">register</a>&nbsp;&nbsp;
+      <a href="#M000010">run</a>&nbsp;&nbsp;
+      <a href="#M000012">unregister</a>&nbsp;&nbsp;
+      </div>
+    </div>
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+    <div id="constants-list">
+      <h3 class="section-bar">Constants</h3>
+
+      <div class="name-list">
+        <table summary="Constants">
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">ERROR_404_RESPONSE</td>
+          <td>=</td>
+          <td class="context-item-value">&quot;HTTP/1.1 404 Not Found\r\nConnection: close\r\nContent-Type: text/plain\r\nServer: Mongrel/0.1\r\n\r\n&quot;</td>
+          <td width="3em">&nbsp;</td>
+          <td class="context-item-desc">
+The standard empty 404 response for bad requests. Use Error4040Handler for
+custom stuff.
+
+</td>
+        </tr>
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">CHUNK_SIZE</td>
+          <td>=</td>
+          <td class="context-item-value">2048</td>
+          <td width="3em">&nbsp;</td>
+          <td class="context-item-desc">
+For now we just read 2k chunks. Not optimal at all.
+
+</td>
+        </tr>
+        </table>
+      </div>
+    </div>
+
+
+
+    <div id="attribute-list">
+      <h3 class="section-bar">Attributes</h3>
+
+      <div class="name-list">
+        <table>
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">acceptor</td>
+          <td class="context-item-value">&nbsp;[R]&nbsp;</td>
+          <td class="context-item-desc"></td>
+        </tr>
+        </table>
+      </div>
+    </div>
+      
+
+
+    <!-- if method_list -->
+    <div id="methods">
+      <h3 class="section-bar">Public Class methods</h3>
+
+      <div id="method-M000008" class="method-detail">
+        <a name="M000008"></a>
+
+        <div class="method-heading">
+          <a href="HttpServer.src/M000008.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpServer.src/M000008.html');return false;">
+          <span class="method-name">new</span><span class="method-args">(host, port)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Creates a working server on host:port (strange things happen if port
+isn&#8217;t a Number). Use HttpServer::run to start the server.
+</p>
+        </div>
+      </div>
+
+      <h3 class="section-bar">Public Instance methods</h3>
+
+      <div id="method-M000009" class="method-detail">
+        <a name="M000009"></a>
+
+        <div class="method-heading">
+          <a href="HttpServer.src/M000009.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpServer.src/M000009.html');return false;">
+          <span class="method-name">process_client</span><span class="method-args">(client)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Used internally to process an accepted client. It uses <a
+href="HttpParser.html">HttpParser</a> and <a
+href="URIClassifier.html">URIClassifier</a> (in ext/http11/http11.c) to do
+the heavy work, and mostly just does a hack job at some simple IO. Future
+releases will target this area mostly.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000011" class="method-detail">
+        <a name="M000011"></a>
+
+        <div class="method-heading">
+          <a href="HttpServer.src/M000011.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpServer.src/M000011.html');return false;">
+          <span class="method-name">register</span><span class="method-args">(uri, handler)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Simply registers a handler with the internal <a
+href="URIClassifier.html">URIClassifier</a>. When the URI is found in the
+prefix of a request then your handler&#8217;s HttpHandler::process method
+is called. See <a
+href="URIClassifier.html#M000014">Mongrel::URIClassifier#register</a> for
+more information.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000010" class="method-detail">
+        <a name="M000010"></a>
+
+        <div class="method-heading">
+          <a href="HttpServer.src/M000010.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpServer.src/M000010.html');return false;">
+          <span class="method-name">run</span><span class="method-args">()</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Runs the thing. It returns the thread used so you can &quot;join&quot; it.
+You can also access the HttpServer::acceptor attribute to get the thread
+later.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000012" class="method-detail">
+        <a name="M000012"></a>
+
+        <div class="method-heading">
+          <a href="HttpServer.src/M000012.html" target="Code" class="method-signature"
+            onclick="popupCode('HttpServer.src/M000012.html');return false;">
+          <span class="method-name">unregister</span><span class="method-args">(uri)</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Removes any handler registered at the given URI. See <a
+href="URIClassifier.html#M000015">Mongrel::URIClassifier#unregister</a> for
+more information.
+</p>
+        </div>
+      </div>
+
+
+    </div>
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html b/doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html
new file mode 100644
index 0000000..d5b5591
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>new (Mongrel::HttpServer)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>     <span class="ruby-comment cmt"># File lib/mongrel.rb, line 114</span>
+114:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">host</span>, <span class="ruby-identifier">port</span>)
+115:       <span class="ruby-ivar">@socket</span> = <span class="ruby-constant">TCPServer</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">host</span>, <span class="ruby-identifier">port</span>)
+116:       <span class="ruby-ivar">@classifier</span> = <span class="ruby-constant">URIClassifier</span>.<span class="ruby-identifier">new</span>
+117:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpServer.src/M000009.html b/doc/rdoc/classes/Mongrel/HttpServer.src/M000009.html
new file mode 100644
index 0000000..5181e70
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpServer.src/M000009.html
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>process_client (Mongrel::HttpServer)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>     <span class="ruby-comment cmt"># File lib/mongrel.rb, line 122</span>
+122:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">process_client</span>(<span class="ruby-identifier">client</span>)
+123:       <span class="ruby-keyword kw">begin</span>
+124:         <span class="ruby-identifier">parser</span> = <span class="ruby-constant">HttpParser</span>.<span class="ruby-identifier">new</span>
+125:         <span class="ruby-identifier">params</span> = {}
+126:         <span class="ruby-identifier">data</span> = <span class="ruby-value str">&quot;&quot;</span>
+127:        
+128:         <span class="ruby-keyword kw">while</span> <span class="ruby-keyword kw">true</span>
+129:           <span class="ruby-identifier">data</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">client</span>.<span class="ruby-identifier">readpartial</span>(<span class="ruby-constant">CHUNK_SIZE</span>)
+130:          
+131:           <span class="ruby-identifier">nread</span> = <span class="ruby-identifier">parser</span>.<span class="ruby-identifier">execute</span>(<span class="ruby-identifier">params</span>, <span class="ruby-identifier">data</span>)
+132:          
+133:           <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">parser</span>.<span class="ruby-identifier">error?</span>
+134:             <span class="ruby-constant">STDERR</span>.<span class="ruby-identifier">puts</span> <span class="ruby-value str">&quot;parser error:&quot;</span>
+135:             <span class="ruby-constant">STDERR</span>.<span class="ruby-identifier">puts</span> <span class="ruby-identifier">data</span>
+136:             <span class="ruby-keyword kw">break</span>
+137:           <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">parser</span>.<span class="ruby-identifier">finished?</span>
+138:             <span class="ruby-identifier">script_name</span>, <span class="ruby-identifier">path_info</span>, <span class="ruby-identifier">handler</span> = <span class="ruby-ivar">@classifier</span>.<span class="ruby-identifier">resolve</span>(<span class="ruby-identifier">params</span>[<span class="ruby-value str">&quot;PATH_INFO&quot;</span>])
+139:            
+140:             <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">handler</span>
+141:               <span class="ruby-identifier">params</span>[<span class="ruby-value str">'PATH_INFO'</span>] = <span class="ruby-identifier">path_info</span>
+142:               <span class="ruby-identifier">params</span>[<span class="ruby-value str">'SCRIPT_NAME'</span>] = <span class="ruby-identifier">script_name</span>
+143:              
+144:               <span class="ruby-identifier">request</span> = <span class="ruby-constant">HttpRequest</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">params</span>, <span class="ruby-identifier">data</span>[<span class="ruby-identifier">nread</span> <span class="ruby-operator">...</span> <span class="ruby-identifier">data</span>.<span class="ruby-identifier">length</span>], <span class="ruby-identifier">client</span>)
+145:               <span class="ruby-identifier">response</span> = <span class="ruby-constant">HttpResponse</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">client</span>)
+146:              
+147:               <span class="ruby-identifier">handler</span>.<span class="ruby-identifier">process</span>(<span class="ruby-identifier">request</span>, <span class="ruby-identifier">response</span>)
+148:             <span class="ruby-keyword kw">else</span>
+149:               <span class="ruby-identifier">client</span>.<span class="ruby-identifier">write</span>(<span class="ruby-constant">ERROR_404_RESPONSE</span>)
+150:             <span class="ruby-keyword kw">end</span>
+151:            
+152:             <span class="ruby-keyword kw">break</span>
+153:           <span class="ruby-keyword kw">else</span>
+154:             <span class="ruby-comment cmt"># gotta stream and read again until we can get the parser to be character safe</span>
+155:             <span class="ruby-comment cmt"># TODO: make this more efficient since this means we're parsing a lot repeatedly</span>
+156:             <span class="ruby-identifier">parser</span>.<span class="ruby-identifier">reset</span>
+157:           <span class="ruby-keyword kw">end</span>
+158:         <span class="ruby-keyword kw">end</span>
+159:       <span class="ruby-keyword kw">rescue</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">details</span>
+160:         <span class="ruby-constant">STDERR</span>.<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;ERROR: #{details}&quot;</span>
+161:         <span class="ruby-constant">STDERR</span>.<span class="ruby-identifier">puts</span> <span class="ruby-identifier">details</span>.<span class="ruby-identifier">backtrace</span>.<span class="ruby-identifier">join</span>(<span class="ruby-value str">&quot;\n&quot;</span>)
+162:       <span class="ruby-keyword kw">ensure</span>
+163:         <span class="ruby-identifier">client</span>.<span class="ruby-identifier">close</span>
+164:       <span class="ruby-keyword kw">end</span>
+165:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpServer.src/M000010.html b/doc/rdoc/classes/Mongrel/HttpServer.src/M000010.html
new file mode 100644
index 0000000..c79c3e3
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpServer.src/M000010.html
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>run (Mongrel::HttpServer)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>     <span class="ruby-comment cmt"># File lib/mongrel.rb, line 169</span>
+169:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">run</span>
+170:       <span class="ruby-ivar">@acceptor</span> = <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">new</span> <span class="ruby-keyword kw">do</span>
+171:         <span class="ruby-keyword kw">while</span> <span class="ruby-keyword kw">true</span>
+172:           <span class="ruby-identifier">process_client</span>(<span class="ruby-ivar">@socket</span>.<span class="ruby-identifier">accept</span>)
+173:         <span class="ruby-keyword kw">end</span>
+174:       <span class="ruby-keyword kw">end</span>
+175:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpServer.src/M000011.html b/doc/rdoc/classes/Mongrel/HttpServer.src/M000011.html
new file mode 100644
index 0000000..7273b5d
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpServer.src/M000011.html
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>register (Mongrel::HttpServer)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>     <span class="ruby-comment cmt"># File lib/mongrel.rb, line 181</span>
+181:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">register</span>(<span class="ruby-identifier">uri</span>, <span class="ruby-identifier">handler</span>)
+182:       <span class="ruby-ivar">@classifier</span>.<span class="ruby-identifier">register</span>(<span class="ruby-identifier">uri</span>, <span class="ruby-identifier">handler</span>)
+183:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/HttpServer.src/M000012.html b/doc/rdoc/classes/Mongrel/HttpServer.src/M000012.html
new file mode 100644
index 0000000..1b8587c
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/HttpServer.src/M000012.html
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>unregister (Mongrel::HttpServer)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>     <span class="ruby-comment cmt"># File lib/mongrel.rb, line 187</span>
+187:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">unregister</span>(<span class="ruby-identifier">uri</span>)
+188:       <span class="ruby-ivar">@classifier</span>.<span class="ruby-identifier">unregister</span>(<span class="ruby-identifier">uri</span>)
+189:     <span class="ruby-keyword kw">end</span></pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/URIClassifier.html b/doc/rdoc/classes/Mongrel/URIClassifier.html
new file mode 100644
index 0000000..4708416
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/URIClassifier.html
@@ -0,0 +1,257 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Class: Mongrel::URIClassifier</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>Class</strong></td>
+          <td class="class-name-in-header">Mongrel::URIClassifier</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+                <a href="../../files/ext/http11/http11_c.html">
+                ext/http11/http11.c
+                </a>
+        <br />
+            </td>
+        </tr>
+
+        <tr class="top-aligned-row">
+            <td><strong>Parent:</strong></td>
+            <td>
+                Object
+            </td>
+        </tr>
+        </table>
+    </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+
+
+   </div>
+
+    <div id="method-list">
+      <h3 class="section-bar">Methods</h3>
+
+      <div class="name-list">
+      <a href="#M000013">new</a>&nbsp;&nbsp;
+      <a href="#M000014">register</a>&nbsp;&nbsp;
+      <a href="#M000016">resolve</a>&nbsp;&nbsp;
+      <a href="#M000015">unregister</a>&nbsp;&nbsp;
+      </div>
+    </div>
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+    <div id="methods">
+      <h3 class="section-bar">Public Class methods</h3>
+
+      <div id="method-M000013" class="method-detail">
+        <a name="M000013"></a>
+
+        <div class="method-heading">
+          <a href="URIClassifier.src/M000013.html" target="Code" class="method-signature"
+            onclick="popupCode('URIClassifier.src/M000013.html');return false;">
+          <span class="method-name">URIClassifier.new &rarr; URIClassifier<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Initializes a new <a href="URIClassifier.html">URIClassifier</a> object
+that you can use to associate URI sequences with objects. You can actually
+use it with any string sequence and any objects, but it&#8217;s mostly used
+with URIs.
+</p>
+<p>
+It uses TST from <a
+href="http://www.octavian.org/cs/software.html">www.octavian.org/cs/software.html</a>
+to build an ternary search trie to hold all of the URIs. It uses this to do
+an initial search for the a URI prefix, and then to break the URI into
+SCRIPT_NAME and PATH_INFO portions. It actually will do two searches most
+of the time in order to find the right handler for the registered prefix
+portion.
+</p>
+<p>
+Here&#8217;s how it all works. Let&#8217;s say you register
+&quot;/blog&quot; with a BlogHandler. Great. Now, someone goes to
+&quot;/blog/zedsucks/ass&quot;. You want SCRIPT_NAME to be
+&quot;/blog&quot; and PATH_INFO to be &quot;/zedsucks/ass&quot;. <a
+href="URIClassifier.html">URIClassifier</a> first does a TST search and
+comes up with a failure, but knows that the failure ended at the
+&quot;/blog&quot; part. So, that&#8217;s the SCRIPT_NAME. It then tries a
+second search for just &quot;/blog&quot;. If that comes back good then it
+sets the rest (&quot;/zedsucks/ass&quot;) to the PATH_INFO and returns the
+BlogHandler.
+</p>
+<p>
+The optimal approach would be to not do the search twice, but the TST lib
+doesn&#8217;t really support returning prefixes. Might not be hard to add
+later.
+</p>
+<p>
+The key though is that it will try to match the <b>longest</b> match it
+can. If you also register &quot;/blog/zed&quot; then the above URI will
+give SCRIPT_NAME=&quot;/blog/zed&quot;, PATH_INFO=&quot;sucks/ass&quot;.
+Probably not what you want, so your handler will need to do the 404 thing.
+</p>
+<p>
+Take a look at the postamble of example/tepee.rb to see how this is handled
+for Camping.
+</p>
+        </div>
+      </div>
+
+      <h3 class="section-bar">Public Instance methods</h3>
+
+      <div id="method-M000014" class="method-detail">
+        <a name="M000014"></a>
+
+        <div class="method-heading">
+          <a href="URIClassifier.src/M000014.html" target="Code" class="method-signature"
+            onclick="popupCode('URIClassifier.src/M000014.html');return false;">
+          <span class="method-name">uc.register("/someuri", SampleHandler.new) &rarr; nil<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Registers the SampleHandler (one for all requests) with the
+&quot;/someuri&quot;. When URIClassifier::resolve is called with
+&quot;/someuri&quot; it&#8217;ll return SampleHandler immediately. When
+&quot;/someuri/pathhere&quot; is called it&#8217;ll find SomeHandler after
+a second search, and setup PATH_INFO=&quot;/pathhere&quot;.
+</p>
+<p>
+You actually can reuse this class to register nearly anything and quickly
+resolve it. This could be used for caching, fast mapping, etc. The downside
+is it uses much more memory than a Hash, but it can be a lot faster.
+It&#8217;s main advantage is that it works on prefixes, which is damn hard
+to get right with a Hash.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000016" class="method-detail">
+        <a name="M000016"></a>
+
+        <div class="method-heading">
+          <a href="URIClassifier.src/M000016.html" target="Code" class="method-signature"
+            onclick="popupCode('URIClassifier.src/M000016.html');return false;">
+          <span class="method-name">uc.resolve("/someuri") &rarr; "/someuri", "", handler<br />
+uc.resolve("/someuri/pathinfo") &rarr; "/someuri", "/pathinfo", handler<br />
+uc.resolve("/notfound/orhere") &rarr; nil, nil, nil<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Attempts to resolve either the whole URI or at the longest prefix,
+returning the prefix (as script_info), path (as path_info), and registered
+handler (usually an <a href="HttpHandler.html">HttpHandler</a>).
+</p>
+<p>
+It expects strings. Don&#8216;t try other string-line stuff yet.
+</p>
+        </div>
+      </div>
+
+      <div id="method-M000015" class="method-detail">
+        <a name="M000015"></a>
+
+        <div class="method-heading">
+          <a href="URIClassifier.src/M000015.html" target="Code" class="method-signature"
+            onclick="popupCode('URIClassifier.src/M000015.html');return false;">
+          <span class="method-name">uc.unregister("/someuri")<br />
+</span>
+          </a>
+        </div>
+      
+        <div class="method-description">
+          <p>
+Yep, just removes this uri and it&#8217;s handler from the trie.
+</p>
+        </div>
+      </div>
+
+
+    </div>
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/URIClassifier.src/M000013.html b/doc/rdoc/classes/Mongrel/URIClassifier.src/M000013.html
new file mode 100644
index 0000000..a843bc8
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/URIClassifier.src/M000013.html
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>new (Mongrel::URIClassifier)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    URIClassifier.new -&gt; URIClassifier
+ *
+ * Initializes a new URIClassifier object that you can use to associate URI sequences
+ * with objects.  You can actually use it with any string sequence and any objects,
+ * but it's mostly used with URIs.
+ *
+ * It uses TST from http://www.octavian.org/cs/software.html to build an ternary search
+ * trie to hold all of the URIs.  It uses this to do an initial search for the a URI
+ * prefix, and then to break the URI into SCRIPT_NAME and PATH_INFO portions.  It actually
+ * will do two searches most of the time in order to find the right handler for the
+ * registered prefix portion.
+ *
+ * Here's how it all works.  Let's say you register &quot;/blog&quot; with a BlogHandler.  Great.
+ * Now, someone goes to &quot;/blog/zedsucks/ass&quot;.  You want SCRIPT_NAME to be &quot;/blog&quot; and
+ * PATH_INFO to be &quot;/zedsucks/ass&quot;.  URIClassifier first does a TST search and comes
+ * up with a failure, but knows that the failure ended at the &quot;/blog&quot; part.  So, that's
+ * the SCRIPT_NAME.  It then tries a second search for just &quot;/blog&quot;.  If that comes back
+ * good then it sets the rest (&quot;/zedsucks/ass&quot;) to the PATH_INFO and returns the BlogHandler.
+ *
+ * The optimal approach would be to not do the search twice, but the TST lib doesn't
+ * really support returning prefixes.  Might not be hard to add later.
+ *
+ * The key though is that it will try to match the *longest* match it can.  If you
+ * also register &quot;/blog/zed&quot; then the above URI will give SCRIPT_NAME=&quot;/blog/zed&quot;,
+ * PATH_INFO=&quot;sucks/ass&quot;.  Probably not what you want, so your handler will need to
+ * do the 404 thing.
+ *
+ * Take a look at the postamble of example/tepee.rb to see how this is handled for
+ * Camping.
+ */
+VALUE URIClassifier_init(VALUE self)
+{
+  VALUE hash;
+
+  // we create an internal hash to protect stuff from the GC
+  hash = rb_hash_new();
+  rb_iv_set(self, &quot;handler_map&quot;, hash);
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/URIClassifier.src/M000014.html b/doc/rdoc/classes/Mongrel/URIClassifier.src/M000014.html
new file mode 100644
index 0000000..5055109
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/URIClassifier.src/M000014.html
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>register (Mongrel::URIClassifier)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    uc.register(&quot;/someuri&quot;, SampleHandler.new) -&gt; nil
+ *
+ * Registers the SampleHandler (one for all requests) with the &quot;/someuri&quot;.
+ * When URIClassifier::resolve is called with &quot;/someuri&quot; it'll return
+ * SampleHandler immediately.  When &quot;/someuri/pathhere&quot; is called it'll
+ * find SomeHandler after a second search, and setup PATH_INFO=&quot;/pathhere&quot;.
+ *
+ * You actually can reuse this class to register nearly anything and
+ * quickly resolve it.  This could be used for caching, fast mapping, etc.
+ * The downside is it uses much more memory than a Hash, but it can be
+ * a lot faster.  It's main advantage is that it works on prefixes, which
+ * is damn hard to get right with a Hash.
+ */
+VALUE URIClassifier_register(VALUE self, VALUE uri, VALUE handler)
+{
+  int rc = 0;
+  void *ptr = NULL;
+  struct tst *tst = NULL;
+  DATA_GET(self, struct tst, tst);
+
+  rc = tst_insert((unsigned char *)StringValueCStr(uri), (void *)handler , tst, 0, &amp;ptr);
+
+  if(rc == TST_DUPLICATE_KEY) {
+    rb_raise(rb_eStandardError, &quot;Handler already registered with that name&quot;);
+  } else if(rc == TST_ERROR) {
+    rb_raise(rb_eStandardError, &quot;Memory error registering handler&quot;);
+  } else if(rc == TST_NULL_KEY) {
+    rb_raise(rb_eStandardError, &quot;URI was empty&quot;);
+  }
+  
+  rb_hash_aset(rb_iv_get(self, &quot;handler_map&quot;), uri, handler);
+
+  return Qnil;
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/URIClassifier.src/M000015.html b/doc/rdoc/classes/Mongrel/URIClassifier.src/M000015.html
new file mode 100644
index 0000000..4fafe2b
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/URIClassifier.src/M000015.html
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>unregister (Mongrel::URIClassifier)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    uc.unregister(&quot;/someuri&quot;)
+ *
+ * Yep, just removes this uri and it's handler from the trie.
+ */
+VALUE URIClassifier_unregister(VALUE self, VALUE uri)
+{
+  void *handler = NULL;
+  struct tst *tst = NULL;
+  DATA_GET(self, struct tst, tst);
+
+  handler = tst_delete((unsigned char *)StringValueCStr(uri), tst);
+
+  if(handler) {
+    rb_hash_delete(rb_iv_get(self, &quot;handler_map&quot;), uri);
+
+    return (VALUE)handler;
+  } else {
+    return Qnil;
+  }
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/classes/Mongrel/URIClassifier.src/M000016.html b/doc/rdoc/classes/Mongrel/URIClassifier.src/M000016.html
new file mode 100644
index 0000000..f545ea2
--- /dev/null
+++ b/doc/rdoc/classes/Mongrel/URIClassifier.src/M000016.html
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+  <title>resolve (Mongrel::URIClassifier)</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>/**
+ * call-seq:
+ *    uc.resolve(&quot;/someuri&quot;) -&gt; &quot;/someuri&quot;, &quot;&quot;, handler
+ *    uc.resolve(&quot;/someuri/pathinfo&quot;) -&gt; &quot;/someuri&quot;, &quot;/pathinfo&quot;, handler
+ *    uc.resolve(&quot;/notfound/orhere&quot;) -&gt; nil, nil, nil
+ *
+ * Attempts to resolve either the whole URI or at the longest prefix, returning
+ * the prefix (as script_info), path (as path_info), and registered handler
+ * (usually an HttpHandler).
+ *
+ * It expects strings.  Don't try other string-line stuff yet.
+ */
+VALUE URIClassifier_resolve(VALUE self, VALUE uri)
+{
+  void *handler = NULL;
+  int pref_len = 0;
+  struct tst *tst = NULL;
+  VALUE result;
+  VALUE script_name;
+  VALUE path_info;
+  unsigned char *uri_str = NULL;
+  unsigned char *script_name_str = NULL;
+
+  DATA_GET(self, struct tst, tst);
+  uri_str = (unsigned char *)StringValueCStr(uri);
+
+  handler = tst_search(uri_str, tst, &amp;pref_len);
+
+  // setup for multiple return values
+  result = rb_ary_new();
+
+
+  if(handler == NULL) {
+    script_name = rb_str_substr (uri, 0, pref_len);
+    script_name_str = (unsigned char *)StringValueCStr(script_name);
+
+    handler = tst_search(script_name_str, tst, NULL);
+
+    if(handler == NULL) {
+      // didn't find the script name at all
+      rb_ary_push(result, Qnil);
+      rb_ary_push(result, Qnil);
+      rb_ary_push(result, Qnil);
+      return result;
+    } else {
+      // found a handler, setup the path info and we're good
+      path_info = rb_str_substr(uri, pref_len, RSTRING(uri)-&gt;len);
+    }
+  } else {
+    // whole thing was found, so uri is the script name, path info empty
+    script_name = uri;
+    path_info = rb_str_new2(&quot;&quot;);
+  }
+
+  rb_ary_push(result, script_name);
+  rb_ary_push(result, path_info);
+  rb_ary_push(result, (VALUE)handler);
+  return result;
+}</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/created.rid b/doc/rdoc/created.rid
new file mode 100644
index 0000000..65487cc
--- /dev/null
+++ b/doc/rdoc/created.rid
@@ -0,0 +1 @@
+Thu Jan 26 01:27:35 EST 2006
diff --git a/doc/rdoc/files/COPYING.html b/doc/rdoc/files/COPYING.html
new file mode 100644
index 0000000..9b91916
--- /dev/null
+++ b/doc/rdoc/files/COPYING.html
@@ -0,0 +1,756 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>File: COPYING</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+  <div id="fileHeader">
+    <h1>COPYING</h1>
+    <table class="header-table">
+    <tr class="top-aligned-row">
+      <td><strong>Path:</strong></td>
+      <td>COPYING
+      </td>
+    </tr>
+    <tr class="top-aligned-row">
+      <td><strong>Last Update:</strong></td>
+      <td>Mon Jan 16 11:34:01 EST 2006</td>
+    </tr>
+    </table>
+  </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <pre>
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+</pre>
+<p>
+[This is the first released version of the Lesser GPL. It also counts
+</p>
+<pre>
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+</pre>
+<p>
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change free
+software&#8212;to make sure the software is free for all its users.
+</p>
+<pre>
+  This license, the Lesser General Public License, applies to some
+</pre>
+<p>
+specially designated software packages&#8212;typically libraries&#8212;of
+the Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether this
+license or the ordinary General Public License is the better strategy to
+use in any particular case, based on the explanations below.
+</p>
+<pre>
+  When we speak of free software, we are referring to freedom of use,
+</pre>
+<p>
+not price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for this
+service if you wish); that you receive source code or can get it if you
+want it; that you can change the software and use pieces of it in new free
+programs; and that you are informed that you can do these things.
+</p>
+<pre>
+  To protect your rights, we need to make restrictions that forbid
+</pre>
+<p>
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for you if
+you distribute copies of the library or if you modify it.
+</p>
+<pre>
+  For example, if you distribute copies of the library, whether gratis
+</pre>
+<p>
+or for a fee, you must give the recipients all the rights that we gave you.
+You must make sure that they, too, receive or can get the source code. If
+you link other code with the library, you must provide complete object
+files to the recipients, so that they can relink them with the library
+after making changes to the library and recompiling it. And you must show
+them these terms so they know their rights.
+</p>
+<pre>
+  We protect your rights with a two-step method: (1) we copyright the
+</pre>
+<p>
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+</p>
+<pre>
+  To protect each distributor, we want to make it very clear that
+</pre>
+<p>
+there is no warranty for the free library. Also, if the library is modified
+by someone else and passed on, the recipients should know that what they
+have is not the original version, so that the original author&#8217;s
+reputation will not be affected by problems that might be introduced by
+others.
+</p>
+<pre>
+  Finally, software patents pose a constant threat to the existence of
+</pre>
+<p>
+any free program. We wish to make sure that a company cannot effectively
+restrict the users of a free program by obtaining a restrictive license
+from a patent holder. Therefore, we insist that any patent license obtained
+for a version of the library must be consistent with the full freedom of
+use specified in this license.
+</p>
+<pre>
+  Most GNU software, including some libraries, is covered by the
+</pre>
+<p>
+ordinary GNU General Public License. This license, the GNU Lesser General
+Public License, applies to certain designated libraries, and is quite
+different from the ordinary General Public License. We use this license for
+certain libraries in order to permit linking those libraries into non-free
+programs.
+</p>
+<pre>
+  When a program is linked with a library, whether statically or using
+</pre>
+<p>
+a shared library, the combination of the two is legally speaking a combined
+work, a derivative of the original library. The ordinary General Public
+License therefore permits such linking only if the entire combination fits
+its criteria of freedom. The Lesser General Public License permits more lax
+criteria for linking other code with the library.
+</p>
+<pre>
+  We call this license the &quot;Lesser&quot; General Public License because it
+</pre>
+<p>
+does Less to protect the user&#8217;s freedom than the ordinary General
+Public License. It also provides other free software developers Less of an
+advantage over competing non-free programs. These disadvantages are the
+reason we use the ordinary General Public License for many libraries.
+However, the Lesser license provides advantages in certain special
+circumstances.
+</p>
+<pre>
+  For example, on rare occasions, there may be a special need to
+</pre>
+<p>
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be allowed to
+use the library. A more frequent case is that a free library does the same
+job as widely used non-free libraries. In this case, there is little to
+gain by limiting the free library to free software only, so we use the
+Lesser General Public License.
+</p>
+<pre>
+  In other cases, permission to use a particular library in non-free
+</pre>
+<p>
+programs enables a greater number of people to use a large body of free
+software. For example, permission to use the GNU C Library in non-free
+programs enables many more people to use the whole GNU operating system, as
+well as its variant, the GNU/Linux operating system.
+</p>
+<pre>
+  Although the Lesser General Public License is Less protective of the
+</pre>
+<p>
+users&#8217; freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run that
+program using a modified version of the Library.
+</p>
+<pre>
+  The precise terms and conditions for copying, distribution and
+</pre>
+<p>
+modification follow. Pay close attention to the difference between a
+&quot;work based on the library&quot; and a &quot;work that uses the
+library&quot;. The former contains code derived from the library, whereas
+the latter must be combined with the library in order to run.
+</p>
+<pre>
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+</pre>
+<p>
+program which contains a notice placed by the copyright holder or other
+authorized party saying it may be distributed under the terms of this
+Lesser General Public License (also called &quot;this License&quot;). Each
+licensee is addressed as &quot;you&quot;.
+</p>
+<pre>
+  A &quot;library&quot; means a collection of software functions and/or data
+</pre>
+<p>
+prepared so as to be conveniently linked with application programs (which
+use some of those functions and data) to form executables.
+</p>
+<pre>
+  The &quot;Library&quot;, below, refers to any such software library or work
+</pre>
+<p>
+which has been distributed under these terms. A &quot;work based on the
+Library&quot; means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a portion
+of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term &quot;modification&quot;.)
+</p>
+<pre>
+  &quot;Source code&quot; for a work means the preferred form of the work for
+</pre>
+<p>
+making modifications to it. For a library, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and
+installation of the library.
+</p>
+<pre>
+  Activities other than copying, distribution and modification are not
+</pre>
+<p>
+covered by this License; they are outside its scope. The act of running a
+program using the Library is not restricted, and output from such a program
+is covered only if its contents constitute a work based on the Library
+(independent of the use of the Library in a tool for writing it). Whether
+that is true depends on what the Library does and what the program that
+uses the Library does.
+</p>
+<pre>
+  1. You may copy and distribute verbatim copies of the Library's
+</pre>
+<p>
+complete source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the notices
+that refer to this License and to the absence of any warranty; and
+distribute a copy of this License along with the Library.
+</p>
+<pre>
+  You may charge a fee for the physical act of transferring a copy,
+</pre>
+<p>
+and you may at your option offer warranty protection in exchange for a fee.
+</p>
+<pre>
+  2. You may modify your copy or copies of the Library or any portion
+</pre>
+<p>
+of it, thus forming a work based on the Library, and copy and distribute
+such modifications or work under the terms of Section 1 above, provided
+that you also meet all of these conditions:
+</p>
+<pre>
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+</pre>
+<p>
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be
+reasonably considered independent and separate works in themselves, then
+this License, and its terms, do not apply to those sections when you
+distribute them as separate works. But when you distribute the same
+sections as part of a whole which is a work based on the Library, the
+distribution of the whole must be on the terms of this License, whose
+permissions for other licensees extend to the entire whole, and thus to
+each and every part regardless of who wrote it.
+</p>
+<p>
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise
+the right to control the distribution of derivative or collective works
+based on the Library.
+</p>
+<p>
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage
+or distribution medium does not bring the other work under the scope of
+this License.
+</p>
+<pre>
+  3. You may opt to apply the terms of the ordinary GNU General Public
+</pre>
+<p>
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they
+refer to the ordinary GNU General Public License, version 2, instead of to
+this License. (If a newer version than version 2 of the ordinary GNU
+General Public License has appeared, then you can specify that version
+instead if you wish.) Do not make any other change in these notices.
+</p>
+<pre>
+  Once this change is made in a given copy, it is irreversible for
+</pre>
+<p>
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+</p>
+<pre>
+  This option is useful when you wish to copy part of the code of
+</pre>
+<p>
+the Library into a program that is not a library.
+</p>
+<pre>
+  4. You may copy and distribute the Library (or a portion or
+</pre>
+<p>
+derivative of it, under Section 2) in object code or executable form under
+the terms of Sections 1 and 2 above provided that you accompany it with the
+complete corresponding machine-readable source code, which must be
+distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange.
+</p>
+<pre>
+  If distribution of object code is made by offering access to copy
+</pre>
+<p>
+from a designated place, then offering equivalent access to copy the source
+code from the same place satisfies the requirement to distribute the source
+code, even though third parties are not compelled to copy the source along
+with the object code.
+</p>
+<pre>
+  5. A program that contains no derivative of any portion of the
+</pre>
+<p>
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a &quot;work that uses the Library&quot;. Such a
+work, in isolation, is not a derivative work of the Library, and therefore
+falls outside the scope of this License.
+</p>
+<pre>
+  However, linking a &quot;work that uses the Library&quot; with the Library
+</pre>
+<p>
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a &quot;work that uses the
+library&quot;. The executable is therefore covered by this License. Section
+6 states terms for distribution of such executables.
+</p>
+<pre>
+  When a &quot;work that uses the Library&quot; uses material from a header file
+</pre>
+<p>
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not. Whether
+this is true is especially significant if the work can be linked without
+the Library, or if the work is itself a library. The threshold for this to
+be true is not precisely defined by law.
+</p>
+<pre>
+  If such an object file uses only numerical parameters, data
+</pre>
+<p>
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object file is
+unrestricted, regardless of whether it is legally a derivative work.
+(Executables containing this object code plus portions of the Library will
+still fall under Section 6.)
+</p>
+<pre>
+  Otherwise, if the work is a derivative of the Library, you may
+</pre>
+<p>
+distribute the object code for the work under the terms of Section 6. Any
+executables containing that work also fall under Section 6, whether or not
+they are linked directly with the Library itself.
+</p>
+<pre>
+  6. As an exception to the Sections above, you may also combine or
+</pre>
+<p>
+link a &quot;work that uses the Library&quot; with the Library to produce a
+work containing portions of the Library, and distribute that work under
+terms of your choice, provided that the terms permit modification of the
+work for the customer&#8217;s own use and reverse engineering for debugging
+such modifications.
+</p>
+<pre>
+  You must give prominent notice with each copy of the work that the
+</pre>
+<p>
+Library is used in it and that the Library and its use are covered by this
+License. You must supply a copy of this License. If the work during
+execution displays copyright notices, you must include the copyright notice
+for the Library among them, as well as a reference directing the user to
+the copy of this License. Also, you must do one of these things:
+</p>
+<pre>
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable &quot;work that
+    uses the Library&quot;, as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the &quot;work that uses the
+</pre>
+<p>
+Library&quot; must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception, the
+materials to be distributed need not include anything that is normally
+distributed (in either source or binary form) with the major components
+(compiler, kernel, and so on) of the operating system on which the
+executable runs, unless that component itself accompanies the executable.
+</p>
+<pre>
+  It may happen that this requirement contradicts the license
+</pre>
+<p>
+restrictions of other proprietary libraries that do not normally accompany
+the operating system. Such a contradiction means you cannot use both them
+and the Library together in an executable that you distribute.
+</p>
+<pre>
+  7. You may place library facilities that are a work based on the
+</pre>
+<p>
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on the
+Library and of the other library facilities is otherwise permitted, and
+provided that you do these two things:
+</p>
+<pre>
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+</pre>
+<p>
+the Library except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense, link with, or distribute the Library
+is void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+</p>
+<pre>
+  9. You are not required to accept this License, since you have not
+</pre>
+<p>
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the Library),
+you indicate your acceptance of this License to do so, and all its terms
+and conditions for copying, distributing or modifying the Library or works
+based on it.
+</p>
+<pre>
+  10. Each time you redistribute the Library (or any work based on the
+</pre>
+<p>
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to
+these terms and conditions. You may not impose any further restrictions on
+the recipients&#8217; exercise of the rights granted herein. You are not
+responsible for enforcing compliance by third parties with this License.
+</p>
+<pre>
+  11. If, as a consequence of a court judgment or allegation of patent
+</pre>
+<p>
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot distribute so
+as to satisfy simultaneously your obligations under this License and any
+other pertinent obligations, then as a consequence you may not distribute
+the Library at all. For example, if a patent license would not permit
+royalty-free redistribution of the Library by all those who receive copies
+directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of
+the Library.
+</p>
+<p>
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+</p>
+<p>
+It is not the purpose of this section to induce you to infringe any patents
+or other property right claims or to contest validity of any such claims;
+this section has the sole purpose of protecting the integrity of the free
+software distribution system which is implemented by public license
+practices. Many people have made generous contributions to the wide range
+of software distributed through that system in reliance on consistent
+application of that system; it is up to the author/donor to decide if he or
+she is willing to distribute software through any other system and a
+licensee cannot impose that choice.
+</p>
+<p>
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+</p>
+<pre>
+  12. If the distribution and/or use of the Library is restricted in
+</pre>
+<p>
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+</p>
+<pre>
+  13. The Free Software Foundation may publish revised and/or new
+</pre>
+<p>
+versions of the Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may differ
+in detail to address new problems or concerns.
+</p>
+<p>
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+&quot;any later version&quot;, you have the option of following the terms
+and conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a license
+version number, you may choose any version ever published by the Free
+Software Foundation.
+</p>
+<pre>
+  14. If you wish to incorporate parts of the Library into other free
+</pre>
+<p>
+programs whose distribution conditions are incompatible with these, write
+to the author to ask for permission. For software which is copyrighted by
+the Free Software Foundation, write to the Free Software Foundation; we
+sometimes make exceptions for this. Our decision will be guided by the two
+goals of preserving the free status of all derivatives of our free software
+and of promoting the sharing and reuse of software generally.
+</p>
+<pre>
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+</pre>
+<p>
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE
+LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+</p>
+<pre>
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+</pre>
+<p>
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER
+SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+</p>
+<pre>
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+</pre>
+<p>
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+</p>
+<pre>
+  To apply these terms, attach the following notices to the library.  It is
+</pre>
+<p>
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+&quot;copyright&quot; line and a pointer to where the full notice is found.
+</p>
+<pre>
+    &lt;one line to give the library's name and a brief idea of what it does.&gt;
+    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+</pre>
+<p>
+Also add information on how to contact you by electronic and paper mail.
+</p>
+<p>
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a &quot;copyright disclaimer&quot; for the library,
+if necessary. Here is a sample; alter the names:
+</p>
+<pre>
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  &lt;signature of Ty Coon&gt;, 1 April 1990
+  Ty Coon, President of Vice
+</pre>
+<p>
+That&#8217;s all there is to it!
+</p>
+
+    </div>
+
+
+   </div>
+
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/files/LICENSE.html b/doc/rdoc/files/LICENSE.html
new file mode 100644
index 0000000..b44feb5
--- /dev/null
+++ b/doc/rdoc/files/LICENSE.html
@@ -0,0 +1,756 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>File: LICENSE</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+  <div id="fileHeader">
+    <h1>LICENSE</h1>
+    <table class="header-table">
+    <tr class="top-aligned-row">
+      <td><strong>Path:</strong></td>
+      <td>LICENSE
+      </td>
+    </tr>
+    <tr class="top-aligned-row">
+      <td><strong>Last Update:</strong></td>
+      <td>Mon Jan 16 11:34:01 EST 2006</td>
+    </tr>
+    </table>
+  </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <pre>
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+</pre>
+<p>
+[This is the first released version of the Lesser GPL. It also counts
+</p>
+<pre>
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+</pre>
+<p>
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change free
+software&#8212;to make sure the software is free for all its users.
+</p>
+<pre>
+  This license, the Lesser General Public License, applies to some
+</pre>
+<p>
+specially designated software packages&#8212;typically libraries&#8212;of
+the Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether this
+license or the ordinary General Public License is the better strategy to
+use in any particular case, based on the explanations below.
+</p>
+<pre>
+  When we speak of free software, we are referring to freedom of use,
+</pre>
+<p>
+not price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for this
+service if you wish); that you receive source code or can get it if you
+want it; that you can change the software and use pieces of it in new free
+programs; and that you are informed that you can do these things.
+</p>
+<pre>
+  To protect your rights, we need to make restrictions that forbid
+</pre>
+<p>
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for you if
+you distribute copies of the library or if you modify it.
+</p>
+<pre>
+  For example, if you distribute copies of the library, whether gratis
+</pre>
+<p>
+or for a fee, you must give the recipients all the rights that we gave you.
+You must make sure that they, too, receive or can get the source code. If
+you link other code with the library, you must provide complete object
+files to the recipients, so that they can relink them with the library
+after making changes to the library and recompiling it. And you must show
+them these terms so they know their rights.
+</p>
+<pre>
+  We protect your rights with a two-step method: (1) we copyright the
+</pre>
+<p>
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+</p>
+<pre>
+  To protect each distributor, we want to make it very clear that
+</pre>
+<p>
+there is no warranty for the free library. Also, if the library is modified
+by someone else and passed on, the recipients should know that what they
+have is not the original version, so that the original author&#8217;s
+reputation will not be affected by problems that might be introduced by
+others.
+</p>
+<pre>
+  Finally, software patents pose a constant threat to the existence of
+</pre>
+<p>
+any free program. We wish to make sure that a company cannot effectively
+restrict the users of a free program by obtaining a restrictive license
+from a patent holder. Therefore, we insist that any patent license obtained
+for a version of the library must be consistent with the full freedom of
+use specified in this license.
+</p>
+<pre>
+  Most GNU software, including some libraries, is covered by the
+</pre>
+<p>
+ordinary GNU General Public License. This license, the GNU Lesser General
+Public License, applies to certain designated libraries, and is quite
+different from the ordinary General Public License. We use this license for
+certain libraries in order to permit linking those libraries into non-free
+programs.
+</p>
+<pre>
+  When a program is linked with a library, whether statically or using
+</pre>
+<p>
+a shared library, the combination of the two is legally speaking a combined
+work, a derivative of the original library. The ordinary General Public
+License therefore permits such linking only if the entire combination fits
+its criteria of freedom. The Lesser General Public License permits more lax
+criteria for linking other code with the library.
+</p>
+<pre>
+  We call this license the &quot;Lesser&quot; General Public License because it
+</pre>
+<p>
+does Less to protect the user&#8217;s freedom than the ordinary General
+Public License. It also provides other free software developers Less of an
+advantage over competing non-free programs. These disadvantages are the
+reason we use the ordinary General Public License for many libraries.
+However, the Lesser license provides advantages in certain special
+circumstances.
+</p>
+<pre>
+  For example, on rare occasions, there may be a special need to
+</pre>
+<p>
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be allowed to
+use the library. A more frequent case is that a free library does the same
+job as widely used non-free libraries. In this case, there is little to
+gain by limiting the free library to free software only, so we use the
+Lesser General Public License.
+</p>
+<pre>
+  In other cases, permission to use a particular library in non-free
+</pre>
+<p>
+programs enables a greater number of people to use a large body of free
+software. For example, permission to use the GNU C Library in non-free
+programs enables many more people to use the whole GNU operating system, as
+well as its variant, the GNU/Linux operating system.
+</p>
+<pre>
+  Although the Lesser General Public License is Less protective of the
+</pre>
+<p>
+users&#8217; freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run that
+program using a modified version of the Library.
+</p>
+<pre>
+  The precise terms and conditions for copying, distribution and
+</pre>
+<p>
+modification follow. Pay close attention to the difference between a
+&quot;work based on the library&quot; and a &quot;work that uses the
+library&quot;. The former contains code derived from the library, whereas
+the latter must be combined with the library in order to run.
+</p>
+<pre>
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+</pre>
+<p>
+program which contains a notice placed by the copyright holder or other
+authorized party saying it may be distributed under the terms of this
+Lesser General Public License (also called &quot;this License&quot;). Each
+licensee is addressed as &quot;you&quot;.
+</p>
+<pre>
+  A &quot;library&quot; means a collection of software functions and/or data
+</pre>
+<p>
+prepared so as to be conveniently linked with application programs (which
+use some of those functions and data) to form executables.
+</p>
+<pre>
+  The &quot;Library&quot;, below, refers to any such software library or work
+</pre>
+<p>
+which has been distributed under these terms. A &quot;work based on the
+Library&quot; means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a portion
+of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term &quot;modification&quot;.)
+</p>
+<pre>
+  &quot;Source code&quot; for a work means the preferred form of the work for
+</pre>
+<p>
+making modifications to it. For a library, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and
+installation of the library.
+</p>
+<pre>
+  Activities other than copying, distribution and modification are not
+</pre>
+<p>
+covered by this License; they are outside its scope. The act of running a
+program using the Library is not restricted, and output from such a program
+is covered only if its contents constitute a work based on the Library
+(independent of the use of the Library in a tool for writing it). Whether
+that is true depends on what the Library does and what the program that
+uses the Library does.
+</p>
+<pre>
+  1. You may copy and distribute verbatim copies of the Library's
+</pre>
+<p>
+complete source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the notices
+that refer to this License and to the absence of any warranty; and
+distribute a copy of this License along with the Library.
+</p>
+<pre>
+  You may charge a fee for the physical act of transferring a copy,
+</pre>
+<p>
+and you may at your option offer warranty protection in exchange for a fee.
+</p>
+<pre>
+  2. You may modify your copy or copies of the Library or any portion
+</pre>
+<p>
+of it, thus forming a work based on the Library, and copy and distribute
+such modifications or work under the terms of Section 1 above, provided
+that you also meet all of these conditions:
+</p>
+<pre>
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+</pre>
+<p>
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be
+reasonably considered independent and separate works in themselves, then
+this License, and its terms, do not apply to those sections when you
+distribute them as separate works. But when you distribute the same
+sections as part of a whole which is a work based on the Library, the
+distribution of the whole must be on the terms of this License, whose
+permissions for other licensees extend to the entire whole, and thus to
+each and every part regardless of who wrote it.
+</p>
+<p>
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise
+the right to control the distribution of derivative or collective works
+based on the Library.
+</p>
+<p>
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage
+or distribution medium does not bring the other work under the scope of
+this License.
+</p>
+<pre>
+  3. You may opt to apply the terms of the ordinary GNU General Public
+</pre>
+<p>
+License instead of this License to a given copy of the Library. To do this,
+you must alter all the notices that refer to this License, so that they
+refer to the ordinary GNU General Public License, version 2, instead of to
+this License. (If a newer version than version 2 of the ordinary GNU
+General Public License has appeared, then you can specify that version
+instead if you wish.) Do not make any other change in these notices.
+</p>
+<pre>
+  Once this change is made in a given copy, it is irreversible for
+</pre>
+<p>
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+</p>
+<pre>
+  This option is useful when you wish to copy part of the code of
+</pre>
+<p>
+the Library into a program that is not a library.
+</p>
+<pre>
+  4. You may copy and distribute the Library (or a portion or
+</pre>
+<p>
+derivative of it, under Section 2) in object code or executable form under
+the terms of Sections 1 and 2 above provided that you accompany it with the
+complete corresponding machine-readable source code, which must be
+distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange.
+</p>
+<pre>
+  If distribution of object code is made by offering access to copy
+</pre>
+<p>
+from a designated place, then offering equivalent access to copy the source
+code from the same place satisfies the requirement to distribute the source
+code, even though third parties are not compelled to copy the source along
+with the object code.
+</p>
+<pre>
+  5. A program that contains no derivative of any portion of the
+</pre>
+<p>
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a &quot;work that uses the Library&quot;. Such a
+work, in isolation, is not a derivative work of the Library, and therefore
+falls outside the scope of this License.
+</p>
+<pre>
+  However, linking a &quot;work that uses the Library&quot; with the Library
+</pre>
+<p>
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a &quot;work that uses the
+library&quot;. The executable is therefore covered by this License. Section
+6 states terms for distribution of such executables.
+</p>
+<pre>
+  When a &quot;work that uses the Library&quot; uses material from a header file
+</pre>
+<p>
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not. Whether
+this is true is especially significant if the work can be linked without
+the Library, or if the work is itself a library. The threshold for this to
+be true is not precisely defined by law.
+</p>
+<pre>
+  If such an object file uses only numerical parameters, data
+</pre>
+<p>
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object file is
+unrestricted, regardless of whether it is legally a derivative work.
+(Executables containing this object code plus portions of the Library will
+still fall under Section 6.)
+</p>
+<pre>
+  Otherwise, if the work is a derivative of the Library, you may
+</pre>
+<p>
+distribute the object code for the work under the terms of Section 6. Any
+executables containing that work also fall under Section 6, whether or not
+they are linked directly with the Library itself.
+</p>
+<pre>
+  6. As an exception to the Sections above, you may also combine or
+</pre>
+<p>
+link a &quot;work that uses the Library&quot; with the Library to produce a
+work containing portions of the Library, and distribute that work under
+terms of your choice, provided that the terms permit modification of the
+work for the customer&#8217;s own use and reverse engineering for debugging
+such modifications.
+</p>
+<pre>
+  You must give prominent notice with each copy of the work that the
+</pre>
+<p>
+Library is used in it and that the Library and its use are covered by this
+License. You must supply a copy of this License. If the work during
+execution displays copyright notices, you must include the copyright notice
+for the Library among them, as well as a reference directing the user to
+the copy of this License. Also, you must do one of these things:
+</p>
+<pre>
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable &quot;work that
+    uses the Library&quot;, as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the &quot;work that uses the
+</pre>
+<p>
+Library&quot; must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception, the
+materials to be distributed need not include anything that is normally
+distributed (in either source or binary form) with the major components
+(compiler, kernel, and so on) of the operating system on which the
+executable runs, unless that component itself accompanies the executable.
+</p>
+<pre>
+  It may happen that this requirement contradicts the license
+</pre>
+<p>
+restrictions of other proprietary libraries that do not normally accompany
+the operating system. Such a contradiction means you cannot use both them
+and the Library together in an executable that you distribute.
+</p>
+<pre>
+  7. You may place library facilities that are a work based on the
+</pre>
+<p>
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on the
+Library and of the other library facilities is otherwise permitted, and
+provided that you do these two things:
+</p>
+<pre>
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+</pre>
+<p>
+the Library except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense, link with, or distribute the Library
+is void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+</p>
+<pre>
+  9. You are not required to accept this License, since you have not
+</pre>
+<p>
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the Library),
+you indicate your acceptance of this License to do so, and all its terms
+and conditions for copying, distributing or modifying the Library or works
+based on it.
+</p>
+<pre>
+  10. Each time you redistribute the Library (or any work based on the
+</pre>
+<p>
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to
+these terms and conditions. You may not impose any further restrictions on
+the recipients&#8217; exercise of the rights granted herein. You are not
+responsible for enforcing compliance by third parties with this License.
+</p>
+<pre>
+  11. If, as a consequence of a court judgment or allegation of patent
+</pre>
+<p>
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot distribute so
+as to satisfy simultaneously your obligations under this License and any
+other pertinent obligations, then as a consequence you may not distribute
+the Library at all. For example, if a patent license would not permit
+royalty-free redistribution of the Library by all those who receive copies
+directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of
+the Library.
+</p>
+<p>
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+</p>
+<p>
+It is not the purpose of this section to induce you to infringe any patents
+or other property right claims or to contest validity of any such claims;
+this section has the sole purpose of protecting the integrity of the free
+software distribution system which is implemented by public license
+practices. Many people have made generous contributions to the wide range
+of software distributed through that system in reliance on consistent
+application of that system; it is up to the author/donor to decide if he or
+she is willing to distribute software through any other system and a
+licensee cannot impose that choice.
+</p>
+<p>
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+</p>
+<pre>
+  12. If the distribution and/or use of the Library is restricted in
+</pre>
+<p>
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+</p>
+<pre>
+  13. The Free Software Foundation may publish revised and/or new
+</pre>
+<p>
+versions of the Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may differ
+in detail to address new problems or concerns.
+</p>
+<p>
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+&quot;any later version&quot;, you have the option of following the terms
+and conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a license
+version number, you may choose any version ever published by the Free
+Software Foundation.
+</p>
+<pre>
+  14. If you wish to incorporate parts of the Library into other free
+</pre>
+<p>
+programs whose distribution conditions are incompatible with these, write
+to the author to ask for permission. For software which is copyrighted by
+the Free Software Foundation, write to the Free Software Foundation; we
+sometimes make exceptions for this. Our decision will be guided by the two
+goals of preserving the free status of all derivatives of our free software
+and of promoting the sharing and reuse of software generally.
+</p>
+<pre>
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+</pre>
+<p>
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE
+LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+</p>
+<pre>
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+</pre>
+<p>
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER
+SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+</p>
+<pre>
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+</pre>
+<p>
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+</p>
+<pre>
+  To apply these terms, attach the following notices to the library.  It is
+</pre>
+<p>
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+&quot;copyright&quot; line and a pointer to where the full notice is found.
+</p>
+<pre>
+    &lt;one line to give the library's name and a brief idea of what it does.&gt;
+    Copyright (C) &lt;year&gt;  &lt;name of author&gt;
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+</pre>
+<p>
+Also add information on how to contact you by electronic and paper mail.
+</p>
+<p>
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a &quot;copyright disclaimer&quot; for the library,
+if necessary. Here is a sample; alter the names:
+</p>
+<pre>
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  &lt;signature of Ty Coon&gt;, 1 April 1990
+  Ty Coon, President of Vice
+</pre>
+<p>
+That&#8217;s all there is to it!
+</p>
+
+    </div>
+
+
+   </div>
+
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/files/README.html b/doc/rdoc/files/README.html
new file mode 100644
index 0000000..9a4fb64
--- /dev/null
+++ b/doc/rdoc/files/README.html
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>File: README</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+  <div id="fileHeader">
+    <h1>README</h1>
+    <table class="header-table">
+    <tr class="top-aligned-row">
+      <td><strong>Path:</strong></td>
+      <td>README
+      </td>
+    </tr>
+    <tr class="top-aligned-row">
+      <td><strong>Last Update:</strong></td>
+      <td>Thu Jan 26 01:27:16 EST 2006</td>
+    </tr>
+    </table>
+  </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+    <div id="description">
+      <h2><a href="../classes/Mongrel.html">Mongrel</a>: Simple Fast Mostly Ruby Web Server</h2>
+<p>
+<a href="../classes/Mongrel.html">Mongrel</a> is a small library that
+provides a very fast HTTP 1.1 server for Ruby web applications. It is not
+particular to any framework, and is intended to be just enough to get a web
+application running behind a more complete and robust web server.
+</p>
+<p>
+What makes <a href="../classes/Mongrel.html">Mongrel</a> so fast is the
+careful use of a C extension to provide fast HTTP 1.1 protocol parsing and
+fast URI lookup. This combination makes the server very fast without too
+many portability issues.
+</p>
+<h2>Status</h2>
+<p>
+<a href="../classes/Mongrel.html">Mongrel</a> is still very ALPHA work, but
+you can see how it&#8217;s used with the Camping framework (version 1.2)
+and take a look at how you might use it. Right now it handles HTTP requests
+well and process the responses fast, but you have to &quot;roll your
+own&quot; response code.
+</p>
+<p>
+The next release of <a href="../classes/Mongrel.html">Mongrel</a> will have
+improved IO handling, much more stability, and should have a better <a
+href="../classes/Mongrel/HttpResponse.html">Mongrel::HttpResponse</a>
+object with more useful features.
+</p>
+<h2>Install</h2>
+<p>
+You can install it via source from <a
+href="http://www.zedshaw.com/downloads/mongrel">www.zedshaw.com/downloads/mongrel</a>/
+or you can gram a RubyGem at <a
+href="http://www.zedshaw.com/downloads/mongrel">www.zedshaw.com/downloads/mongrel</a>/
+and install that manually. I&#8217;m working on setting up a RubyForge
+project.
+</p>
+<p>
+It doesn&#8217;t explicitly require Camping, but if you want to run the
+examples/tepee.rb example then you&#8217;ll need to install Camping 1.2 at
+least (and redcloth I think). These are all available from RubyGems.
+</p>
+<p>
+The library consists of a C extension so you&#8217;ll need a C compiler or
+at least a friend who can build it for you.
+</p>
+<p>
+Finally, the source include a setup.rb for those who hate RubyGems.
+</p>
+<h2>Usage</h2>
+<p>
+Best place to look for usage examples right now is the examples/ directory.
+</p>
+<h2>Speed</h2>
+<p>
+This 0.1.2 release will not be as fast as the 0.1.1 release since
+I&#8217;ve temporarily removed threads as a test. There were many stability
+issues related to handling each request in a thread, especially on OSX.
+I&#8217;ve taken them out for now to make things stable. Even with this
+removed <a href="../classes/Mongrel.html">Mongrel</a> is still pretty fast
+compared to WEBrick.
+</p>
+<h2>Contact</h2>
+<p>
+E-mail zedshaw at zedshaw.com and I&#8217;ll help. Comments about the API
+are welcome.
+</p>
+
+    </div>
+
+
+   </div>
+
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/files/ext/http11/http11_c.html b/doc/rdoc/files/ext/http11/http11_c.html
new file mode 100644
index 0000000..b46289f
--- /dev/null
+++ b/doc/rdoc/files/ext/http11/http11_c.html
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>File: http11.c</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+  <div id="fileHeader">
+    <h1>http11.c</h1>
+    <table class="header-table">
+    <tr class="top-aligned-row">
+      <td><strong>Path:</strong></td>
+      <td>ext/http11/http11.c
+      </td>
+    </tr>
+    <tr class="top-aligned-row">
+      <td><strong>Last Update:</strong></td>
+      <td>Thu Jan 26 00:41:25 EST 2006</td>
+    </tr>
+    </table>
+  </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+
+
+   </div>
+
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/files/lib/mongrel_rb.html b/doc/rdoc/files/lib/mongrel_rb.html
new file mode 100644
index 0000000..2c7ccb0
--- /dev/null
+++ b/doc/rdoc/files/lib/mongrel_rb.html
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>File: mongrel.rb</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+
+
+
+  <div id="fileHeader">
+    <h1>mongrel.rb</h1>
+    <table class="header-table">
+    <tr class="top-aligned-row">
+      <td><strong>Path:</strong></td>
+      <td>lib/mongrel.rb
+      </td>
+    </tr>
+    <tr class="top-aligned-row">
+      <td><strong>Last Update:</strong></td>
+      <td>Thu Jan 26 01:10:22 EST 2006</td>
+    </tr>
+    </table>
+  </div>
+  <!-- banner header -->
+
+  <div id="bodyContent">
+
+
+
+  <div id="contextContent">
+
+
+    <div id="requires-list">
+      <h3 class="section-bar">Required files</h3>
+
+      <div class="name-list">
+      socket&nbsp;&nbsp;
+      http11&nbsp;&nbsp;
+      thread&nbsp;&nbsp;
+      </div>
+    </div>
+
+   </div>
+
+
+  </div>
+
+
+    <!-- if includes -->
+
+    <div id="section">
+
+
+
+
+
+      
+
+
+    <!-- if method_list -->
+
+
+  </div>
+
+
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/fr_class_index.html b/doc/rdoc/fr_class_index.html
new file mode 100644
index 0000000..ba4bb59
--- /dev/null
+++ b/doc/rdoc/fr_class_index.html
@@ -0,0 +1,34 @@
+
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<!--
+
+    Classes
+
+  -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Classes</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
+  <base target="docwin" />
+</head>
+<body>
+<div id="index">
+  <h1 class="section-bar">Classes</h1>
+  <div id="index-entries">
+    <a href="classes/Mongrel.html">Mongrel</a><br />
+    <a href="classes/Mongrel/Error404Handler.html">Mongrel::Error404Handler</a><br />
+    <a href="classes/Mongrel/HttpHandler.html">Mongrel::HttpHandler</a><br />
+    <a href="classes/Mongrel/HttpParser.html">Mongrel::HttpParser</a><br />
+    <a href="classes/Mongrel/HttpRequest.html">Mongrel::HttpRequest</a><br />
+    <a href="classes/Mongrel/HttpResponse.html">Mongrel::HttpResponse</a><br />
+    <a href="classes/Mongrel/HttpServer.html">Mongrel::HttpServer</a><br />
+    <a href="classes/Mongrel/URIClassifier.html">Mongrel::URIClassifier</a><br />
+  </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/fr_file_index.html b/doc/rdoc/fr_file_index.html
new file mode 100644
index 0000000..83d0cd2
--- /dev/null
+++ b/doc/rdoc/fr_file_index.html
@@ -0,0 +1,31 @@
+
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<!--
+
+    Files
+
+  -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Files</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
+  <base target="docwin" />
+</head>
+<body>
+<div id="index">
+  <h1 class="section-bar">Files</h1>
+  <div id="index-entries">
+    <a href="files/COPYING.html">COPYING</a><br />
+    <a href="files/LICENSE.html">LICENSE</a><br />
+    <a href="files/README.html">README</a><br />
+    <a href="files/ext/http11/http11_c.html">ext/http11/http11.c</a><br />
+    <a href="files/lib/mongrel_rb.html">lib/mongrel.rb</a><br />
+  </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/fr_method_index.html b/doc/rdoc/fr_method_index.html
new file mode 100644
index 0000000..c11dc96
--- /dev/null
+++ b/doc/rdoc/fr_method_index.html
@@ -0,0 +1,47 @@
+
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<!--
+
+    Methods
+
+  -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Methods</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
+  <base target="docwin" />
+</head>
+<body>
+<div id="index">
+  <h1 class="section-bar">Methods</h1>
+  <div id="index-entries">
+    <a href="classes/Mongrel/HttpParser.html#M000005">error? (Mongrel::HttpParser)</a><br />
+    <a href="classes/Mongrel/HttpParser.html#M000004">execute (Mongrel::HttpParser)</a><br />
+    <a href="classes/Mongrel/HttpParser.html#M000003">finish (Mongrel::HttpParser)</a><br />
+    <a href="classes/Mongrel/HttpParser.html#M000006">finished? (Mongrel::HttpParser)</a><br />
+    <a href="classes/Mongrel/HttpParser.html#M000001">new (Mongrel::HttpParser)</a><br />
+    <a href="classes/Mongrel/Error404Handler.html#M000019">new (Mongrel::Error404Handler)</a><br />
+    <a href="classes/Mongrel/HttpResponse.html#M000018">new (Mongrel::HttpResponse)</a><br />
+    <a href="classes/Mongrel/HttpServer.html#M000008">new (Mongrel::HttpServer)</a><br />
+    <a href="classes/Mongrel/URIClassifier.html#M000013">new (Mongrel::URIClassifier)</a><br />
+    <a href="classes/Mongrel/HttpRequest.html#M000021">new (Mongrel::HttpRequest)</a><br />
+    <a href="classes/Mongrel/HttpParser.html#M000007">nread (Mongrel::HttpParser)</a><br />
+    <a href="classes/Mongrel/Error404Handler.html#M000020">process (Mongrel::Error404Handler)</a><br />
+    <a href="classes/Mongrel/HttpHandler.html#M000017">process (Mongrel::HttpHandler)</a><br />
+    <a href="classes/Mongrel/HttpServer.html#M000009">process_client (Mongrel::HttpServer)</a><br />
+    <a href="classes/Mongrel/URIClassifier.html#M000014">register (Mongrel::URIClassifier)</a><br />
+    <a href="classes/Mongrel/HttpServer.html#M000011">register (Mongrel::HttpServer)</a><br />
+    <a href="classes/Mongrel/HttpParser.html#M000002">reset (Mongrel::HttpParser)</a><br />
+    <a href="classes/Mongrel/URIClassifier.html#M000016">resolve (Mongrel::URIClassifier)</a><br />
+    <a href="classes/Mongrel/HttpServer.html#M000010">run (Mongrel::HttpServer)</a><br />
+    <a href="classes/Mongrel/HttpServer.html#M000012">unregister (Mongrel::HttpServer)</a><br />
+    <a href="classes/Mongrel/URIClassifier.html#M000015">unregister (Mongrel::URIClassifier)</a><br />
+  </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/index.html b/doc/rdoc/index.html
new file mode 100644
index 0000000..fa5d583
--- /dev/null
+++ b/doc/rdoc/index.html
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+
+<!--
+
+    RDoc Documentation
+
+  -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RDoc Documentation</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+</head>
+<frameset rows="20%, 80%">
+    <frameset cols="25%,35%,45%">
+        <frame src="fr_file_index.html"   title="Files" name="Files" />
+        <frame src="fr_class_index.html"  name="Classes" />
+        <frame src="fr_method_index.html" name="Methods" />
+    </frameset>
+    <frame src="files/README.html" name="docwin" />
+</frameset>
+</html> \ No newline at end of file
diff --git a/doc/rdoc/rdoc-style.css b/doc/rdoc/rdoc-style.css
new file mode 100644
index 0000000..44c7b3d
--- /dev/null
+++ b/doc/rdoc/rdoc-style.css
@@ -0,0 +1,208 @@
+
+body {
+    font-family: Verdana,Arial,Helvetica,sans-serif;
+    font-size:   90%;
+    margin: 0;
+    margin-left: 40px;
+    padding: 0;
+    background: white;
+}
+
+h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
+h1 { font-size: 150%; }
+h2,h3,h4 { margin-top: 1em; }
+
+a { background: #eef; color: #039; text-decoration: none; }
+a:hover { background: #039; color: #eef; }
+
+/* Override the base stylesheet's Anchor inside a table cell */
+td > a {
+  background: transparent;
+  color: #039;
+  text-decoration: none;
+}
+
+/* and inside a section title */
+.section-title > a {
+  background: transparent;
+  color: #eee;
+  text-decoration: none;
+}
+
+/* === Structural elements =================================== */
+
+div#index {
+    margin: 0;
+    margin-left: -40px;
+    padding: 0;
+    font-size: 90%;
+}
+
+
+div#index a {
+    margin-left: 0.7em;
+}
+
+div#index .section-bar {
+   margin-left: 0px;
+   padding-left: 0.7em;
+   background: #ccc;
+   font-size: small;
+}
+
+
+div#classHeader, div#fileHeader {
+    width: auto;
+    color: white;
+    padding: 0.5em 1.5em 0.5em 1.5em;
+    margin: 0;
+    margin-left: -40px;
+    border-bottom: 3px solid #006;
+}
+
+div#classHeader a, div#fileHeader a {
+    background: inherit;
+    color: white;
+}
+
+div#classHeader td, div#fileHeader td {
+    background: inherit;
+    color: white;
+}
+
+
+div#fileHeader {
+    background: #057;
+}
+
+div#classHeader {
+    background: #048;
+}
+
+
+.class-name-in-header {
+  font-size:  180%;
+  font-weight: bold;
+}
+
+
+div#bodyContent {
+    padding: 0 1.5em 0 1.5em;
+}
+
+div#description {
+    padding: 0.5em 1.5em;
+    background: #efefef;
+    border: 1px dotted #999;
+}
+
+div#description h1,h2,h3,h4,h5,h6 {
+    color: #125;;
+    background: transparent;
+}
+
+div#validator-badges {
+    text-align: center;
+}
+div#validator-badges img { border: 0; }
+
+div#copyright {
+    color: #333;
+    background: #efefef;
+    font: 0.75em sans-serif;
+    margin-top: 5em;
+    margin-bottom: 0;
+    padding: 0.5em 2em;
+}
+
+
+/* === Classes =================================== */
+
+table.header-table {
+    color: white;
+    font-size: small;
+}
+
+.type-note {
+    font-size: small;
+    color: #DEDEDE;
+}
+
+.xxsection-bar {
+    background: #eee;
+    color: #333;
+    padding: 3px;
+}
+
+.section-bar {
+   color: #333;
+   border-bottom: 1px solid #999;
+    margin-left: -20px;
+}
+
+
+.section-title {
+    background: #79a;
+    color: #eee;
+    padding: 3px;
+    margin-top: 2em;
+    margin-left: -30px;
+    border: 1px solid #999;
+}
+
+.top-aligned-row {  vertical-align: top }
+.bottom-aligned-row { vertical-align: bottom }
+
+/* --- Context section classes ----------------------- */
+
+.context-row { }
+.context-item-name { font-family: monospace; font-weight: bold; color: black; }
+.context-item-value { font-size: small; color: #448; }
+.context-item-desc { color: #333; padding-left: 2em; }
+
+/* --- Method classes -------------------------- */
+.method-detail {
+    background: #efefef;
+    padding: 0;
+    margin-top: 0.5em;
+    margin-bottom: 1em;
+    border: 1px dotted #ccc;
+}
+.method-heading {
+  color: black;
+  background: #ccc;
+  border-bottom: 1px solid #666;
+  padding: 0.2em 0.5em 0 0.5em;
+}
+.method-signature { color: black; background: inherit; }
+.method-name { font-weight: bold; }
+.method-args { font-style: italic; }
+.method-description { padding: 0 0.5em 0 0.5em; }
+
+/* --- Source code sections -------------------- */
+
+a.source-toggle { font-size: 90%; }
+div.method-source-code {
+    background: #262626;
+    color: #ffdead;
+    margin: 1em;
+    padding: 0.5em;
+    border: 1px dashed #999;
+    overflow: hidden;
+}
+
+div.method-source-code pre { color: #ffdead; overflow: hidden; }
+
+/* --- Ruby keyword styles --------------------- */
+
+.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
+
+.ruby-constant  { color: #7fffd4; background: transparent; }
+.ruby-keyword { color: #00ffff; background: transparent; }
+.ruby-ivar    { color: #eedd82; background: transparent; }
+.ruby-operator  { color: #00ffee; background: transparent; }
+.ruby-identifier { color: #ffdead; background: transparent; }
+.ruby-node    { color: #ffa07a; background: transparent; }
+.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
+.ruby-regexp  { color: #ffa07a; background: transparent; }
+.ruby-value   { color: #7fffd4; background: transparent; } \ No newline at end of file
diff --git a/examples/simpletest.rb b/examples/simpletest.rb
new file mode 100644
index 0000000..c05a745
--- /dev/null
+++ b/examples/simpletest.rb
@@ -0,0 +1,15 @@
+require 'mongrel'
+require 'yaml'
+
+class SimpleHandler < Mongrel::HttpHandler
+    
+    def process(request, response)
+      response.socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nhello!\n")
+    end
+    
+end
+
+h = Mongrel::HttpServer.new("0.0.0.0", "3000")
+h.register("/test", SimpleHandler.new)
+h.run.join
+
diff --git a/examples/tepee.rb b/examples/tepee.rb
new file mode 100644
index 0000000..8b45f88
--- /dev/null
+++ b/examples/tepee.rb
@@ -0,0 +1,178 @@
+#!/usr/bin/ruby
+$:.unshift File.dirname(__FILE__) + "/../../lib"
+%w(rubygems redcloth camping acts_as_versioned).each { |lib| require lib }
+
+Camping.goes :Tepee
+
+module Tepee::Models
+  def self.schema(&block)
+    @@schema = block if block_given?
+    @@schema
+  end
+  
+  class Page < Base
+    PAGE_LINK = /\[\[([^\]|]*)[|]?([^\]]*)\]\]/
+    validates_uniqueness_of :title
+    before_save { |r| r.title = r.title.underscore }
+    acts_as_versioned
+  end
+end
+
+Tepee::Models.schema do
+  create_table :pages, :force => true do |t|
+    t.column :title, :string, :limit => 255
+    t.column :body, :text
+  end
+  Tepee::Models::Page.create_versioned_table
+end
+
+module Tepee::Controllers
+  class Index < R '/'
+    def get
+      redirect Show, 'home_page'
+    end
+  end
+
+  class List < R '/list'
+    def get
+      @pages = Page.find :all, :order => 'title'
+      render :list
+    end
+  end
+
+  class Show < R '/s/(\w+)', '/s/(\w+)/(\d+)'
+    def get page_name, version = nil
+      redirect(Edit, page_name, 1) and return unless @page = Page.find_by_title(page_name)
+      @version = (version.nil? or version == @page.version.to_s) ? @page : @page.versions.find_by_version(version)
+      render :show
+    end
+  end
+
+  class Edit < R '/e/(\w+)/(\d+)', '/e/(\w+)'
+    def get page_name, version = nil
+      @page = Page.find_or_create_by_title(page_name)
+      @page = @page.versions.find_by_version(version) unless version.nil? or version == @page.version.to_s
+      render :edit
+    end
+    
+    def post page_name
+      Page.find_or_create_by_title(page_name).update_attributes :body => input.post_body and redirect Show, page_name
+    end
+  end
+end
+
+module Tepee::Views
+  def layout
+    html do
+      head do
+        title 'test'
+      end
+      body do
+        p do
+          small do
+            span "welcome to " ; a 'tepee', :href => "http://code.whytheluckystiff.net/svn/camping/trunk/examples/tepee/"
+            span '. go ' ;       a 'home',  :href => R(Show, 'home_page')
+            span '. list all ' ; a 'pages', :href => R(List)
+          end
+        end
+        div.content do
+          self << yield
+        end
+      end
+    end
+  end
+
+  def show
+    h1 @page.title
+    div { _markup @version.body }
+    p do
+      a 'edit',    :href => R(Edit, @version.title, @version.version)
+      a 'back',    :href => R(Show, @version.title, @version.version-1) unless @version.version == 1
+      a 'next',    :href => R(Show, @version.title, @version.version+1) unless @version.version == @page.version
+      a 'current', :href => R(Show, @version.title)                     unless @version.version == @page.version
+    end
+  end
+
+  def edit
+    form :method => 'post', :action => R(Edit, @page.title) do
+      p do
+        label 'Body' ; br
+        textarea @page.body, :name => 'post_body', :rows => 50, :cols => 100
+      end
+      
+      p do
+        input :type => 'submit'
+        a 'cancel', :href => R(Show, @page.title, @page.version)
+      end
+    end
+  end
+
+  def list
+    h1 'all pages'
+    ul { @pages.each { |p| li { a p.title, :href => R(Show, p.title) } } }
+  end
+
+  def _markup body
+    return '' if body.blank?
+    body.gsub!(Tepee::Models::Page::PAGE_LINK) do
+      page = title = $1.underscore
+      title = $2 unless $2.empty?
+      if Tepee::Models::Page.find(:all, :select => 'title').collect { |p| p.title }.include?(page)
+        %Q{<a href="#{$docroot}#{R Show, page}">#{title}</a>}
+      else
+        %Q{<span>#{title}<a href="#{$docroot}#{R Edit, page, 1}">?</a></span>}
+      end
+    end
+    RedCloth.new(body, [ :hard_breaks ]).to_html
+  end
+end
+
+
+module Tepee
+  class << self
+    def mongrel_run(request, response)
+      req = StringIO.new(request.body)
+      status = 500
+      
+      resp = ""
+      begin
+        klass, path = Controllers.D request.params["PATH_INFO"]
+        method = request.params['REQUEST_METHOD']||"GET"
+        klass.class_eval { include C; include Controllers::Base; include Models }
+        controller = klass.new
+        resp = controller.service(req, request.params, method, path)
+        status = controller.status
+      rescue => e
+        req.rewind
+        resp = Controllers::ServerError.new.service(req, request.params, "GET", [klass,method,e])
+      end
+      
+      response.socket.write("HTTP/1.1 #{status} OK\r\n")
+      response.socket.write(resp)
+    end
+  end
+end
+
+require 'thread'
+
+class CampingHandler < Mongrel::HttpHandler
+  def process(request, response)
+    Tepee.mongrel_run(request, response)
+  end
+end
+
+if __FILE__ == $0
+  $docroot = "/blog"
+  
+  db_exists = File.exists?('tepee.db')
+  Tepee::Models::Base.establish_connection :adapter => 'sqlite3', :database => 'tepee.db'
+  Tepee::Models::Base.logger = Logger.new('camping.log')
+  Tepee::Models::Base.threaded_connections=false
+  ActiveRecord::Schema.define(&Tepee::Models.schema) unless db_exists
+  
+  h = Mongrel::HttpServer.new("0.0.0.0", "3000")
+  h.register("/blog", CampingHandler.new)
+  h.register("/favicon.ico", Mongrel::Error404Handler.new(""))
+  h.run.join
+  
+end
diff --git a/examples/webrick_compare.rb b/examples/webrick_compare.rb
new file mode 100644
index 0000000..15199b0
--- /dev/null
+++ b/examples/webrick_compare.rb
@@ -0,0 +1,20 @@
+#!/usr/local/bin/ruby
+require 'webrick'
+include WEBrick
+
+s = HTTPServer.new( :Port => 4000 )
+
+# HTTPServer#mount(path, servletclass)
+#   When a request referring "/hello" is received,
+#   the HTTPServer get an instance of servletclass
+#   and then call a method named do_"a HTTP method".
+
+class HelloServlet < HTTPServlet::AbstractServlet
+  def do_GET(req, res)
+    res.body = "hello!"
+    res['Content-Type'] = "text/html"
+  end
+end
+s.mount("/test", HelloServlet)
+
+s.start \ No newline at end of file
diff --git a/ext/http11/MANIFEST b/ext/http11/MANIFEST
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ext/http11/MANIFEST
diff --git a/ext/http11/ext_help.h b/ext/http11/ext_help.h
new file mode 100644
index 0000000..8b4d754
--- /dev/null
+++ b/ext/http11/ext_help.h
@@ -0,0 +1,14 @@
+#ifndef ext_help_h
+#define ext_help_h
+
+#define RAISE_NOT_NULL(T) if(T == NULL) rb_raise(rb_eArgError, "NULL found for " # T " when shouldn't be.");
+#define DATA_GET(from,type,name) Data_Get_Struct(from,type,name); RAISE_NOT_NULL(name);
+#define REQUIRE_TYPE(V, T) if(TYPE(V) != T) rb_raise(rb_eTypeError, "Wrong argument type for " # V " required " # T);
+
+#ifdef DEBUG
+#define TRACE()  fprintf(stderr, "> %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
+#else
+#define TRACE()
+#endif
+
+#endif
diff --git a/ext/http11/extconf.rb b/ext/http11/extconf.rb
new file mode 100644
index 0000000..e4f6918
--- /dev/null
+++ b/ext/http11/extconf.rb
@@ -0,0 +1,6 @@
+require 'mkmf'
+
+dir_config("http11")
+have_library("c", "main")
+
+create_makefile("http11")
diff --git a/ext/http11/http11.c b/ext/http11/http11.c
new file mode 100644
index 0000000..3755d65
--- /dev/null
+++ b/ext/http11/http11.c
@@ -0,0 +1,429 @@
+#include "ruby.h"
+#include "ext_help.h"
+#include <assert.h>
+#include <string.h>
+#include "http11_parser.h"
+#include <ctype.h>
+#include "tst.h"
+
+static VALUE mMongrel;
+static VALUE cHttpParser;
+static VALUE cURIClassifier;
+
+
+void http_field(void *data, const char *field, size_t flen, const char *value, size_t vlen)
+{
+  char *ch, *end;
+  VALUE req = (VALUE)data;
+  VALUE f = rb_str_new2("HTTP_");
+  VALUE v = rb_str_new(value, vlen);
+  
+  rb_str_buf_cat(f, field, flen);
+  
+  for(ch = RSTRING(f)->ptr, end = ch + RSTRING(f)->len; ch < end; ch++) {
+    if(*ch == '-') {
+      *ch = '_';
+    } else {
+      *ch = toupper(*ch);
+    }
+  }
+
+  rb_hash_aset(req, f, v);
+}
+
+void request_method(void *data, const char *at, size_t length)
+{
+  VALUE req = (VALUE)data;
+  VALUE val = rb_str_new(at, length);
+  VALUE id = rb_str_new2("REQUEST_METHOD");
+  rb_hash_aset(req, id, val);
+}
+
+void path_info(void *data, const char *at, size_t length)
+{
+  VALUE req = (VALUE)data;
+  VALUE val = rb_str_new(at, length);
+  VALUE id = rb_str_new2("PATH_INFO");
+  rb_hash_aset(req, id, val);
+}
+
+
+void query_string(void *data, const char *at, size_t length)
+{
+  VALUE req = (VALUE)data;
+  VALUE val = rb_str_new(at, length);
+  VALUE id = rb_str_new2("QUERY_STRING");
+  rb_hash_aset(req, id, val);
+}
+
+void http_version(void *data, const char *at, size_t length)
+{
+  VALUE req = (VALUE)data;
+  VALUE val = rb_str_new(at, length);
+  VALUE id = rb_str_new2("HTTP_VERSION");
+  rb_hash_aset(req, id, val);
+}
+
+
+
+
+
+void HttpParser_free(void *data) {
+    TRACE();
+    
+    if(data) {
+        free(data);
+    }
+}
+
+
+VALUE HttpParser_alloc(VALUE klass)
+{
+    TRACE();
+    VALUE obj;
+    http_parser *hp = calloc(1, sizeof(http_parser));
+    hp->http_field = http_field;
+    hp->request_method = request_method;
+    hp->path_info = path_info;
+    hp->query_string = query_string;
+    hp->http_version = http_version;
+    
+    obj = Data_Wrap_Struct(klass, NULL, HttpParser_free, hp);
+
+    return obj;
+}
+
+
+/**
+ * call-seq:
+ *    parser.new -> parser
+ *
+ * Creates a new parser.
+ */
+VALUE HttpParser_init(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  http_parser_init(http);
+  
+  return self;
+}
+
+
+/**
+ * call-seq:
+ *    parser.reset -> nil
+ *
+ * Resets the parser to it's initial state so that you can reuse it
+ * rather than making new ones.
+ */
+VALUE HttpParser_reset(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  http_parser_init(http);
+  
+  return Qnil;
+}
+
+
+/**
+ * call-seq:
+ *    parser.finish -> true/false
+ *
+ * Finishes a parser early which could put in a "good" or bad state.
+ * You should call reset after finish it or bad things will happen.
+ */
+VALUE HttpParser_finish(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  http_parser_finish(http);
+  
+  return http_parser_is_finished(http) ? Qtrue : Qfalse;
+}
+
+
+/**
+ * call-seq:
+ *    parser.execute(req_hash, data) -> Integer
+ *
+ * Takes a Hash and a String of data, parses the String of data filling in the Hash
+ * returning an Integer to indicate how much of the data has been read.  No matter
+ * what the return value, you should call HttpParser#finished? and HttpParser#error?
+ * to figure out if it's done parsing or there was an error.
+ */
+VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+
+  http->data = (void *)req_hash;
+  http_parser_execute(http, RSTRING(data)->ptr, RSTRING(data)->len);
+  
+  return INT2FIX(http_parser_nread(http));
+}
+
+
+/**
+ * call-seq:
+ *    parser.error? -> true/false
+ *
+ * Tells you whether the parser is in an error state.
+ */
+VALUE HttpParser_has_error(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  
+  return http_parser_has_error(http) ? Qtrue : Qfalse;
+}
+
+
+/**
+ * call-seq:
+ *    parser.finished? -> true/false
+ *
+ * Tells you whether the parser is finished or not and in a good state.
+ */
+VALUE HttpParser_is_finished(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  
+  return http_parser_is_finished(http) ? Qtrue : Qfalse;
+}
+
+
+/**
+ * call-seq:
+ *    parser.nread -> Integer
+ *
+ * Returns the amount of data processed so far during this processing cycle.  It is
+ * set to 0 on initialize or reset calls and is incremented each time execute is called.
+ */
+VALUE HttpParser_nread(VALUE self)
+{
+  http_parser *http = NULL;
+  DATA_GET(self, http_parser, http);
+  
+  return INT2FIX(http->nread);
+}
+
+
+void URIClassifier_free(void *data)
+{
+    TRACE();
+    
+    if(data) {
+      tst_cleanup((struct tst *)data);
+    }
+}
+
+
+#define TRIE_INCREASE 30
+
+VALUE URIClassifier_alloc(VALUE klass)
+{
+    TRACE();
+    VALUE obj;
+    struct tst *tst = tst_init(TRIE_INCREASE);
+    assert(tst && "failed to initialize trie structure");
+
+    obj = Data_Wrap_Struct(klass, NULL, URIClassifier_free, tst);
+
+    return obj;
+}
+
+/**
+ * call-seq:
+ *    URIClassifier.new -> URIClassifier
+ *
+ * Initializes a new URIClassifier object that you can use to associate URI sequences
+ * with objects.  You can actually use it with any string sequence and any objects,
+ * but it's mostly used with URIs.
+ *
+ * It uses TST from http://www.octavian.org/cs/software.html to build an ternary search
+ * trie to hold all of the URIs.  It uses this to do an initial search for the a URI
+ * prefix, and then to break the URI into SCRIPT_NAME and PATH_INFO portions.  It actually
+ * will do two searches most of the time in order to find the right handler for the
+ * registered prefix portion.
+ *
+ * Here's how it all works.  Let's say you register "/blog" with a BlogHandler.  Great.
+ * Now, someone goes to "/blog/zedsucks/ass".  You want SCRIPT_NAME to be "/blog" and
+ * PATH_INFO to be "/zedsucks/ass".  URIClassifier first does a TST search and comes
+ * up with a failure, but knows that the failure ended at the "/blog" part.  So, that's
+ * the SCRIPT_NAME.  It then tries a second search for just "/blog".  If that comes back
+ * good then it sets the rest ("/zedsucks/ass") to the PATH_INFO and returns the BlogHandler.
+ *
+ * The optimal approach would be to not do the search twice, but the TST lib doesn't
+ * really support returning prefixes.  Might not be hard to add later.
+ *
+ * The key though is that it will try to match the *longest* match it can.  If you
+ * also register "/blog/zed" then the above URI will give SCRIPT_NAME="/blog/zed",
+ * PATH_INFO="sucks/ass".  Probably not what you want, so your handler will need to
+ * do the 404 thing.
+ *
+ * Take a look at the postamble of example/tepee.rb to see how this is handled for
+ * Camping.
+ */
+VALUE URIClassifier_init(VALUE self)
+{
+  VALUE hash;
+
+  // we create an internal hash to protect stuff from the GC
+  hash = rb_hash_new();
+  rb_iv_set(self, "handler_map", hash);
+}
+
+
+/**
+ * call-seq:
+ *    uc.register("/someuri", SampleHandler.new) -> nil
+ *
+ * Registers the SampleHandler (one for all requests) with the "/someuri".
+ * When URIClassifier::resolve is called with "/someuri" it'll return
+ * SampleHandler immediately.  When "/someuri/pathhere" is called it'll
+ * find SomeHandler after a second search, and setup PATH_INFO="/pathhere".
+ *
+ * You actually can reuse this class to register nearly anything and
+ * quickly resolve it.  This could be used for caching, fast mapping, etc.
+ * The downside is it uses much more memory than a Hash, but it can be
+ * a lot faster.  It's main advantage is that it works on prefixes, which
+ * is damn hard to get right with a Hash.
+ */
+VALUE URIClassifier_register(VALUE self, VALUE uri, VALUE handler)
+{
+  int rc = 0;
+  void *ptr = NULL;
+  struct tst *tst = NULL;
+  DATA_GET(self, struct tst, tst);
+
+  rc = tst_insert((unsigned char *)StringValueCStr(uri), (void *)handler , tst, 0, &ptr);
+
+  if(rc == TST_DUPLICATE_KEY) {
+    rb_raise(rb_eStandardError, "Handler already registered with that name");
+  } else if(rc == TST_ERROR) {
+    rb_raise(rb_eStandardError, "Memory error registering handler");
+  } else if(rc == TST_NULL_KEY) {
+    rb_raise(rb_eStandardError, "URI was empty");
+  }
+  
+  rb_hash_aset(rb_iv_get(self, "handler_map"), uri, handler);
+
+  return Qnil;
+}
+
+
+/**
+ * call-seq:
+ *    uc.unregister("/someuri")
+ *
+ * Yep, just removes this uri and it's handler from the trie.
+ */
+VALUE URIClassifier_unregister(VALUE self, VALUE uri)
+{
+  void *handler = NULL;
+  struct tst *tst = NULL;
+  DATA_GET(self, struct tst, tst);
+
+  handler = tst_delete((unsigned char *)StringValueCStr(uri), tst);
+
+  if(handler) {
+    rb_hash_delete(rb_iv_get(self, "handler_map"), uri);
+
+    return (VALUE)handler;
+  } else {
+    return Qnil;
+  }
+}
+
+
+/**
+ * call-seq:
+ *    uc.resolve("/someuri") -> "/someuri", "", handler
+ *    uc.resolve("/someuri/pathinfo") -> "/someuri", "/pathinfo", handler
+ *    uc.resolve("/notfound/orhere") -> nil, nil, nil
+ *
+ * Attempts to resolve either the whole URI or at the longest prefix, returning
+ * the prefix (as script_info), path (as path_info), and registered handler
+ * (usually an HttpHandler).
+ *
+ * It expects strings.  Don't try other string-line stuff yet.
+ */
+VALUE URIClassifier_resolve(VALUE self, VALUE uri)
+{
+  void *handler = NULL;
+  int pref_len = 0;
+  struct tst *tst = NULL;
+  VALUE result;
+  VALUE script_name;
+  VALUE path_info;
+  unsigned char *uri_str = NULL;
+  unsigned char *script_name_str = NULL;
+
+  DATA_GET(self, struct tst, tst);
+  uri_str = (unsigned char *)StringValueCStr(uri);
+
+  handler = tst_search(uri_str, tst, &pref_len);
+
+  // setup for multiple return values
+  result = rb_ary_new();
+
+
+  if(handler == NULL) {
+    script_name = rb_str_substr (uri, 0, pref_len);
+    script_name_str = (unsigned char *)StringValueCStr(script_name);
+
+    handler = tst_search(script_name_str, tst, NULL);
+
+    if(handler == NULL) {
+      // didn't find the script name at all
+      rb_ary_push(result, Qnil);
+      rb_ary_push(result, Qnil);
+      rb_ary_push(result, Qnil);
+      return result;
+    } else {
+      // found a handler, setup the path info and we're good
+      path_info = rb_str_substr(uri, pref_len, RSTRING(uri)->len);
+    }
+  } else {
+    // whole thing was found, so uri is the script name, path info empty
+    script_name = uri;
+    path_info = rb_str_new2("");
+  }
+
+  rb_ary_push(result, script_name);
+  rb_ary_push(result, path_info);
+  rb_ary_push(result, (VALUE)handler);
+  return result;
+}
+
+
+
+void Init_http11()
+{
+    
+  TRACE();
+  
+  mMongrel = rb_define_module("Mongrel");
+  
+  cHttpParser = rb_define_class_under(mMongrel, "HttpParser", rb_cObject);
+  rb_define_alloc_func(cHttpParser, HttpParser_alloc);
+  rb_define_method(cHttpParser, "initialize", HttpParser_init,0);
+  rb_define_method(cHttpParser, "reset", HttpParser_reset,0);
+  rb_define_method(cHttpParser, "finish", HttpParser_finish,0);
+  rb_define_method(cHttpParser, "execute", HttpParser_execute,2);
+  rb_define_method(cHttpParser, "error?", HttpParser_has_error,0);
+  rb_define_method(cHttpParser, "finished?", HttpParser_is_finished,0);
+  rb_define_method(cHttpParser, "nread", HttpParser_nread,0);
+
+  cURIClassifier = rb_define_class_under(mMongrel, "URIClassifier", rb_cObject);
+  rb_define_alloc_func(cURIClassifier, URIClassifier_alloc);
+  rb_define_method(cURIClassifier, "initialize", URIClassifier_init, 0);
+  rb_define_method(cURIClassifier, "register", URIClassifier_register, 2);
+  rb_define_method(cURIClassifier, "unregister", URIClassifier_unregister, 1);
+  rb_define_method(cURIClassifier, "resolve", URIClassifier_resolve, 1);
+}
+
+
diff --git a/ext/http11/http11_parser.c b/ext/http11/http11_parser.c
new file mode 100644
index 0000000..c256037
--- /dev/null
+++ b/ext/http11/http11_parser.c
@@ -0,0 +1,918 @@
+#line 1 "ext/http11/http11_parser.rl"
+#include "http11_parser.h"
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define MARK(S,F) assert((F) - (S)->mark >= 0); (S)->mark = (F);
+
+/** machine **/
+#line 100 "ext/http11/http11_parser.rl"
+
+
+/** Data **/
+
+#line 18 "ext/http11/http11_parser.c"
+static int http_parser_start = 0;
+
+static int http_parser_first_final = 56;
+
+static int http_parser_error = 1;
+
+#line 104 "ext/http11/http11_parser.rl"
+
+int http_parser_init(http_parser *parser)  {
+    int cs = 0;
+    
+#line 30 "ext/http11/http11_parser.c"
+        {
+        cs = http_parser_start;
+        }
+#line 108 "ext/http11/http11_parser.rl"
+    parser->cs = cs;
+    parser->body_start = NULL;
+    parser->content_len = 0;
+    parser->mark = NULL;
+    parser->nread = 0;
+
+    return(1);
+}
+
+
+/** exec **/
+size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len)  {
+    const char *p, *pe;
+    int cs = parser->cs;
+
+    p = buffer;
+    pe = buffer+len;
+
+    
+#line 54 "ext/http11/http11_parser.c"
+        {
+        p -= 1;
+        if ( ++p == pe )
+                goto _out;
+        switch ( cs )
+        {
+case 0:
+        switch( (*p) ) {
+                case 68: goto tr13;
+                case 71: goto tr14;
+                case 72: goto tr15;
+                case 79: goto tr16;
+                case 80: goto tr17;
+                case 84: goto tr18;
+        }
+        goto st1;
+st1:
+        goto _out1;
+tr13:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st2;
+st2:
+        if ( ++p == pe )
+                goto _out2;
+case 2:
+#line 81 "ext/http11/http11_parser.c"
+        if ( (*p) == 69 )
+                goto st3;
+        goto st1;
+st3:
+        if ( ++p == pe )
+                goto _out3;
+case 3:
+        if ( (*p) == 76 )
+                goto st4;
+        goto st1;
+st4:
+        if ( ++p == pe )
+                goto _out4;
+case 4:
+        if ( (*p) == 69 )
+                goto st5;
+        goto st1;
+st5:
+        if ( ++p == pe )
+                goto _out5;
+case 5:
+        if ( (*p) == 84 )
+                goto st6;
+        goto st1;
+st6:
+        if ( ++p == pe )
+                goto _out6;
+case 6:
+        if ( (*p) == 69 )
+                goto st7;
+        goto st1;
+st7:
+        if ( ++p == pe )
+                goto _out7;
+case 7:
+        if ( (*p) == 32 )
+                goto tr33;
+        goto st1;
+tr33:
+#line 29 "ext/http11/http11_parser.rl"
+        {
+               if(parser->request_method != NULL)
+                              parser->request_method(parser->data, parser->mark, p - parser->mark);
+        }
+        goto st8;
+st8:
+        if ( ++p == pe )
+                goto _out8;
+case 8:
+#line 131 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 42: goto tr27;
+                case 43: goto tr28;
+                case 47: goto tr29;
+                case 58: goto tr30;
+        }
+        if ( (*p) < 65 ) {
+                if ( 45 <= (*p) && (*p) <= 57 )
+                        goto tr28;
+        } else if ( (*p) > 90 ) {
+                if ( 97 <= (*p) && (*p) <= 122 )
+                        goto tr28;
+        } else
+                goto tr28;
+        goto st1;
+tr27:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st9;
+st9:
+        if ( ++p == pe )
+                goto _out9;
+case 9:
+#line 155 "ext/http11/http11_parser.c"
+        if ( (*p) == 32 )
+                goto tr34;
+        goto st1;
+tr34:
+#line 33 "ext/http11/http11_parser.rl"
+        {
+               if(parser->path_info != NULL)
+                              parser->path_info(parser->data, parser->mark, p - parser->mark);
+        }
+        goto st10;
+tr48:
+#line 37 "ext/http11/http11_parser.rl"
+        {
+               if(parser->query_string != NULL)
+                              parser->query_string(parser->data, parser->mark, p - parser->mark);
+        }
+        goto st10;
+st10:
+        if ( ++p == pe )
+                goto _out10;
+case 10:
+#line 177 "ext/http11/http11_parser.c"
+        if ( (*p) == 72 )
+                goto tr11;
+        goto st1;
+tr11:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st11;
+st11:
+        if ( ++p == pe )
+                goto _out11;
+case 11:
+#line 189 "ext/http11/http11_parser.c"
+        if ( (*p) == 84 )
+                goto st12;
+        goto st1;
+st12:
+        if ( ++p == pe )
+                goto _out12;
+case 12:
+        if ( (*p) == 84 )
+                goto st13;
+        goto st1;
+st13:
+        if ( ++p == pe )
+                goto _out13;
+case 13:
+        if ( (*p) == 80 )
+                goto st14;
+        goto st1;
+st14:
+        if ( ++p == pe )
+                goto _out14;
+case 14:
+        if ( (*p) == 47 )
+                goto st15;
+        goto st1;
+st15:
+        if ( ++p == pe )
+                goto _out15;
+case 15:
+        if ( 48 <= (*p) && (*p) <= 57 )
+                goto st16;
+        goto st1;
+st16:
+        if ( ++p == pe )
+                goto _out16;
+case 16:
+        if ( (*p) == 46 )
+                goto st17;
+        if ( 48 <= (*p) && (*p) <= 57 )
+                goto st16;
+        goto st1;
+st17:
+        if ( ++p == pe )
+                goto _out17;
+case 17:
+        if ( 48 <= (*p) && (*p) <= 57 )
+                goto st18;
+        goto st1;
+st18:
+        if ( ++p == pe )
+                goto _out18;
+case 18:
+        if ( (*p) == 13 )
+                goto tr37;
+        if ( 48 <= (*p) && (*p) <= 57 )
+                goto st18;
+        goto st1;
+tr37:
+#line 42 "ext/http11/http11_parser.rl"
+        {        
+               if(parser->http_version != NULL)
+                              parser->http_version(parser->data, parser->mark, p - parser->mark);
+        }
+        goto st19;
+st19:
+        if ( ++p == pe )
+                goto _out19;
+case 19:
+#line 257 "ext/http11/http11_parser.c"
+        if ( (*p) == 10 )
+                goto st20;
+        goto st1;
+st20:
+        if ( ++p == pe )
+                goto _out20;
+case 20:
+        switch( (*p) ) {
+                case 13: goto st21;
+                case 33: goto tr36;
+                case 124: goto tr36;
+                case 126: goto tr36;
+        }
+        if ( (*p) < 45 ) {
+                if ( (*p) > 39 ) {
+                        if ( 42 <= (*p) && (*p) <= 43 )
+                                goto tr36;
+                } else if ( (*p) >= 35 )
+                        goto tr36;
+        } else if ( (*p) > 46 ) {
+                if ( (*p) < 65 ) {
+                        if ( 48 <= (*p) && (*p) <= 57 )
+                                goto tr36;
+                } else if ( (*p) > 90 ) {
+                        if ( 94 <= (*p) && (*p) <= 122 )
+                                goto tr36;
+                } else
+                        goto tr36;
+        } else
+                goto tr36;
+        goto st1;
+st21:
+        if ( ++p == pe )
+                goto _out21;
+case 21:
+        if ( (*p) == 10 )
+                goto tr40;
+        goto st1;
+tr40:
+#line 46 "ext/http11/http11_parser.rl"
+        {
+               parser->body_start = p+1; goto _out56;
+        }
+        goto st56;
+st56:
+        if ( ++p == pe )
+                goto _out56;
+case 56:
+#line 306 "ext/http11/http11_parser.c"
+        goto st1;
+tr36:
+#line 16 "ext/http11/http11_parser.rl"
+        { parser->field_start = p; }
+        goto st22;
+st22:
+        if ( ++p == pe )
+                goto _out22;
+case 22:
+#line 316 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 33: goto st22;
+                case 58: goto tr32;
+                case 124: goto st22;
+                case 126: goto st22;
+        }
+        if ( (*p) < 45 ) {
+                if ( (*p) > 39 ) {
+                        if ( 42 <= (*p) && (*p) <= 43 )
+                                goto st22;
+                } else if ( (*p) >= 35 )
+                        goto st22;
+        } else if ( (*p) > 46 ) {
+                if ( (*p) < 65 ) {
+                        if ( 48 <= (*p) && (*p) <= 57 )
+                                goto st22;
+                } else if ( (*p) > 90 ) {
+                        if ( 94 <= (*p) && (*p) <= 122 )
+                                goto st22;
+                } else
+                        goto st22;
+        } else
+                goto st22;
+        goto st1;
+tr32:
+#line 17 "ext/http11/http11_parser.rl"
+        {
+               parser->field_len = (p - parser->field_start);
+        }
+        goto st23;
+st23:
+        if ( ++p == pe )
+                goto _out23;
+case 23:
+#line 351 "ext/http11/http11_parser.c"
+        if ( (*p) == 13 )
+                goto tr56;
+        goto tr55;
+tr55:
+#line 21 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st24;
+st24:
+        if ( ++p == pe )
+                goto _out24;
+case 24:
+#line 363 "ext/http11/http11_parser.c"
+        if ( (*p) == 13 )
+                goto tr51;
+        goto st24;
+tr51:
+#line 22 "ext/http11/http11_parser.rl"
+        {
+               if(parser->http_field != NULL) {
+                              parser->http_field(parser->data,
+                                       parser->field_start, parser->field_len,
+                                parser->mark+1, p - (parser->mark +1));
+                }
+        }
+        goto st25;
+tr56:
+#line 21 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+#line 22 "ext/http11/http11_parser.rl"
+        {
+               if(parser->http_field != NULL) {
+                              parser->http_field(parser->data,
+                                       parser->field_start, parser->field_len,
+                                parser->mark+1, p - (parser->mark +1));
+                }
+        }
+        goto st25;
+st25:
+        if ( ++p == pe )
+                goto _out25;
+case 25:
+#line 393 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 10: goto st26;
+                case 13: goto tr51;
+        }
+        goto st24;
+st26:
+        if ( ++p == pe )
+                goto _out26;
+case 26:
+        switch( (*p) ) {
+                case 13: goto st21;
+                case 33: goto tr42;
+                case 124: goto tr42;
+                case 126: goto tr42;
+        }
+        if ( (*p) < 45 ) {
+                if ( (*p) > 39 ) {
+                        if ( 42 <= (*p) && (*p) <= 43 )
+                                goto tr42;
+                } else if ( (*p) >= 35 )
+                        goto tr42;
+        } else if ( (*p) > 46 ) {
+                if ( (*p) < 65 ) {
+                        if ( 48 <= (*p) && (*p) <= 57 )
+                                goto tr42;
+                } else if ( (*p) > 90 ) {
+                        if ( 94 <= (*p) && (*p) <= 122 )
+                                goto tr42;
+                } else
+                        goto tr42;
+        } else
+                goto tr42;
+        goto st24;
+tr42:
+#line 16 "ext/http11/http11_parser.rl"
+        { parser->field_start = p; }
+        goto st27;
+st27:
+        if ( ++p == pe )
+                goto _out27;
+case 27:
+#line 435 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 13: goto tr51;
+                case 33: goto st27;
+                case 58: goto tr32;
+                case 124: goto st27;
+                case 126: goto st27;
+        }
+        if ( (*p) < 45 ) {
+                if ( (*p) > 39 ) {
+                        if ( 42 <= (*p) && (*p) <= 43 )
+                                goto st27;
+                } else if ( (*p) >= 35 )
+                        goto st27;
+        } else if ( (*p) > 46 ) {
+                if ( (*p) < 65 ) {
+                        if ( 48 <= (*p) && (*p) <= 57 )
+                                goto st27;
+                } else if ( (*p) > 90 ) {
+                        if ( 94 <= (*p) && (*p) <= 122 )
+                                goto st27;
+                } else
+                        goto st27;
+        } else
+                goto st27;
+        goto st24;
+tr28:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st28;
+st28:
+        if ( ++p == pe )
+                goto _out28;
+case 28:
+#line 469 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 43: goto st28;
+                case 58: goto st29;
+        }
+        if ( (*p) < 48 ) {
+                if ( 45 <= (*p) && (*p) <= 46 )
+                        goto st28;
+        } else if ( (*p) > 57 ) {
+                if ( (*p) > 90 ) {
+                        if ( 97 <= (*p) && (*p) <= 122 )
+                                goto st28;
+                } else if ( (*p) >= 65 )
+                        goto st28;
+        } else
+                goto st28;
+        goto st1;
+tr30:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st29;
+st29:
+        if ( ++p == pe )
+                goto _out29;
+case 29:
+#line 494 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 32: goto tr34;
+                case 37: goto st30;
+                case 60: goto st1;
+                case 62: goto st1;
+                case 127: goto st1;
+        }
+        if ( (*p) > 31 ) {
+                if ( 34 <= (*p) && (*p) <= 35 )
+                        goto st1;
+        } else if ( (*p) >= 0 )
+                goto st1;
+        goto st29;
+st30:
+        if ( ++p == pe )
+                goto _out30;
+case 30:
+        if ( (*p) < 65 ) {
+                if ( 48 <= (*p) && (*p) <= 57 )
+                        goto st31;
+        } else if ( (*p) > 70 ) {
+                if ( 97 <= (*p) && (*p) <= 102 )
+                        goto st31;
+        } else
+                goto st31;
+        goto st1;
+st31:
+        if ( ++p == pe )
+                goto _out31;
+case 31:
+        if ( (*p) < 65 ) {
+                if ( 48 <= (*p) && (*p) <= 57 )
+                        goto st29;
+        } else if ( (*p) > 70 ) {
+                if ( 97 <= (*p) && (*p) <= 102 )
+                        goto st29;
+        } else
+                goto st29;
+        goto st1;
+tr29:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st32;
+st32:
+        if ( ++p == pe )
+                goto _out32;
+case 32:
+#line 542 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 32: goto tr34;
+                case 37: goto st34;
+                case 47: goto st1;
+                case 60: goto st1;
+                case 62: goto st1;
+                case 63: goto tr46;
+                case 127: goto st1;
+        }
+        if ( (*p) > 31 ) {
+                if ( 34 <= (*p) && (*p) <= 35 )
+                        goto st1;
+        } else if ( (*p) >= 0 )
+                goto st1;
+        goto st33;
+st33:
+        if ( ++p == pe )
+                goto _out33;
+case 33:
+        switch( (*p) ) {
+                case 32: goto tr34;
+                case 37: goto st34;
+                case 60: goto st1;
+                case 62: goto st1;
+                case 63: goto tr46;
+                case 127: goto st1;
+        }
+        if ( (*p) > 31 ) {
+                if ( 34 <= (*p) && (*p) <= 35 )
+                        goto st1;
+        } else if ( (*p) >= 0 )
+                goto st1;
+        goto st33;
+st34:
+        if ( ++p == pe )
+                goto _out34;
+case 34:
+        if ( (*p) < 65 ) {
+                if ( 48 <= (*p) && (*p) <= 57 )
+                        goto st35;
+        } else if ( (*p) > 70 ) {
+                if ( 97 <= (*p) && (*p) <= 102 )
+                        goto st35;
+        } else
+                goto st35;
+        goto st1;
+st35:
+        if ( ++p == pe )
+                goto _out35;
+case 35:
+        if ( (*p) < 65 ) {
+                if ( 48 <= (*p) && (*p) <= 57 )
+                        goto st33;
+        } else if ( (*p) > 70 ) {
+                if ( 97 <= (*p) && (*p) <= 102 )
+                        goto st33;
+        } else
+                goto st33;
+        goto st1;
+tr46:
+#line 33 "ext/http11/http11_parser.rl"
+        {
+               if(parser->path_info != NULL)
+                              parser->path_info(parser->data, parser->mark, p - parser->mark);
+        }
+        goto st36;
+st36:
+        if ( ++p == pe )
+                goto _out36;
+case 36:
+#line 613 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 32: goto tr48;
+                case 37: goto tr54;
+                case 60: goto st1;
+                case 62: goto st1;
+                case 127: goto st1;
+        }
+        if ( (*p) > 31 ) {
+                if ( 34 <= (*p) && (*p) <= 35 )
+                        goto st1;
+        } else if ( (*p) >= 0 )
+                goto st1;
+        goto tr53;
+tr53:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st37;
+st37:
+        if ( ++p == pe )
+                goto _out37;
+case 37:
+#line 635 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 32: goto tr48;
+                case 37: goto st38;
+                case 60: goto st1;
+                case 62: goto st1;
+                case 127: goto st1;
+        }
+        if ( (*p) > 31 ) {
+                if ( 34 <= (*p) && (*p) <= 35 )
+                        goto st1;
+        } else if ( (*p) >= 0 )
+                goto st1;
+        goto st37;
+tr54:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st38;
+st38:
+        if ( ++p == pe )
+                goto _out38;
+case 38:
+#line 657 "ext/http11/http11_parser.c"
+        if ( (*p) < 65 ) {
+                if ( 48 <= (*p) && (*p) <= 57 )
+                        goto st39;
+        } else if ( (*p) > 70 ) {
+                if ( 97 <= (*p) && (*p) <= 102 )
+                        goto st39;
+        } else
+                goto st39;
+        goto st1;
+st39:
+        if ( ++p == pe )
+                goto _out39;
+case 39:
+        if ( (*p) < 65 ) {
+                if ( 48 <= (*p) && (*p) <= 57 )
+                        goto st37;
+        } else if ( (*p) > 70 ) {
+                if ( 97 <= (*p) && (*p) <= 102 )
+                        goto st37;
+        } else
+                goto st37;
+        goto st1;
+tr14:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st40;
+st40:
+        if ( ++p == pe )
+                goto _out40;
+case 40:
+#line 688 "ext/http11/http11_parser.c"
+        if ( (*p) == 69 )
+                goto st41;
+        goto st1;
+st41:
+        if ( ++p == pe )
+                goto _out41;
+case 41:
+        if ( (*p) == 84 )
+                goto st7;
+        goto st1;
+tr15:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st42;
+st42:
+        if ( ++p == pe )
+                goto _out42;
+case 42:
+#line 707 "ext/http11/http11_parser.c"
+        if ( (*p) == 69 )
+                goto st43;
+        goto st1;
+st43:
+        if ( ++p == pe )
+                goto _out43;
+case 43:
+        if ( (*p) == 65 )
+                goto st44;
+        goto st1;
+st44:
+        if ( ++p == pe )
+                goto _out44;
+case 44:
+        if ( (*p) == 68 )
+                goto st7;
+        goto st1;
+tr16:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st45;
+st45:
+        if ( ++p == pe )
+                goto _out45;
+case 45:
+#line 733 "ext/http11/http11_parser.c"
+        if ( (*p) == 80 )
+                goto st46;
+        goto st1;
+st46:
+        if ( ++p == pe )
+                goto _out46;
+case 46:
+        if ( (*p) == 84 )
+                goto st47;
+        goto st1;
+st47:
+        if ( ++p == pe )
+                goto _out47;
+case 47:
+        if ( (*p) == 73 )
+                goto st48;
+        goto st1;
+st48:
+        if ( ++p == pe )
+                goto _out48;
+case 48:
+        if ( (*p) == 79 )
+                goto st49;
+        goto st1;
+st49:
+        if ( ++p == pe )
+                goto _out49;
+case 49:
+        if ( (*p) == 78 )
+                goto st50;
+        goto st1;
+st50:
+        if ( ++p == pe )
+                goto _out50;
+case 50:
+        if ( (*p) == 83 )
+                goto st7;
+        goto st1;
+tr17:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st51;
+st51:
+        if ( ++p == pe )
+                goto _out51;
+case 51:
+#line 780 "ext/http11/http11_parser.c"
+        switch( (*p) ) {
+                case 79: goto st52;
+                case 85: goto st41;
+        }
+        goto st1;
+st52:
+        if ( ++p == pe )
+                goto _out52;
+case 52:
+        if ( (*p) == 83 )
+                goto st41;
+        goto st1;
+tr18:
+#line 14 "ext/http11/http11_parser.rl"
+        { MARK(parser, p); }
+        goto st53;
+st53:
+        if ( ++p == pe )
+                goto _out53;
+case 53:
+#line 801 "ext/http11/http11_parser.c"
+        if ( (*p) == 82 )
+                goto st54;
+        goto st1;
+st54:
+        if ( ++p == pe )
+                goto _out54;
+case 54:
+        if ( (*p) == 65 )
+                goto st55;
+        goto st1;
+st55:
+        if ( ++p == pe )
+                goto _out55;
+case 55:
+        if ( (*p) == 67 )
+                goto st6;
+        goto st1;
+        }
+        _out1: cs = 1; goto _out;
+        _out2: cs = 2; goto _out;
+        _out3: cs = 3; goto _out;
+        _out4: cs = 4; goto _out;
+        _out5: cs = 5; goto _out;
+        _out6: cs = 6; goto _out;
+        _out7: cs = 7; goto _out;
+        _out8: cs = 8; goto _out;
+        _out9: cs = 9; goto _out;
+        _out10: cs = 10; goto _out;
+        _out11: cs = 11; goto _out;
+        _out12: cs = 12; goto _out;
+        _out13: cs = 13; goto _out;
+        _out14: cs = 14; goto _out;
+        _out15: cs = 15; goto _out;
+        _out16: cs = 16; goto _out;
+        _out17: cs = 17; goto _out;
+        _out18: cs = 18; goto _out;
+        _out19: cs = 19; goto _out;
+        _out20: cs = 20; goto _out;
+        _out21: cs = 21; goto _out;
+        _out56: cs = 56; goto _out;
+        _out22: cs = 22; goto _out;
+        _out23: cs = 23; goto _out;
+        _out24: cs = 24; goto _out;
+        _out25: cs = 25; goto _out;
+        _out26: cs = 26; goto _out;
+        _out27: cs = 27; goto _out;
+        _out28: cs = 28; goto _out;
+        _out29: cs = 29; goto _out;
+        _out30: cs = 30; goto _out;
+        _out31: cs = 31; goto _out;
+        _out32: cs = 32; goto _out;
+        _out33: cs = 33; goto _out;
+        _out34: cs = 34; goto _out;
+        _out35: cs = 35; goto _out;
+        _out36: cs = 36; goto _out;
+        _out37: cs = 37; goto _out;
+        _out38: cs = 38; goto _out;
+        _out39: cs = 39; goto _out;
+        _out40: cs = 40; goto _out;
+        _out41: cs = 41; goto _out;
+        _out42: cs = 42; goto _out;
+        _out43: cs = 43; goto _out;
+        _out44: cs = 44; goto _out;
+        _out45: cs = 45; goto _out;
+        _out46: cs = 46; goto _out;
+        _out47: cs = 47; goto _out;
+        _out48: cs = 48; goto _out;
+        _out49: cs = 49; goto _out;
+        _out50: cs = 50; goto _out;
+        _out51: cs = 51; goto _out;
+        _out52: cs = 52; goto _out;
+        _out53: cs = 53; goto _out;
+        _out54: cs = 54; goto _out;
+        _out55: cs = 55; goto _out;
+
+        _out: {}
+        }
+#line 127 "ext/http11/http11_parser.rl"
+
+    parser->cs = cs;
+    parser->nread = p - buffer;
+    if(parser->body_start) {
+        /* final \r\n combo encountered so stop right here */
+        
+#line 886 "ext/http11/http11_parser.c"
+#line 133 "ext/http11/http11_parser.rl"
+        parser->nread++;
+    }
+
+    return(parser->nread);
+}
+
+int http_parser_finish(http_parser *parser)
+{
+        int cs = parser->cs;
+
+        
+#line 899 "ext/http11/http11_parser.c"
+#line 144 "ext/http11/http11_parser.rl"
+
+        parser->cs = cs;
+
+        if (http_parser_has_error(parser) ) {
+                return -1;
+        } else if (http_parser_is_finished(parser) ) {
+                return 1;
+        } else {
+               return 0;
+        }
+}
+
+int http_parser_has_error(http_parser *parser) {
+    return parser->cs == http_parser_error;
+}
+
+int http_parser_is_finished(http_parser *parser) {
+    return parser->cs == http_parser_first_final;
+}
diff --git a/ext/http11/http11_parser.h b/ext/http11/http11_parser.h
new file mode 100644
index 0000000..f4a205f
--- /dev/null
+++ b/ext/http11/http11_parser.h
@@ -0,0 +1,37 @@
+#ifndef http11_parser_h
+#define http11_parser_h
+
+#include <sys/types.h>
+
+typedef void (*element_cb)(void *data, const char *at, size_t length);
+typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen);
+
+typedef struct http_parser {
+  int cs;
+  const char *body_start;
+  int content_len;
+  size_t nread;
+  const char *mark;
+  const char *field_start;
+  size_t field_len;
+
+  void *data;
+
+  field_cb http_field;
+  element_cb request_method;
+  element_cb path_info;
+  element_cb query_string;
+  element_cb http_version;
+
+} http_parser;
+
+int http_parser_init(http_parser *parser);
+int http_parser_finish(http_parser *parser);
+size_t http_parser_execute(http_parser *parser, const char *data, size_t len );
+int http_parser_has_error(http_parser *parser);
+int http_parser_is_finished(http_parser *parser);
+void http_parser_destroy(http_parser *parser);
+
+#define http_parser_nread(parser) (parser)->nread
+
+#endif
diff --git a/ext/http11/http11_parser.rl b/ext/http11/http11_parser.rl
new file mode 100644
index 0000000..7642cb1
--- /dev/null
+++ b/ext/http11/http11_parser.rl
@@ -0,0 +1,162 @@
+#include "http11_parser.h"
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define MARK(S,F) assert((F) - (S)->mark >= 0); (S)->mark = (F);
+
+/** machine **/
+%%{
+        machine http_parser;
+
+            action mark { MARK(parser, fpc); }
+
+        action start_field { parser->field_start = fpc; }        
+        action write_field {
+               parser->field_len = (p - parser->field_start);
+        }
+
+        action start_value { MARK(parser, fpc); }
+        action write_value {
+               if(parser->http_field != NULL) {
+                              parser->http_field(parser->data,
+                                       parser->field_start, parser->field_len,
+                                parser->mark+1, p - (parser->mark +1));
+                }
+        }
+        action request_method {
+               if(parser->request_method != NULL)
+                              parser->request_method(parser->data, parser->mark, p - parser->mark);
+        }
+        action path_info {
+               if(parser->path_info != NULL)
+                              parser->path_info(parser->data, parser->mark, p - parser->mark);
+        }
+        action query_string {
+               if(parser->query_string != NULL)
+                              parser->query_string(parser->data, parser->mark, p - parser->mark);
+        }
+
+        action http_version {        
+               if(parser->http_version != NULL)
+                              parser->http_version(parser->data, parser->mark, p - parser->mark);
+        }
+            action done {
+               parser->body_start = p+1; fbreak;
+        }
+
+
+        #### HTTP PROTOCOL GRAMMAR
+        # line endings
+        CRLF = "\r\n";
+
+        # character types
+        CTL = (cntrl | 127);
+        safe = ("$" | "-" | "_" | ".");
+        extra = ("!" | "*" | "'" | "(" | ")" | ",");
+        reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
+        unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">");
+        national = any - (alpha | digit | reserved | extra | safe | unsafe);
+        unreserved = (alpha | digit | safe | extra | national);
+        escape = ("%" xdigit xdigit);
+        uchar = (unreserved | escape);
+        pchar = (uchar | ":" | "@" | "&" | "=" | "+");
+        tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
+
+        # elements
+        token = (ascii - (CTL | tspecials));
+
+        # URI schemes and absolute paths
+        scheme = ( alpha | digit | "+" | "-" | "." )* ;
+        absolute_uri = (scheme ":" (uchar | reserved )*) >mark %path_info;
+
+        path = (pchar+ ( "/" pchar* )*) ;
+        query = ( uchar | reserved )* >mark %query_string ;
+        param = ( pchar | "/" )* ;
+        params = (param ( ";" param )*) ;
+        rel_path = (path? (";" params)?) %path_info  ("?" query)? ;
+        absolute_path = ("/" rel_path) >mark ;
+        
+        Request_URI = ("*" >mark %path_info | absolute_uri | absolute_path) ;
+        Method = ("OPTIONS"| "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE") >mark %request_method;
+        
+        http_number = (digit+ "." digit+) ;
+        HTTP_Version = ("HTTP/" http_number) >mark %http_version ;
+        Request_Line = (Method " " Request_URI " " HTTP_Version CRLF) ;
+
+      
+        
+        field_name = (token - ":")+ >start_field %write_field;
+
+        field_value = (any - CRLF)*;
+
+        message_header = field_name ":" field_value >start_value %write_value CRLF;
+        
+        Request = Request_Line (message_header)* $0 ( CRLF $1 @done );
+
+                main := Request;
+}%%
+
+/** Data **/
+%% write data;
+
+int http_parser_init(http_parser *parser)  {
+    int cs = 0;
+    %% write init;
+    parser->cs = cs;
+    parser->body_start = NULL;
+    parser->content_len = 0;
+    parser->mark = NULL;
+    parser->nread = 0;
+
+    return(1);
+}
+
+
+/** exec **/
+size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len)  {
+    const char *p, *pe;
+    int cs = parser->cs;
+
+    p = buffer;
+    pe = buffer+len;
+
+    %% write exec;
+
+    parser->cs = cs;
+    parser->nread = p - buffer;
+    if(parser->body_start) {
+        /* final \r\n combo encountered so stop right here */
+        %%write eof;
+        parser->nread++;
+    }
+
+    return(parser->nread);
+}
+
+int http_parser_finish(http_parser *parser)
+{
+        int cs = parser->cs;
+
+        %%write eof;
+
+        parser->cs = cs;
+
+        if (http_parser_has_error(parser) ) {
+                return -1;
+        } else if (http_parser_is_finished(parser) ) {
+                return 1;
+        } else {
+               return 0;
+        }
+}
+
+int http_parser_has_error(http_parser *parser) {
+    return parser->cs == http_parser_error;
+}
+
+int http_parser_is_finished(http_parser *parser) {
+    return parser->cs == http_parser_first_final;
+}
diff --git a/ext/http11/tst.h b/ext/http11/tst.h
new file mode 100644
index 0000000..8e5ab2c
--- /dev/null
+++ b/ext/http11/tst.h
@@ -0,0 +1,40 @@
+
+
+struct node
+{
+   unsigned char value;
+   struct node *left;
+   struct node *middle;
+   struct node *right;
+};
+
+struct tst
+{
+   int node_line_width;
+   struct node_lines *node_lines;
+   struct node *free_list;
+   struct node *head[127];
+};
+
+struct node_lines
+{
+   struct node *node_line;
+   struct node_lines *next;
+};
+
+enum tst_constants
+{
+   TST_OK, TST_ERROR, TST_NULL_KEY, TST_DUPLICATE_KEY, TST_REPLACE
+};
+
+struct tst *tst_init(int node_line_width);
+
+int tst_insert(unsigned char *key, void *data, struct tst *tst, int option, void **exist_ptr);
+
+void *tst_search(unsigned char *key, struct tst *tst, int *prefix_len);
+
+void *tst_delete(unsigned char *key, struct tst *tst);
+
+void tst_cleanup(struct tst *tst);
+
+
diff --git a/ext/http11/tst_cleanup.c b/ext/http11/tst_cleanup.c
new file mode 100644
index 0000000..b574f9f
--- /dev/null
+++ b/ext/http11/tst_cleanup.c
@@ -0,0 +1,24 @@
+
+#include "tst.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+void tst_cleanup(struct tst *tst)
+{
+   struct node_lines *current_line;
+   struct node_lines *next_line;
+
+   next_line = tst->node_lines;
+
+   do
+   {
+      current_line = next_line;
+      next_line = current_line->next;
+      free(current_line->node_line);
+      free(current_line);
+   }
+   while(next_line != NULL);
+
+   free(tst);
+}
+
diff --git a/ext/http11/tst_delete.c b/ext/http11/tst_delete.c
new file mode 100644
index 0000000..cb18f16
--- /dev/null
+++ b/ext/http11/tst_delete.c
@@ -0,0 +1,146 @@
+
+#include "tst.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+void *tst_delete(unsigned char *key, struct tst *tst)
+{
+   struct node *current_node;
+   struct node *current_node_parent;
+   struct node *last_branch;
+   struct node *last_branch_parent;
+   struct node *next_node;
+   struct node *last_branch_replacement;
+   struct node *last_branch_dangling_child;
+   int key_index;
+
+  
+   if(key[0] == 0)
+      return NULL;
+   if(tst->head[(int)key[0]] == NULL)
+      return NULL;
+  
+   last_branch = NULL;
+   last_branch_parent = NULL;
+   current_node = tst->head[(int)key[0]];
+   current_node_parent = NULL;
+   key_index = 1;
+   while(current_node != NULL)
+   {
+      if(key[key_index] == current_node->value)
+      {
+        
+         if( (current_node->left != NULL) || (current_node->right != NULL) )
+         {
+            last_branch = current_node;
+            last_branch_parent = current_node_parent;
+         }
+         if(key[key_index] == 0)
+            break;
+         else
+         {
+            current_node_parent = current_node;
+            current_node = current_node->middle;
+            key_index++;
+            continue;
+         }
+      }
+      else if( ((current_node->value == 0) && (key[key_index] < 64)) ||
+         ((current_node->value != 0) && (key[key_index] <
+         current_node->value)) )
+      {
+         last_branch_parent = current_node;
+         current_node_parent = current_node;
+         current_node = current_node->left;
+         last_branch = current_node;
+         continue;
+      }
+      else
+      {
+         last_branch_parent = current_node;
+         current_node_parent = current_node;
+         current_node = current_node->right;
+         last_branch = current_node;
+         continue;
+      }
+  
+   }
+   if(current_node == NULL)
+      return NULL;
+  
+   if(last_branch == NULL)
+   {
+      
+         next_node = tst->head[(int)key[0]];
+         tst->head[(int)key[0]] = NULL;
+   }
+   else if( (last_branch->left == NULL) && (last_branch->right == NULL) )
+   {
+      
+      if(last_branch_parent->left == last_branch)
+         last_branch_parent->left = NULL;
+      else
+         last_branch_parent->right = NULL;
+      
+      next_node = last_branch;
+   }
+   else
+   {
+      
+      if( (last_branch->left != NULL) && (last_branch->right != NULL) )
+      {
+         last_branch_replacement = last_branch->right;
+         last_branch_dangling_child = last_branch->left;
+      }
+      else if(last_branch->right != NULL)
+      {
+         last_branch_replacement = last_branch->right;
+         last_branch_dangling_child = NULL;
+      }
+      else
+      {
+         last_branch_replacement = last_branch->left;
+         last_branch_dangling_child = NULL;
+      }
+      
+      if(last_branch_parent == NULL)
+         tst->head[(int)key[0]]=last_branch_replacement;
+      else
+      {
+         if (last_branch_parent->left == last_branch)
+            last_branch_parent->left = last_branch_replacement;
+         else if (last_branch_parent->right == last_branch)
+            last_branch_parent->right = last_branch_replacement;
+         else
+            last_branch_parent->middle = last_branch_replacement;
+      }
+      
+      if(last_branch_dangling_child != NULL)
+      {
+         current_node = last_branch_replacement;
+      
+         while (current_node->left != NULL)
+            current_node = current_node->left;
+      
+         current_node->left = last_branch_dangling_child;
+      }
+      
+      next_node = last_branch;
+   }
+  
+   do
+   {
+      current_node = next_node;
+      next_node = current_node->middle;
+      
+      current_node->left = NULL;
+      current_node->right = NULL;
+      current_node->middle = tst->free_list;
+      tst->free_list = current_node;
+   }
+   while(current_node->value != 0);
+  
+   return next_node;
+  
+}
+
diff --git a/ext/http11/tst_grow_node_free_list.c b/ext/http11/tst_grow_node_free_list.c
new file mode 100644
index 0000000..da21333
--- /dev/null
+++ b/ext/http11/tst_grow_node_free_list.c
@@ -0,0 +1,38 @@
+
+#include "tst.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+int tst_grow_node_free_list(struct tst *tst)
+{
+   struct node *current_node;
+   struct node_lines *new_line;
+   int i;
+
+  
+   if((new_line = (struct node_lines *) malloc(sizeof(struct node_lines))) == NULL)
+      return TST_ERROR;
+  
+   if((new_line->node_line = (struct node *)
+   calloc(tst->node_line_width, sizeof(struct node))) == NULL)
+   {
+      free(new_line);
+      return TST_ERROR;
+   }
+   else
+   {
+      new_line->next = tst->node_lines;
+      tst->node_lines = new_line;
+   }
+  
+   current_node = tst->node_lines->node_line;
+   tst->free_list = current_node;
+   for (i = 1; i < tst->node_line_width; i++)
+   {
+      current_node->middle = &(tst->node_lines->node_line[i]);
+      current_node = current_node->middle;
+   }
+   current_node->middle = NULL;
+   return 1;
+}
+
diff --git a/ext/http11/tst_init.c b/ext/http11/tst_init.c
new file mode 100644
index 0000000..259734a
--- /dev/null
+++ b/ext/http11/tst_init.c
@@ -0,0 +1,41 @@
+
+#include "tst.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+struct tst *tst_init(int width)
+{
+   struct tst *tst;
+   struct node *current_node;
+   int i;
+
+
+if((tst = (struct tst *) calloc(1, sizeof(struct tst))) == NULL)
+   return NULL;
+
+if ((tst->node_lines = (struct node_lines *) calloc(1, sizeof(struct node_lines))) == NULL)
+{
+   free(tst);
+   return NULL;
+}
+
+tst->node_line_width = width;
+tst->node_lines->next = NULL;
+if ((tst->node_lines->node_line = (struct node *) calloc(width, sizeof(struct node))) == NULL)
+{
+   free(tst->node_lines);
+   free(tst);
+   return NULL;
+}
+
+current_node = tst->node_lines->node_line;
+tst->free_list = current_node;
+for (i = 1; i < width; i++)
+{
+   current_node->middle = &(tst->node_lines->node_line[i]);
+   current_node = current_node->middle;
+}
+current_node->middle = NULL;
+return tst;
+}
+
diff --git a/ext/http11/tst_insert.c b/ext/http11/tst_insert.c
new file mode 100644
index 0000000..0f83849
--- /dev/null
+++ b/ext/http11/tst_insert.c
@@ -0,0 +1,192 @@
+
+#include "tst.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int tst_grow_node_free_list(struct tst *tst);
+int tst_insert(unsigned char *key, void *data, struct tst *tst, int option, void **exist_ptr)
+{
+   struct node *current_node;
+   struct node *new_node_tree_begin = NULL;
+   int key_index;
+   int perform_loop = 1;
+
+  
+   if (key == NULL)
+      return TST_NULL_KEY;
+  
+   if(key[0] == 0)
+      return TST_NULL_KEY;
+  
+   if(tst->head[(int)key[0]] == NULL)
+   {
+      
+      if(tst->free_list == NULL)
+      {
+         if(tst_grow_node_free_list(tst) != 1)
+            return TST_ERROR;
+      }
+      tst->head[(int)key[0]] = tst->free_list;
+      
+      tst->free_list = tst->free_list->middle;
+      current_node = tst->head[(int)key[0]];
+      current_node->value = key[1];
+      if(key[1] == 0)
+      {
+         current_node->middle = data;
+         return TST_OK;
+      }
+      else
+         perform_loop = 0;
+   }
+  
+   current_node = tst->head[(int)key[0]];
+   key_index = 1;
+   while(perform_loop == 1)
+   {
+      if(key[key_index] == current_node->value)
+      {
+        
+         if(key[key_index] == 0)
+         {
+            if (option == TST_REPLACE)
+            {
+               if (exist_ptr != NULL)
+                  *exist_ptr = current_node->middle;
+        
+               current_node->middle = data;
+               return TST_OK;
+            }
+            else
+            {
+               if (exist_ptr != NULL)
+                  *exist_ptr = current_node->middle;
+               return TST_DUPLICATE_KEY;
+            }
+         }
+         else
+         {
+            if(current_node->middle == NULL)
+            {
+              
+               if(tst->free_list == NULL)
+               {
+                  if(tst_grow_node_free_list(tst) != 1)
+                     return TST_ERROR;
+               }
+               current_node->middle = tst->free_list;
+              
+               tst->free_list = tst->free_list->middle;
+               new_node_tree_begin = current_node;
+               current_node = current_node->middle;
+               current_node->value = key[key_index];
+               break;
+            }
+            else
+            {
+               current_node = current_node->middle;
+               key_index++;
+               continue;
+            }
+         }
+      }
+  
+      if( ((current_node->value == 0) && (key[key_index] < 64)) ||
+         ((current_node->value != 0) && (key[key_index] <
+         current_node->value)) )
+      {
+        
+         if (current_node->left == NULL)
+         {
+            
+            if(tst->free_list == NULL)
+            {
+               if(tst_grow_node_free_list(tst) != 1)
+                  return TST_ERROR;
+            }
+            current_node->left = tst->free_list;
+            
+            tst->free_list = tst->free_list->middle;
+            new_node_tree_begin = current_node;
+            current_node = current_node->left;
+            current_node->value = key[key_index];
+            if(key[key_index] == 0)
+            {
+               current_node->middle = data;
+               return TST_OK;
+            }
+            else
+               break;
+         }
+         else
+         {
+            current_node = current_node->left;
+            continue;
+         }
+      }
+      else
+      {
+        
+         if (current_node->right == NULL)
+         {
+            
+            if(tst->free_list == NULL)
+            {
+               if(tst_grow_node_free_list(tst) != 1)
+                  return TST_ERROR;
+            }
+            current_node->right = tst->free_list;
+            
+            tst->free_list = tst->free_list->middle;
+            new_node_tree_begin = current_node;
+            current_node = current_node->right;
+            current_node->value = key[key_index];
+            break;
+         }
+         else
+         {
+            current_node = current_node->right;
+            continue;
+         }
+      }
+   }
+  
+   do
+   {
+      key_index++;
+  
+      if(tst->free_list == NULL)
+      {
+         if(tst_grow_node_free_list(tst) != 1)
+         {
+            current_node = new_node_tree_begin->middle;
+  
+            while (current_node->middle != NULL)
+               current_node = current_node->middle;
+  
+            current_node->middle = tst->free_list;
+            tst->free_list = new_node_tree_begin->middle;
+            new_node_tree_begin->middle = NULL;
+  
+            return TST_ERROR;
+         }
+      }
+  
+      
+      if(tst->free_list == NULL)
+      {
+         if(tst_grow_node_free_list(tst) != 1)
+            return TST_ERROR;
+      }
+      current_node->middle = tst->free_list;
+      
+      tst->free_list = tst->free_list->middle;
+      current_node = current_node->middle;
+      current_node->value = key[key_index];
+   } while(key[key_index] !=0);
+  
+   current_node->middle = data;
+   return TST_OK;
+}
+
diff --git a/ext/http11/tst_search.c b/ext/http11/tst_search.c
new file mode 100644
index 0000000..efa1cfa
--- /dev/null
+++ b/ext/http11/tst_search.c
@@ -0,0 +1,54 @@
+
+#include "tst.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+void *tst_search(unsigned char *key, struct tst *tst, int *prefix_len)
+{
+  struct node *current_node;
+  int key_index;
+  
+  assert(key != NULL && "key can't be NULL");
+  assert(tst != NULL && "tst can't be NULL");
+  
+  
+  if(key[0] == 0)
+    return NULL;
+  
+  if(tst->head[(int)key[0]] == NULL)
+    return NULL;
+  
+  current_node = tst->head[(int)key[0]];
+  key_index = 1;
+  
+  while (current_node != NULL)
+    {
+      if(key[key_index] == current_node->value)
+        {
+          if(current_node->value == 0) {
+            if(prefix_len) *prefix_len = key_index;
+            return current_node->middle;
+          } else {
+            current_node = current_node->middle;
+            key_index++;
+            continue;
+          }
+        }
+      else if( ((current_node->value == 0) && (key[key_index] < 64)) ||
+               ((current_node->value != 0) && (key[key_index] <
+                                               current_node->value)) )
+        {
+          current_node = current_node->left;
+          continue;
+        }
+      else
+        {
+          current_node = current_node->right;
+          continue;
+        }
+    }
+  
+  if(prefix_len) *prefix_len = key_index;
+  return NULL;
+}
diff --git a/lib/mongrel.rb b/lib/mongrel.rb
new file mode 100644
index 0000000..c46ccab
--- /dev/null
+++ b/lib/mongrel.rb
@@ -0,0 +1,191 @@
+require 'socket'
+require 'http11'
+require 'thread'
+
+
+# Mongrel module containing all of the classes (include C extensions) for running
+# a Mongrel web server.  It contains a minimalist HTTP server with just enough
+# functionality to service web application requests fast as possible.
+module Mongrel
+
+  # When a handler is found for a registered URI then this class is constructed
+  # and passed to your HttpHandler::process method.  You should assume that
+  # *one* handler processes all requests.  Included in the HttpReqeust is a
+  # HttpRequest.params Hash that matches common CGI params, and a HttpRequest.body
+  # which is a string containing the request body (raw for now).
+  #
+  # Mongrel really only support small-ish request bodies right now since really
+  # huge ones have to be completely read off the wire and put into a string.
+  # Later there will be several options for efficiently handling large file
+  # uploads.
+  class HttpRequest
+    attr_reader :body, :params
+    
+    # You don't really call this.  It's made for you.
+    # Main thing it does is hook up the params, and store any remaining
+    # body data into the HttpRequest.body attribute.
+    def initialize(params, initial_body, socket)
+      @body = initial_body || ""
+      @params = params
+      @socket = socket
+
+      # fix up the CGI requirements
+      params['CONTENT_LENGTH'] = params['HTTP_CONTENT_LENGTH'] || 0
+
+      # now, if the initial_body isn't long enough for the content length we have to fill it
+      # TODO: adapt for big ass stuff by writing to a temp file
+      clen = params['HTTP_CONTENT_LENGTH'].to_i
+      if @body.length < clen
+        @body << @socket.read(clen - @body.length)
+      end
+    end
+  end
+
+  # Very very simple response object.  You basically write your stuff raw
+  # to the HttpResponse.socket variable.  This will be made *much* easier
+  # in future releases allowing you to set status and request headers prior
+  # to sending the response.
+  class HttpResponse
+    attr_reader :socket
+    
+    def initialize(socket)
+      @socket = socket
+    end
+  
+  end
+  
+  # You implement your application handler with this.  It's very light giving
+  # just the minimum necessary for you to handle a request and shoot back
+  # a response.  Look at the HttpRequest and HttpResponse objects for how
+  # to use them.
+  class HttpHandler
+    attr_accessor :script_name
+
+    def process(request, response)
+    end
+  end
+
+  # The server normally returns a 404 response if a URI is requested, but it
+  # also returns a lame empty message.  This lets you do a 404 response
+  # with a custom message for special URIs.
+  class Error404Handler < HttpHandler
+
+    # Sets the message to return.  This is constructed once for the handler
+    # so it's pretty efficient.
+    def initialize(msg)
+      @response = HttpServer::ERROR_404_RESPONSE + msg
+    end
+    
+    # Just kicks back the standard 404 response with your special message.
+    def process(request, response)
+      response.socket.write(@response)
+    end
+
+  end
+  
+
+  # This is the main driver of Mongrel, while the Mognrel::HttpParser and Mongrel::URIClassifier
+  # make up the majority of how the server functions.  It's a very simple class that just
+  # has a thread accepting connections and a simple HttpServer.process_client function
+  # to do the heavy lifting with the IO and Ruby.  
+  #
+  # *NOTE:* The process_client function used threads at one time but that proved to have
+  # stability issues on Mac OSX.  Actually, Ruby in general has stability issues on Mac OSX.
+  #
+  # You use it by doing the following:
+  #
+  #   server = HttpServer.new("0.0.0.0", 3000)
+  #   server.register("/stuff", MyNifterHandler.new)
+  #   server.run.join
+  #
+  # The last line can be just server.run if you don't want to join the thread used.
+  # If you don't though Ruby will mysteriously just exit on you.
+  class HttpServer
+    attr_reader :acceptor
+
+    # The standard empty 404 response for bad requests.  Use Error4040Handler for custom stuff.
+    ERROR_404_RESPONSE="HTTP/1.1 404 Not Found\r\nConnection: close\r\nContent-Type: text/plain\r\nServer: Mongrel/0.1\r\n\r\n"
+
+    # For now we just read 2k chunks.  Not optimal at all.
+    CHUNK_SIZE=2048
+    
+    # Creates a working server on host:port (strange things happen if port isn't a Number).
+    # Use HttpServer::run to start the server.
+    def initialize(host, port)
+      @socket = TCPServer.new(host, port)
+      @classifier = URIClassifier.new
+    end
+    
+    # Used internally to process an accepted client.  It uses HttpParser and URIClassifier
+    # (in ext/http11/http11.c) to do the heavy work, and mostly just does a hack job
+    # at some simple IO.  Future releases will target this area mostly.
+    def process_client(client)
+      begin
+        parser = HttpParser.new
+        params = {}
+        data = ""
+        
+        while true
+          data << client.readpartial(CHUNK_SIZE)
+          
+          nread = parser.execute(params, data)
+          
+          if parser.error?
+            STDERR.puts "parser error:"
+            STDERR.puts data
+            break
+          elsif parser.finished?
+            script_name, path_info, handler = @classifier.resolve(params["PATH_INFO"])
+            
+            if handler
+              params['PATH_INFO'] = path_info
+              params['SCRIPT_NAME'] = script_name
+              
+              request = HttpRequest.new(params, data[nread ... data.length], client)
+              response = HttpResponse.new(client)
+              
+              handler.process(request, response)
+            else
+              client.write(ERROR_404_RESPONSE)
+            end
+            
+            break
+          else
+            # gotta stream and read again until we can get the parser to be character safe
+            # TODO: make this more efficient since this means we're parsing a lot repeatedly
+            parser.reset
+          end
+        end
+      rescue => details
+        STDERR.puts "ERROR: #{details}"
+        STDERR.puts details.backtrace.join("\n")
+      ensure
+        client.close
+      end
+    end
+
+    # Runs the thing.  It returns the thread used so you can "join" it.  You can also
+    # access the HttpServer::acceptor attribute to get the thread later.
+    def run
+      @acceptor = Thread.new do
+        while true
+          process_client(@socket.accept)
+        end
+      end
+    end
+
+    
+    # Simply registers a handler with the internal URIClassifier.  When the URI is
+    # found in the prefix of a request then your handler's HttpHandler::process method
+    # is called.  See Mongrel::URIClassifier#register for more information.
+    def register(uri, handler)
+      @classifier.register(uri, handler)
+    end
+
+    # Removes any handler registered at the given URI.  See Mongrel::URIClassifier#unregister
+    # for more information.
+    def unregister(uri)
+      @classifier.unregister(uri)
+    end
+  end
+end
diff --git a/setup.rb b/setup.rb
new file mode 100644
index 0000000..0807023
--- /dev/null
+++ b/setup.rb
@@ -0,0 +1,1360 @@
+#
+# setup.rb
+#
+# Copyright (c) 2000-2004 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU LGPL, Lesser General Public License version 2.1.
+#
+
+unless Enumerable.method_defined?(:map)   # Ruby 1.4.6
+  module Enumerable
+    alias map collect
+  end
+end
+
+unless File.respond_to?(:read)   # Ruby 1.6
+  def File.read(fname)
+    open(fname) {|f|
+      return f.read
+    }
+  end
+end
+
+def File.binread(fname)
+  open(fname, 'rb') {|f|
+    return f.read
+  }
+end
+
+# for corrupted windows stat(2)
+def File.dir?(path)
+  File.directory?((path[-1,1] == '/') ? path : path + '/')
+end
+
+
+class SetupError < StandardError; end
+
+def setup_rb_error(msg)
+  raise SetupError, msg
+end
+
+#
+# Config
+#
+
+if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
+  ARGV.delete(arg)
+  require arg.split(/=/, 2)[1]
+  $".push 'rbconfig.rb'
+else
+  require 'rbconfig'
+end
+
+def multipackage_install?
+  FileTest.directory?(File.dirname($0) + '/packages')
+end
+
+
+class ConfigItem
+  def initialize(name, template, default, desc)
+    @name = name.freeze
+    @template = template
+    @value = default
+    @default = default.dup.freeze
+    @description = desc
+  end
+
+  attr_reader :name
+  attr_reader :description
+
+  attr_accessor :default
+  alias help_default default
+
+  def help_opt
+    "--#{@name}=#{@template}"
+  end
+
+  def value
+    @value
+  end
+
+  def eval(table)
+    @value.gsub(%r<\$([^/]+)>) { table[$1] }
+  end
+
+  def set(val)
+    @value = check(val)
+  end
+
+  private
+
+  def check(val)
+    setup_rb_error "config: --#{name} requires argument" unless val
+    val
+  end
+end
+
+class BoolItem < ConfigItem
+  def config_type
+    'bool'
+  end
+
+  def help_opt
+    "--#{@name}"
+  end
+
+  private
+
+  def check(val)
+    return 'yes' unless val
+    unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val
+      setup_rb_error "config: --#{@name} accepts only yes/no for argument"
+    end
+    (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
+  end
+end
+
+class PathItem < ConfigItem
+  def config_type
+    'path'
+  end
+
+  private
+
+  def check(path)
+    setup_rb_error "config: --#{@name} requires argument"  unless path
+    path[0,1] == '$' ? path : File.expand_path(path)
+  end
+end
+
+class ProgramItem < ConfigItem
+  def config_type
+    'program'
+  end
+end
+
+class SelectItem < ConfigItem
+  def initialize(name, template, default, desc)
+    super
+    @ok = template.split('/')
+  end
+
+  def config_type
+    'select'
+  end
+
+  private
+
+  def check(val)
+    unless @ok.include?(val.strip)
+      setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
+    end
+    val.strip
+  end
+end
+
+class PackageSelectionItem < ConfigItem
+  def initialize(name, template, default, help_default, desc)
+    super name, template, default, desc
+    @help_default = help_default
+  end
+
+  attr_reader :help_default
+
+  def config_type
+    'package'
+  end
+
+  private
+
+  def check(val)
+    unless File.dir?("packages/#{val}")
+      setup_rb_error "config: no such package: #{val}"
+    end
+    val
+  end
+end
+
+class ConfigTable_class
+
+  def initialize(items)
+    @items = items
+    @table = {}
+    items.each do |i|
+      @table[i.name] = i
+    end
+    ALIASES.each do |ali, name|
+      @table[ali] = @table[name]
+    end
+  end
+
+  include Enumerable
+
+  def each(&block)
+    @items.each(&block)
+  end
+
+  def key?(name)
+    @table.key?(name)
+  end
+
+  def lookup(name)
+    @table[name] or raise ArgumentError, "no such config item: #{name}"
+  end
+
+  def add(item)
+    @items.push item
+    @table[item.name] = item
+  end
+
+  def remove(name)
+    item = lookup(name)
+    @items.delete_if {|i| i.name == name }
+    @table.delete_if {|name, i| i.name == name }
+    item
+  end
+
+  def new
+    dup()
+  end
+
+  def savefile
+    '.config'
+  end
+
+  def load
+    begin
+      t = dup()
+      File.foreach(savefile()) do |line|
+        k, v = *line.split(/=/, 2)
+        t[k] = v.strip
+      end
+      t
+    rescue Errno::ENOENT
+      setup_rb_error $!.message + "#{File.basename($0)} config first"
+    end
+  end
+
+  def save
+    @items.each {|i| i.value }
+    File.open(savefile(), 'w') {|f|
+      @items.each do |i|
+        f.printf "%s=%s\n", i.name, i.value if i.value
+      end
+    }
+  end
+
+  def [](key)
+    lookup(key).eval(self)
+  end
+
+  def []=(key, val)
+    lookup(key).set val
+  end
+
+end
+
+c = ::Config::CONFIG
+
+rubypath = c['bindir'] + '/' + c['ruby_install_name']
+
+major = c['MAJOR'].to_i
+minor = c['MINOR'].to_i
+teeny = c['TEENY'].to_i
+version = "#{major}.#{minor}"
+
+# ruby ver. >= 1.4.4?
+newpath_p = ((major >= 2) or
+             ((major == 1) and
+              ((minor >= 5) or
+               ((minor == 4) and (teeny >= 4)))))
+
+if c['rubylibdir']
+  # V < 1.6.3
+  _stdruby         = c['rubylibdir']
+  _siteruby        = c['sitedir']
+  _siterubyver     = c['sitelibdir']
+  _siterubyverarch = c['sitearchdir']
+elsif newpath_p
+  # 1.4.4 <= V <= 1.6.3
+  _stdruby         = "$prefix/lib/ruby/#{version}"
+  _siteruby        = c['sitedir']
+  _siterubyver     = "$siteruby/#{version}"
+  _siterubyverarch = "$siterubyver/#{c['arch']}"
+else
+  # V < 1.4.4
+  _stdruby         = "$prefix/lib/ruby/#{version}"
+  _siteruby        = "$prefix/lib/ruby/#{version}/site_ruby"
+  _siterubyver     = _siteruby
+  _siterubyverarch = "$siterubyver/#{c['arch']}"
+end
+libdir = '-* dummy libdir *-'
+stdruby = '-* dummy rubylibdir *-'
+siteruby = '-* dummy site_ruby *-'
+siterubyver = '-* dummy site_ruby version *-'
+parameterize = lambda {|path|
+  path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')\
+      .sub(/\A#{Regexp.quote(libdir)}/,      '$libdir')\
+      .sub(/\A#{Regexp.quote(stdruby)}/,     '$stdruby')\
+      .sub(/\A#{Regexp.quote(siteruby)}/,    '$siteruby')\
+      .sub(/\A#{Regexp.quote(siterubyver)}/, '$siterubyver')
+}
+libdir          = parameterize.call(c['libdir'])
+stdruby         = parameterize.call(_stdruby)
+siteruby        = parameterize.call(_siteruby)
+siterubyver     = parameterize.call(_siterubyver)
+siterubyverarch = parameterize.call(_siterubyverarch)
+
+if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
+  makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
+else
+  makeprog = 'make'
+end
+
+common_conf = [
+  PathItem.new('prefix', 'path', c['prefix'],
+               'path prefix of target environment'),
+  PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
+               'the directory for commands'),
+  PathItem.new('libdir', 'path', libdir,
+               'the directory for libraries'),
+  PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
+               'the directory for shared data'),
+  PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
+               'the directory for man pages'),
+  PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
+               'the directory for man pages'),
+  PathItem.new('stdruby', 'path', stdruby,
+               'the directory for standard ruby libraries'),
+  PathItem.new('siteruby', 'path', siteruby,
+      'the directory for version-independent aux ruby libraries'),
+  PathItem.new('siterubyver', 'path', siterubyver,
+               'the directory for aux ruby libraries'),
+  PathItem.new('siterubyverarch', 'path', siterubyverarch,
+               'the directory for aux ruby binaries'),
+  PathItem.new('rbdir', 'path', '$siterubyver',
+               'the directory for ruby scripts'),
+  PathItem.new('sodir', 'path', '$siterubyverarch',
+               'the directory for ruby extentions'),
+  PathItem.new('rubypath', 'path', rubypath,
+               'the path to set to #! line'),
+  ProgramItem.new('rubyprog', 'name', rubypath,
+                  'the ruby program using for installation'),
+  ProgramItem.new('makeprog', 'name', makeprog,
+                  'the make program to compile ruby extentions'),
+  SelectItem.new('shebang', 'all/ruby/never', 'ruby',
+                 'shebang line (#!) editing mode'),
+  BoolItem.new('without-ext', 'yes/no', 'no',
+               'does not compile/install ruby extentions')
+]
+class ConfigTable_class   # open again
+  ALIASES = {
+    'std-ruby'         => 'stdruby',
+    'site-ruby-common' => 'siteruby',     # For backward compatibility
+    'site-ruby'        => 'siterubyver',  # For backward compatibility
+    'bin-dir'          => 'bindir',
+    'bin-dir'          => 'bindir',
+    'rb-dir'           => 'rbdir',
+    'so-dir'           => 'sodir',
+    'data-dir'         => 'datadir',
+    'ruby-path'        => 'rubypath',
+    'ruby-prog'        => 'rubyprog',
+    'ruby'             => 'rubyprog',
+    'make-prog'        => 'makeprog',
+    'make'             => 'makeprog'
+  }
+end
+multipackage_conf = [
+  PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
+                           'package names that you want to install'),
+  PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
+                           'package names that you do not want to install')
+]
+if multipackage_install?
+  ConfigTable = ConfigTable_class.new(common_conf + multipackage_conf)
+else
+  ConfigTable = ConfigTable_class.new(common_conf)
+end
+
+
+module MetaConfigAPI
+
+  def eval_file_ifexist(fname)
+    instance_eval File.read(fname), fname, 1 if File.file?(fname)
+  end
+
+  def config_names
+    ConfigTable.map {|i| i.name }
+  end
+
+  def config?(name)
+    ConfigTable.key?(name)
+  end
+
+  def bool_config?(name)
+    ConfigTable.lookup(name).config_type == 'bool'
+  end
+
+  def path_config?(name)
+    ConfigTable.lookup(name).config_type == 'path'
+  end
+
+  def value_config?(name)
+    case ConfigTable.lookup(name).config_type
+    when 'bool', 'path'
+      true
+    else
+      false
+    end
+  end
+
+  def add_config(item)
+    ConfigTable.add item
+  end
+
+  def add_bool_config(name, default, desc)
+    ConfigTable.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
+  end
+
+  def add_path_config(name, default, desc)
+    ConfigTable.add PathItem.new(name, 'path', default, desc)
+  end
+
+  def set_config_default(name, default)
+    ConfigTable.lookup(name).default = default
+  end
+
+  def remove_config(name)
+    ConfigTable.remove(name)
+  end
+
+end
+
+
+#
+# File Operations
+#
+
+module FileOperations
+
+  def mkdir_p(dirname, prefix = nil)
+    dirname = prefix + File.expand_path(dirname) if prefix
+    $stderr.puts "mkdir -p #{dirname}" if verbose?
+    return if no_harm?
+
+    # does not check '/'... it's too abnormal case
+    dirs = File.expand_path(dirname).split(%r<(?=/)>)
+    if /\A[a-z]:\z/i =~ dirs[0]
+      disk = dirs.shift
+      dirs[0] = disk + dirs[0]
+    end
+    dirs.each_index do |idx|
+      path = dirs[0..idx].join('')
+      Dir.mkdir path unless File.dir?(path)
+    end
+  end
+
+  def rm_f(fname)
+    $stderr.puts "rm -f #{fname}" if verbose?
+    return if no_harm?
+
+    if File.exist?(fname) or File.symlink?(fname)
+      File.chmod 0777, fname
+      File.unlink fname
+    end
+  end
+
+  def rm_rf(dn)
+    $stderr.puts "rm -rf #{dn}" if verbose?
+    return if no_harm?
+
+    Dir.chdir dn
+    Dir.foreach('.') do |fn|
+      next if fn == '.'
+      next if fn == '..'
+      if File.dir?(fn)
+        verbose_off {
+          rm_rf fn
+        }
+      else
+        verbose_off {
+          rm_f fn
+        }
+      end
+    end
+    Dir.chdir '..'
+    Dir.rmdir dn
+  end
+
+  def move_file(src, dest)
+    File.unlink dest if File.exist?(dest)
+    begin
+      File.rename src, dest
+    rescue
+      File.open(dest, 'wb') {|f| f.write File.binread(src) }
+      File.chmod File.stat(src).mode, dest
+      File.unlink src
+    end
+  end
+
+  def install(from, dest, mode, prefix = nil)
+    $stderr.puts "install #{from} #{dest}" if verbose?
+    return if no_harm?
+
+    realdest = prefix ? prefix + File.expand_path(dest) : dest
+    realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
+    str = File.binread(from)
+    if diff?(str, realdest)
+      verbose_off {
+        rm_f realdest if File.exist?(realdest)
+      }
+      File.open(realdest, 'wb') {|f|
+        f.write str
+      }
+      File.chmod mode, realdest
+
+      File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
+        if prefix
+          f.puts realdest.sub(prefix, '')
+        else
+          f.puts realdest
+        end
+      }
+    end
+  end
+
+  def diff?(new_content, path)
+    return true unless File.exist?(path)
+    new_content != File.binread(path)
+  end
+
+  def command(str)
+    $stderr.puts str if verbose?
+    system str or raise RuntimeError, "'system #{str}' failed"
+  end
+
+  def ruby(str)
+    command config('rubyprog') + ' ' + str
+  end
+  
+  def make(task = '')
+    command config('makeprog') + ' ' + task
+  end
+
+  def extdir?(dir)
+    File.exist?(dir + '/MANIFEST')
+  end
+
+  def all_files_in(dirname)
+    Dir.open(dirname) {|d|
+      return d.select {|ent| File.file?("#{dirname}/#{ent}") }
+    }
+  end
+
+  REJECT_DIRS = %w(
+    CVS SCCS RCS CVS.adm .svn
+  )
+
+  def all_dirs_in(dirname)
+    Dir.open(dirname) {|d|
+      return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
+    }
+  end
+
+end
+
+
+#
+# Main Installer
+#
+
+module HookUtils
+
+  def run_hook(name)
+    try_run_hook "#{curr_srcdir()}/#{name}" or
+    try_run_hook "#{curr_srcdir()}/#{name}.rb"
+  end
+
+  def try_run_hook(fname)
+    return false unless File.file?(fname)
+    begin
+      instance_eval File.read(fname), fname, 1
+    rescue
+      setup_rb_error "hook #{fname} failed:\n" + $!.message
+    end
+    true
+  end
+
+end
+
+
+module HookScriptAPI
+
+  def get_config(key)
+    @config[key]
+  end
+
+  alias config get_config
+
+  def set_config(key, val)
+    @config[key] = val
+  end
+
+  #
+  # srcdir/objdir (works only in the package directory)
+  #
+
+  #abstract srcdir_root
+  #abstract objdir_root
+  #abstract relpath
+
+  def curr_srcdir
+    "#{srcdir_root()}/#{relpath()}"
+  end
+
+  def curr_objdir
+    "#{objdir_root()}/#{relpath()}"
+  end
+
+  def srcfile(path)
+    "#{curr_srcdir()}/#{path}"
+  end
+
+  def srcexist?(path)
+    File.exist?(srcfile(path))
+  end
+
+  def srcdirectory?(path)
+    File.dir?(srcfile(path))
+  end
+  
+  def srcfile?(path)
+    File.file? srcfile(path)
+  end
+
+  def srcentries(path = '.')
+    Dir.open("#{curr_srcdir()}/#{path}") {|d|
+      return d.to_a - %w(. ..)
+    }
+  end
+
+  def srcfiles(path = '.')
+    srcentries(path).select {|fname|
+      File.file?(File.join(curr_srcdir(), path, fname))
+    }
+  end
+
+  def srcdirectories(path = '.')
+    srcentries(path).select {|fname|
+      File.dir?(File.join(curr_srcdir(), path, fname))
+    }
+  end
+
+end
+
+
+class ToplevelInstaller
+
+  Version   = '3.3.1'
+  Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
+
+  TASKS = [
+    [ 'all',      'do config, setup, then install' ],
+    [ 'config',   'saves your configurations' ],
+    [ 'show',     'shows current configuration' ],
+    [ 'setup',    'compiles ruby extentions and others' ],
+    [ 'install',  'installs files' ],
+    [ 'clean',    "does `make clean' for each extention" ],
+    [ 'distclean',"does `make distclean' for each extention" ]
+  ]
+
+  def ToplevelInstaller.invoke
+    instance().invoke
+  end
+
+  @singleton = nil
+
+  def ToplevelInstaller.instance
+    @singleton ||= new(File.dirname($0))
+    @singleton
+  end
+
+  include MetaConfigAPI
+
+  def initialize(ardir_root)
+    @config = nil
+    @options = { 'verbose' => true }
+    @ardir = File.expand_path(ardir_root)
+  end
+
+  def inspect
+    "#<#{self.class} #{__id__()}>"
+  end
+
+  def invoke
+    run_metaconfigs
+    case task = parsearg_global()
+    when nil, 'all'
+      @config = load_config('config')
+      parsearg_config
+      init_installers
+      exec_config
+      exec_setup
+      exec_install
+    else
+      @config = load_config(task)
+      __send__ "parsearg_#{task}"
+      init_installers
+      __send__ "exec_#{task}"
+    end
+  end
+  
+  def run_metaconfigs
+    eval_file_ifexist "#{@ardir}/metaconfig"
+  end
+
+  def load_config(task)
+    case task
+    when 'config'
+      ConfigTable.new
+    when 'clean', 'distclean'
+      if File.exist?(ConfigTable.savefile)
+      then ConfigTable.load
+      else ConfigTable.new
+      end
+    else
+      ConfigTable.load
+    end
+  end
+
+  def init_installers
+    @installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
+  end
+
+  #
+  # Hook Script API bases
+  #
+
+  def srcdir_root
+    @ardir
+  end
+
+  def objdir_root
+    '.'
+  end
+
+  def relpath
+    '.'
+  end
+
+  #
+  # Option Parsing
+  #
+
+  def parsearg_global
+    valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
+
+    while arg = ARGV.shift
+      case arg
+      when /\A\w+\z/
+        setup_rb_error "invalid task: #{arg}" unless valid_task =~ arg
+        return arg
+
+      when '-q', '--quiet'
+        @options['verbose'] = false
+
+      when       '--verbose'
+        @options['verbose'] = true
+
+      when '-h', '--help'
+        print_usage $stdout
+        exit 0
+
+      when '-v', '--version'
+        puts "#{File.basename($0)} version #{Version}"
+        exit 0
+      
+      when '--copyright'
+        puts Copyright
+        exit 0
+
+      else
+        setup_rb_error "unknown global option '#{arg}'"
+      end
+    end
+
+    nil
+  end
+
+
+  def parsearg_no_options
+    unless ARGV.empty?
+      setup_rb_error "#{task}:  unknown options: #{ARGV.join ' '}"
+    end
+  end
+
+  alias parsearg_show       parsearg_no_options
+  alias parsearg_setup      parsearg_no_options
+  alias parsearg_clean      parsearg_no_options
+  alias parsearg_distclean  parsearg_no_options
+
+  def parsearg_config
+    re = /\A--(#{ConfigTable.map {|i| i.name }.join('|')})(?:=(.*))?\z/
+    @options['config-opt'] = []
+
+    while i = ARGV.shift
+      if /\A--?\z/ =~ i
+        @options['config-opt'] = ARGV.dup
+        break
+      end
+      m = re.match(i)  or setup_rb_error "config: unknown option #{i}"
+      name, value = *m.to_a[1,2]
+      @config[name] = value
+    end
+  end
+
+  def parsearg_install
+    @options['no-harm'] = false
+    @options['install-prefix'] = ''
+    while a = ARGV.shift
+      case a
+      when /\A--no-harm\z/
+        @options['no-harm'] = true
+      when /\A--prefix=(.*)\z/
+        path = $1
+        path = File.expand_path(path) unless path[0,1] == '/'
+        @options['install-prefix'] = path
+      else
+        setup_rb_error "install: unknown option #{a}"
+      end
+    end
+  end
+
+  def print_usage(out)
+    out.puts 'Typical Installation Procedure:'
+    out.puts "  $ ruby #{File.basename $0} config"
+    out.puts "  $ ruby #{File.basename $0} setup"
+    out.puts "  # ruby #{File.basename $0} install (may require root privilege)"
+    out.puts
+    out.puts 'Detailed Usage:'
+    out.puts "  ruby #{File.basename $0} <global option>"
+    out.puts "  ruby #{File.basename $0} [<global options>] <task> [<task options>]"
+
+    fmt = "  %-24s %s\n"
+    out.puts
+    out.puts 'Global options:'
+    out.printf fmt, '-q,--quiet',   'suppress message outputs'
+    out.printf fmt, '   --verbose', 'output messages verbosely'
+    out.printf fmt, '-h,--help',    'print this message'
+    out.printf fmt, '-v,--version', 'print version and quit'
+    out.printf fmt, '   --copyright',  'print copyright and quit'
+    out.puts
+    out.puts 'Tasks:'
+    TASKS.each do |name, desc|
+      out.printf fmt, name, desc
+    end
+
+    fmt = "  %-24s %s [%s]\n"
+    out.puts
+    out.puts 'Options for CONFIG or ALL:'
+    ConfigTable.each do |item|
+      out.printf fmt, item.help_opt, item.description, item.help_default
+    end
+    out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
+    out.puts
+    out.puts 'Options for INSTALL:'
+    out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
+    out.printf fmt, '--prefix=path',  'install path prefix', '$prefix'
+    out.puts
+  end
+
+  #
+  # Task Handlers
+  #
+
+  def exec_config
+    @installer.exec_config
+    @config.save   # must be final
+  end
+
+  def exec_setup
+    @installer.exec_setup
+  end
+
+  def exec_install
+    @installer.exec_install
+  end
+
+  def exec_show
+    ConfigTable.each do |i|
+      printf "%-20s %s\n", i.name, i.value
+    end
+  end
+
+  def exec_clean
+    @installer.exec_clean
+  end
+
+  def exec_distclean
+    @installer.exec_distclean
+  end
+
+end
+
+
+class ToplevelInstallerMulti < ToplevelInstaller
+
+  include HookUtils
+  include HookScriptAPI
+  include FileOperations
+
+  def initialize(ardir)
+    super
+    @packages = all_dirs_in("#{@ardir}/packages")
+    raise 'no package exists' if @packages.empty?
+  end
+
+  def run_metaconfigs
+    eval_file_ifexist "#{@ardir}/metaconfig"
+    @packages.each do |name|
+      eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
+    end
+  end
+
+  def init_installers
+    @installers = {}
+    @packages.each do |pack|
+      @installers[pack] = Installer.new(@config, @options,
+                                       "#{@ardir}/packages/#{pack}",
+                                       "packages/#{pack}")
+    end
+
+    with    = extract_selection(config('with'))
+    without = extract_selection(config('without'))
+    @selected = @installers.keys.select {|name|
+                  (with.empty? or with.include?(name)) \
+                      and not without.include?(name)
+                }
+  end
+
+  def extract_selection(list)
+    a = list.split(/,/)
+    a.each do |name|
+      setup_rb_error "no such package: #{name}"  unless @installers.key?(name)
+    end
+    a
+  end
+
+  def print_usage(f)
+    super
+    f.puts 'Inluded packages:'
+    f.puts '  ' + @packages.sort.join(' ')
+    f.puts
+  end
+
+  #
+  # multi-package metaconfig API
+  #
+
+  attr_reader :packages
+
+  def declare_packages(list)
+    raise 'package list is empty' if list.empty?
+    list.each do |name|
+      raise "directory packages/#{name} does not exist"\
+              unless File.dir?("#{@ardir}/packages/#{name}")
+    end
+    @packages = list
+  end
+
+  #
+  # Task Handlers
+  #
+
+  def exec_config
+    run_hook 'pre-config'
+    each_selected_installers {|inst| inst.exec_config }
+    run_hook 'post-config'
+    @config.save   # must be final
+  end
+
+  def exec_setup
+    run_hook 'pre-setup'
+    each_selected_installers {|inst| inst.exec_setup }
+    run_hook 'post-setup'
+  end
+
+  def exec_install
+    run_hook 'pre-install'
+    each_selected_installers {|inst| inst.exec_install }
+    run_hook 'post-install'
+  end
+
+  def exec_clean
+    rm_f ConfigTable.savefile
+    run_hook 'pre-clean'
+    each_selected_installers {|inst| inst.exec_clean }
+    run_hook 'post-clean'
+  end
+
+  def exec_distclean
+    rm_f ConfigTable.savefile
+    run_hook 'pre-distclean'
+    each_selected_installers {|inst| inst.exec_distclean }
+    run_hook 'post-distclean'
+  end
+
+  #
+  # lib
+  #
+
+  def each_selected_installers
+    Dir.mkdir 'packages' unless File.dir?('packages')
+    @selected.each do |pack|
+      $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose']
+      Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
+      Dir.chdir "packages/#{pack}"
+      yield @installers[pack]
+      Dir.chdir '../..'
+    end
+  end
+
+  def verbose?
+    @options['verbose']
+  end
+
+  def no_harm?
+    @options['no-harm']
+  end
+
+end
+
+
+class Installer
+
+  FILETYPES = %w( bin lib ext data )
+
+  include HookScriptAPI
+  include HookUtils
+  include FileOperations
+
+  def initialize(config, opt, srcroot, objroot)
+    @config = config
+    @options = opt
+    @srcdir = File.expand_path(srcroot)
+    @objdir = File.expand_path(objroot)
+    @currdir = '.'
+  end
+
+  def inspect
+    "#<#{self.class} #{File.basename(@srcdir)}>"
+  end
+
+  #
+  # Hook Script API base methods
+  #
+
+  def srcdir_root
+    @srcdir
+  end
+
+  def objdir_root
+    @objdir
+  end
+
+  def relpath
+    @currdir
+  end
+
+  #
+  # configs/options
+  #
+
+  def no_harm?
+    @options['no-harm']
+  end
+
+  def verbose?
+    @options['verbose']
+  end
+
+  def verbose_off
+    begin
+      save, @options['verbose'] = @options['verbose'], false
+      yield
+    ensure
+      @options['verbose'] = save
+    end
+  end
+
+  #
+  # TASK config
+  #
+
+  def exec_config
+    exec_task_traverse 'config'
+  end
+
+  def config_dir_bin(rel)
+  end
+
+  def config_dir_lib(rel)
+  end
+
+  def config_dir_ext(rel)
+    extconf if extdir?(curr_srcdir())
+  end
+
+  def extconf
+    opt = @options['config-opt'].join(' ')
+    command "#{config('rubyprog')} #{curr_srcdir()}/extconf.rb #{opt}"
+  end
+
+  def config_dir_data(rel)
+  end
+
+  #
+  # TASK setup
+  #
+
+  def exec_setup
+    exec_task_traverse 'setup'
+  end
+
+  def setup_dir_bin(rel)
+    all_files_in(curr_srcdir()).each do |fname|
+      adjust_shebang "#{curr_srcdir()}/#{fname}"
+    end
+  end
+
+  def adjust_shebang(path)
+    return if no_harm?
+    tmpfile = File.basename(path) + '.tmp'
+    begin
+      File.open(path, 'rb') {|r|
+        first = r.gets
+        return unless File.basename(config('rubypath')) == 'ruby'
+        return unless File.basename(first.sub(/\A\#!/, '').split[0]) == 'ruby'
+        $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose?
+        File.open(tmpfile, 'wb') {|w|
+          w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
+          w.write r.read
+        }
+        move_file tmpfile, File.basename(path)
+      }
+    ensure
+      File.unlink tmpfile if File.exist?(tmpfile)
+    end
+  end
+
+  def setup_dir_lib(rel)
+  end
+
+  def setup_dir_ext(rel)
+    make if extdir?(curr_srcdir())
+  end
+
+  def setup_dir_data(rel)
+  end
+
+  #
+  # TASK install
+  #
+
+  def exec_install
+    rm_f 'InstalledFiles'
+    exec_task_traverse 'install'
+  end
+
+  def install_dir_bin(rel)
+    install_files collect_filenames_auto(), "#{config('bindir')}/#{rel}", 0755
+  end
+
+  def install_dir_lib(rel)
+    install_files ruby_scripts(), "#{config('rbdir')}/#{rel}", 0644
+  end
+
+  def install_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    install_files ruby_extentions('.'),
+                  "#{config('sodir')}/#{File.dirname(rel)}",
+                  0555
+  end
+
+  def install_dir_data(rel)
+    install_files collect_filenames_auto(), "#{config('datadir')}/#{rel}", 0644
+  end
+
+  def install_files(list, dest, mode)
+    mkdir_p dest, @options['install-prefix']
+    list.each do |fname|
+      install fname, dest, mode, @options['install-prefix']
+    end
+  end
+
+  def ruby_scripts
+    collect_filenames_auto().select {|n| /\.rb\z/ =~ n }
+  end
+  
+  # picked up many entries from cvs-1.11.1/src/ignore.c
+  reject_patterns = %w(
+    core RCSLOG tags TAGS .make.state
+    .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
+    *~ *.old *.bak *.BAK *.orig *.rej _$* *$
+
+    *.org *.in .*
+  )
+  mapping = {
+    '.' => '\.',
+    '$' => '\$',
+    '#' => '\#',
+    '*' => '.*'
+  }
+  REJECT_PATTERNS = Regexp.new('\A(?:' +
+                               reject_patterns.map {|pat|
+                                 pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
+                               }.join('|') +
+                               ')\z')
+
+  def collect_filenames_auto
+    mapdir((existfiles() - hookfiles()).reject {|fname|
+             REJECT_PATTERNS =~ fname
+           })
+  end
+
+  def existfiles
+    all_files_in(curr_srcdir()) | all_files_in('.')
+  end
+
+  def hookfiles
+    %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
+      %w( config setup install clean ).map {|t| sprintf(fmt, t) }
+    }.flatten
+  end
+
+  def mapdir(filelist)
+    filelist.map {|fname|
+      if File.exist?(fname)   # objdir
+        fname
+      else                    # srcdir
+        File.join(curr_srcdir(), fname)
+      end
+    }
+  end
+
+  def ruby_extentions(dir)
+    Dir.open(dir) {|d|
+      ents = d.select {|fname| /\.#{::Config::CONFIG['DLEXT']}\z/ =~ fname }
+      if ents.empty?
+        setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
+      end
+      return ents
+    }
+  end
+
+  #
+  # TASK clean
+  #
+
+  def exec_clean
+    exec_task_traverse 'clean'
+    rm_f ConfigTable.savefile
+    rm_f 'InstalledFiles'
+  end
+
+  def clean_dir_bin(rel)
+  end
+
+  def clean_dir_lib(rel)
+  end
+
+  def clean_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    make 'clean' if File.file?('Makefile')
+  end
+
+  def clean_dir_data(rel)
+  end
+
+  #
+  # TASK distclean
+  #
+
+  def exec_distclean
+    exec_task_traverse 'distclean'
+    rm_f ConfigTable.savefile
+    rm_f 'InstalledFiles'
+  end
+
+  def distclean_dir_bin(rel)
+  end
+
+  def distclean_dir_lib(rel)
+  end
+
+  def distclean_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    make 'distclean' if File.file?('Makefile')
+  end
+
+  #
+  # lib
+  #
+
+  def exec_task_traverse(task)
+    run_hook "pre-#{task}"
+    FILETYPES.each do |type|
+      if config('without-ext') == 'yes' and type == 'ext'
+        $stderr.puts 'skipping ext/* by user option' if verbose?
+        next
+      end
+      traverse task, type, "#{task}_dir_#{type}"
+    end
+    run_hook "post-#{task}"
+  end
+
+  def traverse(task, rel, mid)
+    dive_into(rel) {
+      run_hook "pre-#{task}"
+      __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
+      all_dirs_in(curr_srcdir()).each do |d|
+        traverse task, "#{rel}/#{d}", mid
+      end
+      run_hook "post-#{task}"
+    }
+  end
+
+  def dive_into(rel)
+    return unless File.dir?("#{@srcdir}/#{rel}")
+
+    dir = File.basename(rel)
+    Dir.mkdir dir unless File.dir?(dir)
+    prevdir = Dir.pwd
+    Dir.chdir dir
+    $stderr.puts '---> ' + rel if verbose?
+    @currdir = rel
+    yield
+    Dir.chdir prevdir
+    $stderr.puts '<--- ' + rel if verbose?
+    @currdir = File.dirname(rel)
+  end
+
+end
+
+
+if $0 == __FILE__
+  begin
+    if multipackage_install?
+      ToplevelInstallerMulti.invoke
+    else
+      ToplevelInstaller.invoke
+    end
+  rescue SetupError
+    raise if $DEBUG
+    $stderr.puts $!.message
+    $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
+    exit 1
+  end
+end
diff --git a/test/.test_ws.rb.swp b/test/.test_ws.rb.swp
new file mode 100644
index 0000000..84dbb1d
--- /dev/null
+++ b/test/.test_ws.rb.swp
Binary files differ
diff --git a/test/test_http11.rb b/test/test_http11.rb
new file mode 100644
index 0000000..8f07900
--- /dev/null
+++ b/test/test_http11.rb
@@ -0,0 +1,31 @@
+require 'test/unit'
+require 'http11'
+
+
+class HttpParserTest < Test::Unit::TestCase
+    
+    def test_parse_simple
+            parser = HttpParser.new
+            req = {}
+            http = "GET / HTTP/1.1\r\n\r\n"
+            nread = parser.execute(req, http);
+            assert nread == http.length, "Failed to parse the full HTTP request"
+            assert parser.finished?, "Parser didn't finish"
+            assert !parser.error?, "Parser had error"
+            assert nread == parser.nread, "Number read returned from execute does not match"
+            parser.reset
+            assert parser.nread == 0, "Number read after reset should be 0"
+    end
+    
+    
+    def test_parse_error
+        parser = HttpParser.new
+        req = {}
+        bad_http = "GET / SsUTF/1.1"
+        nread = parser.execute(req, bad_http)
+        assert nread < bad_http.length, "Number read should be less than total on error"
+        assert !parser.finished?, "Parser shouldn't be finished"
+        assert parser.error?, "Parser SHOULD have error"
+    end
+end
+
diff --git a/test/test_uriclassifier.rb b/test/test_uriclassifier.rb
new file mode 100644
index 0000000..ae5df1d
--- /dev/null
+++ b/test/test_uriclassifier.rb
@@ -0,0 +1,104 @@
+require 'test/unit'
+require 'net/http'
+require 'mongrel'
+require 'benchmark'
+
+include Mongrel
+
+class URIClassifierTest < Test::Unit::TestCase
+
+  def test_uri_finding
+    u = URIClassifier.new
+    u.register("/test", 1)
+    
+    sn,pi,val = u.resolve("/test")
+    assert val != nil, "didn't resolve"
+    assert_equal 1, val, "wrong value"
+    assert_equal "/test",sn, "wrong SCRIPT_NAME"
+  end
+
+
+  def test_uri_prefix_ops
+    test = "/pre/fix/test"
+    prefix = "/pre"
+
+    u = URIClassifier.new
+    u.register(prefix,1)
+
+    sn,pi,val = u.resolve(test)
+    assert val != nil, "didn't resolve"
+    assert_equal prefix,sn, "wrong script name"
+    assert_equal test[sn.length .. -1],pi, "wrong path info"
+  end
+
+  def test_not_finding
+    test = "/cant/find/me"
+    u = URIClassifier.new
+    u.register(test, 1)
+
+    sn,pi,val = u.resolve("/nope/not/here")
+    assert_equal nil,sn, "shouldn't be found"
+    assert_equal nil,pi, "shouldn't be found"
+    assert_equal nil,val, "shouldn't be found"
+  end
+
+  def test_exceptions
+    u = URIClassifier.new
+
+    u.register("test", 1)
+    
+    failed = false
+    begin
+      u.register("test", 1)
+    rescue => e
+      failed = true
+    end
+
+    assert failed, "it didn't fail as expected"
+
+    failed = false
+    begin
+      u.register("", 1)
+    rescue => e
+      failed = true
+    end
+
+    assert failed, "it didn't fail as expected"
+  end
+
+
+  def test_register_unregister
+    u = URIClassifier.new
+    
+    100.times do
+      u.register("stuff", 1)
+      val = u.unregister("stuff")
+      assert_equal 1,val, "didn't get the right return value"
+    end
+
+    u.register("things",1)
+    sn,pi,val = u.resolve("things")
+    assert_equal 1, val, "result doesn't match"
+
+    u.unregister("things")
+    sn,pi,val = u.resolve("things")
+    assert_equal nil, val, "result should be nil"
+
+  end
+
+
+  def test_performance
+    count = 8500
+    u = URIClassifier.new
+    u.register("stuff",1)
+
+    res = Benchmark.measure {   count.times { u.resolve("stuff") } }
+    
+    reg_unreg = Benchmark.measure { count.times { u.register("other",1); u.unregister("other"); } }
+
+    puts "\nRESOLVE(#{count}): #{res}"
+    puts "REG_UNREG(#{count}): #{reg_unreg}"
+  end
+      
+end
+
diff --git a/test/test_ws.rb b/test/test_ws.rb
new file mode 100644
index 0000000..dd7fa77
--- /dev/null
+++ b/test/test_ws.rb
@@ -0,0 +1,33 @@
+require 'test/unit'
+require 'net/http'
+require 'mongrel'
+require 'timeout'
+
+include Mongrel;
+
+class TestHandler < Mongrel::HttpHandler
+    attr_reader :ran_test
+    
+    def process(request, response)
+        @ran_test = true
+        response.socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nhello!\n")
+    end
+end
+                
+
+class WSTest < Test::Unit::TestCase
+
+    def test_simple_server
+        h = HttpServer.new("0.0.0.0", 9998)
+        tester = TestHandler.new
+        h.register("/test", tester)
+        h.run
+
+        sleep(1)
+        res = Net::HTTP.get(URI.parse('http://localhost:9998/test'))
+        assert res != nil, "Didn't get a response"
+        assert tester.ran_test, "Handler didn't really run"
+    end
+
+end
+
diff --git a/tools/rakehelp.rb b/tools/rakehelp.rb
new file mode 100644
index 0000000..6996658
--- /dev/null
+++ b/tools/rakehelp.rb
@@ -0,0 +1,99 @@
+
+def make(makedir)
+    Dir.chdir(makedir) do
+        sh 'make'
+    end
+end
+
+
+def extconf(dir)
+    Dir.chdir(dir) do ruby "extconf.rb" end
+end
+
+
+def setup_tests
+    Rake::TestTask.new do |t|
+        t.libs << "test"
+        t.test_files = FileList['test/test*.rb']
+        t.verbose = true
+    end
+end
+
+
+def setup_clean otherfiles
+    files = ['build/*', '**/*.o', '**/*.so', '**/*.a', 'lib/*-*', '**/*.log'] + otherfiles
+    CLEAN.include(files)
+end
+
+
+def setup_rdoc files
+    Rake::RDocTask.new do |rdoc|
+        rdoc.rdoc_dir = 'doc/rdoc'
+        rdoc.options << '--line-numbers'
+        rdoc.rdoc_files.add(files)
+    end
+end
+
+
+def setup_extension(dir, extension)
+    ext = "ext/#{dir}"
+    ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}"
+    ext_files = FileList[
+    "#{ext}/*.c",
+    "#{ext}/*.h",
+    "#{ext}/extconf.rb",
+    "#{ext}/Makefile",
+    "lib"
+    ]
+    
+    task "lib" do
+        directory "lib"
+    end
+
+    desc "Builds just the #{extension} extension"
+    task extension.to_sym => ["#{ext}/Makefile", ext_so ]
+
+    file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
+        extconf "#{ext}"
+    end
+
+    file ext_so => ext_files do
+        make "#{ext}"
+        cp ext_so, "lib"
+    end
+end
+
+
+def setup_gem(pkg_name, pkg_version, author, summary, executables, test_file)
+    pkg_version = pkg_version
+    pkg_name    = pkg_name
+    pkg_file_name = "#{pkg_name}-#{pkg_version}"
+
+    spec = Gem::Specification.new do |s|
+        s.name = pkg_name
+        s.version = pkg_version
+        s.platform = Gem::Platform::RUBY
+        s.author = author
+        s.summary = summary
+        s.test_file = test_file
+        s.has_rdoc = true
+        s.extra_rdoc_files = [ "README" ]
+
+        s.files = %w(COPYING LICENSE ext/http11/MANIFEST README Rakefile setup.rb) +
+        Dir.glob("{bin,doc,test,lib}/**/*") +
+        Dir.glob("ext/**/*.{h,c,rb}") +
+        Dir.glob("examples/**/*.rb") +
+        Dir.glob("tools/*.rb")
+    
+        s.require_path = "lib"
+        s.extensions = FileList["ext/**/extconf.rb"].to_a
+
+        s.executables = executables
+        s.bindir = "bin"
+    end
+
+    Rake::GemPackageTask.new(spec) do |p|
+        p.gem_spec = spec
+        p.need_tar = true
+    end
+end