Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'release/v1.8.0'

Conflicts:
	docs/manual/deploying.tex
	docs/manual/hacking.tex
	docs/manual/installing.tex
	docs/manual/managing.tex
	docs/manual/preamble.tex
	src/io.c
  • Loading branch information...
commit 1a1ec9bd69d37924ea0b1cb89c21faa8834df256 2 parents 5d60d87 + 6f4b788
Guillermo O. Freschi Tordek authored
Showing with 24,597 additions and 3,515 deletions.
  1. +5 −0 .dexy
  2. +11 −1 .gitignore
  3. +13 −4 Makefile
  4. +7 −0 README
  5. +1 −2  README.md
  6. +0 −6 docs/manual/.dexy
  7. +2 −3 docs/manual/Makefile
  8. +4 −0 docs/manual/book.cfg
  9. +18 −18 docs/manual/deploying.tex
  10. +65 −8 docs/manual/hacking.tex
  11. +25 −0 docs/manual/inputs/filters.conf
  12. +0 −2  docs/manual/inputs/install_procer.sh
  13. +5 −0 docs/manual/inputs/make_deployment_directories.sh
  14. +24 −0 docs/manual/inputs/makecert.sh
  15. +20 −0 docs/manual/inputs/mini_ssl_settings.conf
  16. +1 −1  docs/manual/inputs/procer_handlertest_run.sh
  17. +1 −1  docs/manual/inputs/procer_mp3stream_run.sh
  18. +1 −1  docs/manual/inputs/procer_script_for_chat_demo.sh
  19. +1 −1  docs/manual/inputs/procer_web_run.sh
  20. +20 −6 docs/manual/installing.tex
  21. +1 −1  docs/manual/introduction.tex
  22. +118 −11 docs/manual/managing.tex
  23. +1 −1  docs/manual/preamble.tex
  24. 0  docs/ru/.nodexy
  25. +2 −2 docs/ru/manual/book.wiki
  26. +3 −3 docs/ru/manual/deploying.tex
  27. +12 −0 docs/site/Makefile
  28. BIN  docs/site/assets/assets/aj-125x125.gif
  29. BIN  docs/site/assets/assets/icons/automation.png
  30. BIN  docs/site/assets/assets/icons/book_info.png
  31. BIN  docs/site/assets/assets/icons/comment_blue.gif
  32. BIN  docs/site/assets/assets/icons/comment_new.gif
  33. BIN  docs/site/assets/assets/icons/date.gif
  34. BIN  docs/site/assets/assets/icons/icon-16x16.png
  35. BIN  docs/site/assets/assets/icons/icon-32x32.png
  36. BIN  docs/site/assets/assets/icons/icon_info.gif
  37. BIN  docs/site/assets/assets/icons/languages.png
  38. BIN  docs/site/assets/assets/icons/modern_design.png
  39. BIN  docs/site/assets/assets/icons/people.png
  40. BIN  docs/site/assets/assets/icons/protocols.png
  41. BIN  docs/site/assets/assets/icons/source_clone.png
  42. BIN  docs/site/assets/assets/placeholder-50x50.png
  43. BIN  docs/site/assets/assets/placeholder-520x340.png
  44. BIN  docs/site/assets/assets/placeholder-58x58.png
  45. BIN  docs/site/assets/assets/placeholder-615x140.png
  46. BIN  docs/site/assets/assets/placeholder-840x320.png
  47. BIN  docs/site/assets/assets/tf-125x125.gif
  48. +2,699 −0 docs/site/assets/css/light-green.css
  49. BIN  docs/site/assets/images/light-green/ajax-loader.gif
  50. BIN  docs/site/assets/images/light-green/ajax-loader2.gif
  51. BIN  docs/site/assets/images/light-green/arrow-left.png
  52. BIN  docs/site/assets/images/light-green/background-texture.png
  53. BIN  docs/site/assets/images/light-green/box-info-icon.png
  54. BIN  docs/site/assets/images/light-green/box-resource-icon.png
  55. BIN  docs/site/assets/images/light-green/box-sprite.png
  56. BIN  docs/site/assets/images/light-green/box-warning-icon.png
  57. BIN  docs/site/assets/images/light-green/comment-bg.png
  58. BIN  docs/site/assets/images/light-green/comment-child-bg.png
  59. BIN  docs/site/assets/images/light-green/content-texture-top.png
  60. BIN  docs/site/assets/images/light-green/dropdown-arrow.png
  61. BIN  docs/site/assets/images/light-green/faq-closed.png
  62. BIN  docs/site/assets/images/light-green/faq-opened.png
  63. BIN  docs/site/assets/images/light-green/footer-texture-top.png
  64. BIN  docs/site/assets/images/light-green/header-texture.png
  65. BIN  docs/site/assets/images/light-green/icons.png
  66. BIN  docs/site/assets/images/light-green/image-overlay.png
  67. BIN  docs/site/assets/images/light-green/list-item-current.png
  68. BIN  docs/site/assets/images/light-green/list-item.png
  69. BIN  docs/site/assets/images/light-green/logo-small.png
  70. BIN  docs/site/assets/images/light-green/logo.png
  71. BIN  docs/site/assets/images/light-green/quote.png
  72. BIN  docs/site/assets/images/light-green/wiki-list-bg.png
  73. +315 −0 docs/site/assets/js/forms.js
  74. +12 −0 docs/site/assets/js/iefixes.js
  75. +18 −0 docs/site/assets/js/jquery-1.6.1.min.js
  76. +871 −0 docs/site/assets/js/royal.js
  77. +3 −0  docs/site/config.json
  78. +7 −0 docs/site/gensite.lua
  79. +163 −0 docs/site/model/site.lua
  80. +142 −0 docs/site/src/blog/JUL_04_2011.md
  81. +24 −0 docs/site/src/blog/JUL_13_2011.md
  82. +8 −0 docs/site/src/blog/index.json
  83. +4 −0 docs/site/src/contact.json
  84. +44 −0 docs/site/src/downloads/index.json
  85. +10 −0 docs/site/src/features/architectures.md
  86. +39 −0 docs/site/src/features/design.md
  87. +8 −0 docs/site/src/features/index.json
  88. +52 −0 docs/site/src/features/languages.md
  89. +26 −0 docs/site/src/features/protocols.md
  90. +3 −0  docs/site/src/index.json
  91. +140 −0 docs/site/src/wiki/contributor_instructions.md
  92. +95 −0 docs/site/src/wiki/design_criticisms.md
  93. +9 −0 docs/site/src/wiki/index.json
  94. +42 −0 docs/site/src/wiki/license.md
  95. +103 −0 docs/site/src/wiki/quick_start.md
  96. +40 −0 docs/site/views/blog-post.html
  97. +57 −0 docs/site/views/blog.html
  98. +53 −0 docs/site/views/contact.html
  99. +45 −0 docs/site/views/downloads.html
  100. +33 −0 docs/site/views/features-post.html
  101. +151 −0 docs/site/views/features.html
  102. +35 −0 docs/site/views/footer.html
  103. +81 −0 docs/site/views/header.html
  104. +189 −0 docs/site/views/index.html
  105. +26 −0 docs/site/views/sponsors.html
  106. +13 −0 docs/site/views/sponsors_side.html
  107. +12 −0 docs/site/views/top.html
  108. +35 −0 docs/site/views/wiki-post.html
  109. +40 −0 docs/site/views/wiki.html
  110. +3 −0  examples/configs/.dexy
  111. +25 −0 examples/configs/filters.conf
  112. +2 −1  examples/configs/mongrel2.conf
  113. +4 −1 examples/http_0mq/http.py
  114. +0 −15 examples/procer/Makefile
  115. +43 −1 examples/python/mongrel2/handler.py
  116. +1 −1  examples/python/mongrel2/sql/config.sql
  117. +5 −0 examples/python/mongrel2/tnetstrings.py
  118. +55 −0 examples/ws/mongrel2.conf
  119. +121 −0 examples/ws/python/echo.py
  120. +22 −0 examples/ws/python/wsutil.py
  121. +7 −2 src/adt/darray.c
  122. +9 −3 src/adt/darray.h
  123. +2 −0  src/adt/dict.c
  124. +2 −0  src/adt/hash.c
  125. +271 −0 src/adt/radixmap.c
  126. +35 −0 src/adt/radixmap.h
  127. +1 −3 src/adt/tst.c
  128. +12 −12 src/bstr/bsafe.c
  129. +4 −4 src/bstr/bstraux.c
  130. +42 −0 src/config/config.c
  131. +6 −1 src/config/config.sql
  132. +8 −1 src/config/module.c
  133. +1 −0  src/config/module.h
  134. +329 −45 src/connection.c
  135. +12 −1 src/connection.h
  136. +34 −12 src/control.c
  137. +13 −0 src/dbg.c
  138. +9 −7 src/dbg.h
  139. +117 −16 src/dir.c
  140. +0 −1  src/dir.h
  141. +2 −1  src/events.h
  142. +14 −7 src/filter.c
  143. +6 −10 src/filter.h
  144. +37 −34 src/handler.c
  145. +2 −2 src/handler_parser.c
  146. +1 −1  src/handler_parser.rl
  147. +1 −0  src/headers.c
  148. +1 −0  src/headers.h
  149. +12 −0 src/host.c
  150. +5,069 −822 src/http11/http11_parser.c
  151. +109 −38 src/http11/http11_parser.rl
  152. +219 −111 src/io.c
  153. +3 −0  src/io.h
  154. +9 −7 src/log.c
  155. +19 −1 src/mime.c
  156. +112 −58 src/mongrel2.c
  157. +21 −24 src/pattern.c
  158. +29 −1 src/polarssl/CMakeLists.txt
  159. +318 −60 src/polarssl/LICENSE
  160. +28 −14 src/polarssl/Makefile
  161. +182 −10 src/polarssl/aes.c
  162. +44 −7 src/polarssl/aes.h
  163. +6 −4 src/polarssl/arc4.c
  164. +6 −2 src/polarssl/arc4.h
  165. +244 −0 src/polarssl/asn1.h
  166. +260 −0 src/polarssl/asn1parse.c
  167. +7 −7 src/polarssl/base64.c
  168. +10 −6 src/polarssl/base64.h
  169. +309 −236 src/polarssl/bignum.c
  170. +169 −70 src/polarssl/bignum.h
  171. +12 −6 src/polarssl/bn_mul.h
  172. +179 −11 src/polarssl/camellia.c
  173. +44 −7 src/polarssl/camellia.h
  174. +7 −0 src/polarssl/certs.c
  175. +3 −0  src/polarssl/certs.h
  176. +527 −0 src/polarssl/cipher.c
  177. +456 −0 src/polarssl/cipher.h
  178. +552 −0 src/polarssl/cipher_wrap.c
  179. +91 −0 src/polarssl/cipher_wrap.h
  180. +410 −58 src/polarssl/config.h
  181. +566 −0 src/polarssl/ctr_drbg.c
  182. +228 −0 src/polarssl/ctr_drbg.h
  183. +45 −19 src/polarssl/debug.c
  184. +9 −7 src/polarssl/debug.h
  185. +110 −12 src/polarssl/des.c
  186. +58 −9 src/polarssl/des.h
  187. +25 −33 src/polarssl/dhm.c
  188. +25 −15 src/polarssl/dhm.h
  189. +204 −0 src/polarssl/entropy.c
  190. +150 −0 src/polarssl/entropy.h
  191. +136 −0 src/polarssl/entropy_poll.c
  192. +75 −0 src/polarssl/entropy_poll.h
  193. +512 −0 src/polarssl/error.c
  194. +101 −0 src/polarssl/error.h
  195. +21 −56 src/polarssl/havege.c
  196. +7 −1 src/polarssl/havege.h
  197. +298 −0 src/polarssl/md.c
  198. +354 −0 src/polarssl/md.h
  199. +22 −19 src/polarssl/md2.c
  200. +16 −11 src/polarssl/md2.h
  201. +16 −13 src/polarssl/md4.c
  202. +13 −8 src/polarssl/md4.h
  203. +16 −13 src/polarssl/md5.c
  204. +13 −8 src/polarssl/md5.h
  205. +715 −0 src/polarssl/md_wrap.c
  206. +64 −0 src/polarssl/md_wrap.h
  207. +14 −17 src/polarssl/net.c
  208. +22 −15 src/polarssl/net.h
  209. +6 −4 src/polarssl/openssl.h
  210. +3 −5 src/polarssl/padlock.c
  211. +6 −4 src/polarssl/padlock.h
  212. +352 −0 src/polarssl/pem.c
  213. +100 −0 src/polarssl/pem.h
  214. +238 −0 src/polarssl/pkcs11.c
  215. +126 −0 src/polarssl/pkcs11.h
  216. +536 −148 src/polarssl/rsa.c
  217. +83 −64 src/polarssl/rsa.h
  218. +16 −13 src/polarssl/sha1.c
  219. +13 −8 src/polarssl/sha1.h
  220. +16 −13 src/polarssl/sha2.c
  221. +13 −8 src/polarssl/sha2.h
  222. +34 −31 src/polarssl/sha4.c
  223. +17 −12 src/polarssl/sha4.h
  224. +201 −74 src/polarssl/ssl.h
  225. +91 −47 src/polarssl/ssl_cli.c
  226. +141 −64 src/polarssl/ssl_srv.c
  227. +270 −89 src/polarssl/ssl_tls.c
  228. +17 −4 src/polarssl/timing.c
  229. +4 −2 src/polarssl/timing.h
  230. +15 −12 src/polarssl/version.h
  231. +415 −133 src/polarssl/x509.h
  232. +1,316 −710 src/polarssl/x509parse.c
Sorry, we could not display the entire diff because too many files (349) changed.
5 .dexy
View
@@ -1,2 +1,7 @@
{
+ "*.tex|jinja" : { "allinputs" : true },
+ "*.py|pyg|l": {},
+ "*.sh|pyg|l": {},
+ "*.conf|dexy": {},
+ "*.cfg": {}
}
12 .gitignore
View
@@ -1,5 +1,7 @@
bin/
+tools/config_modules/mongo-c-driver/
+
# Compiled Object files
*.slo
*.lo
@@ -14,7 +16,6 @@ bin/
*.a
.*.sw*
tests/*_tests
-tests/*_tests.*/*
tests/config.sqlite
tests/empty.sqlite
*.log
@@ -25,13 +26,22 @@ tools/lemon/lemon
tools/m2sh/build/
tools/m2sh/tests/*_tests
tools/m2sh/tests/tests.log
+tools/procer/procer
run/*
logs/*
tmp/*
+# dexy crap
+output/
+output-long/
+artifacts/
+
#Coverage generated files
*.zcov
tests/coverage
*.gcno
*.gcda
*.dSYM
+
+#OSX garbage
+.DS_Store
17 Makefile
View
@@ -16,7 +16,7 @@ TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,${TEST_SRC})
MAKEOPTS=OPTFLAGS="${NOEXTCFLAGS} ${OPTFLAGS}" OPTLIBS="${OPTLIBS}" LIBS="${LIBS}" DESTDIR="${DESTDIR}" PREFIX="${PREFIX}"
-all: bin/mongrel2 tests m2sh
+all: bin/mongrel2 tests m2sh procer
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS) -D_FILE_OFFSET_BITS=64
dev: all
@@ -50,6 +50,7 @@ clean:
${MAKE} -C tools/filters OPTLIB=${OPTLIB} clean
${MAKE} -C tests/filters OPTLIB=${OPTLIB} clean
${MAKE} -C tools/config_modules OPTLIB=${OPTLIB} clean
+ ${MAKE} -C tools/procer OPTLIB=${OPTLIB} clean
pristine: clean
sudo rm -rf examples/python/build examples/python/dist examples/python/m2py.egg-info
@@ -60,6 +61,7 @@ pristine: clean
rm -f logs/*
rm -f run/*
${MAKE} -C tools/m2sh pristine
+ ${MAKE} -C tools/procer pristine
.PHONY: tests
tests: tests/config.sqlite ${TESTS} test_filters filters config_modules
@@ -84,6 +86,9 @@ check:
m2sh:
${MAKE} ${MAKEOPTS} -C tools/m2sh all
+procer:
+ ${MAKE} ${MAKEOPTS} -C tools/procer all
+
test_filters: build/libm2.a
${MAKE} ${MAKEOPTS} -C tests/filters all
@@ -93,12 +98,15 @@ filters: build/libm2.a
config_modules: build/libm2.a
${MAKE} ${MAKEOPTS} -C tools/config_modules all
+# Try to install first before creating target directory and trying again
install: all
- install -d $(DESTDIR)/$(PREFIX)/bin/
- install bin/mongrel2 $(DESTDIR)/$(PREFIX)/bin/
+ install bin/mongrel2 $(DESTDIR)/$(PREFIX)/bin/ \
+ || ( install -d $(DESTDIR)/$(PREFIX)/bin/ \
+ && install bin/mongrel2 $(DESTDIR)/$(PREFIX)/bin/ )
${MAKE} ${MAKEOPTS} -C tools/m2sh install
${MAKE} ${MAKEOPTS} -C tools/config_modules install
${MAKE} ${MAKEOPTS} -C tools/filters install
+ ${MAKE} ${MAKEOPTS} -C tools/procer install
examples/python/mongrel2/sql/config.sql: src/config/config.sql src/config/mimetypes.sql
cat src/config/config.sql src/config/mimetypes.sql > $@
@@ -110,7 +118,7 @@ ragel:
ragel -G2 src/http11/httpclient_parser.rl
valgrind:
- valgrind --leak-check=full --show-reachable=yes --log-file=valgrind.log --suppressions=tests/valgrind.sup ./bin/mongrel2 tests/config.sqlite localhost
+ VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" ${MAKE}
%.o: %.S
$(CC) $(CFLAGS) -c $< -o $@
@@ -163,6 +171,7 @@ openbsd: all
solaris: OPTFLAGS += -I/usr/local/include
solaris: OPTLIBS += -L/usr/local/lib -R/usr/local/lib -lsocket -lnsl -lsendfile
+solaris: OPTLIBS += -L/lib -R/lib
solaris: all
7 README
View
@@ -0,0 +1,7 @@
+This site design is *not* licensed under the BSD license. It is
+actually purchased from:
+
+http://themeforest.net/item/cheerapp-premium-app-html-template/286942
+
+and therefore you may NOT copy it.
+
3  README.md
View
@@ -39,7 +39,6 @@ Mongrel2 is now 1.7.5 as of *Wed Jun 22 09:23:16 PDT 2011*:
Documentation
-------------
-There is a full manual available at [mongrel2.org](http://mongrel2.org/static/mongrel2-manual.html)
-covering every aspect of Mongrel2, with more as we write features.
+Go to [http://mongrel2.org](http://mongrel2.org) for more information.
6 docs/manual/.dexy
View
@@ -1,6 +0,0 @@
-{
- "*.tex|jinja" : { "allinputs" : true },
- "*.py|pyg|l": {},
- "*.sh|pyg|l": {},
- "*.conf|dexy": {}
-}
5 docs/manual/Makefile
View
@@ -4,8 +4,7 @@ WEBSITE=$(USER)@mongrel2.org:/var/www/mongrel2.org/static/
FINAL=book-final
draft: book-final.dvi
- htlatex book-final.tex
- tidy -quiet -ashtml -omit -ic -m book-final.html || true
+ htlatex book-final.tex "book,index=1,2,next,fn-in"
book-final.dvi:
cp $(SOURCE).tex book-final.tex
@@ -26,5 +25,5 @@ release: clean book-final.pdf draft book-final.pdf sync
sync:
rsync -vz $(FINAL).pdf $(WEBSITE)/mongrel2-manual.pdf
rsync -vz $(FINAL).html $(WEBSITE)/mongrel2-manual.html
- rsync -vz $(FINAL).css $(FINAL)[0-9]*.html $(WEBSITE)/
+ rsync -vz $(FINAL).css $(FINAL)*.html $(WEBSITE)/
4 docs/manual/book.cfg
View
@@ -0,0 +1,4 @@
+\Preamble{html}
+\begin{document}
+\Css{}
+\EndPreamble
36 docs/manual/deploying.tex
View
@@ -78,7 +78,7 @@ \subsection{Introducing procer}
expected to be the one true init, poorly documented, not maintained, and definitely not
going to work for this manual. My only choice was to shave a yak and write my own.
-The end result is \shell{procer}, which lives in \file{examples/procer} and does
+The end result is \shell{procer}, which lives in \file{tools/procer} and does
most of what you need in a USPM. It works a lot like daemontools or minit, but
is much simpler, with these differences:
@@ -129,11 +129,11 @@ \subsection{Introducing procer}
\subsection{Installing procer}
Installing procer is very easy. It's a single little binary and it lives in
-\file{examples/procer} in the Mongrel2 source. Here's how you'd install it
-totally from scratch as if you hadn't even build Mongrel2 yet:
+\file{tools/procer} in the Mongrel2 source. Here's how you'd install it
+totally from scratch as if you hadn't even built Mongrel2 yet:
\begin{code}{Install procer}
-<< d['/docs/manual/inputs/install_procer.sh|pyg|l'] >>
+<< d['inputs/install_procer.sh|pyg|l'] >>
\end{code}
That's the entire install process, and now procer is in \file{/usr/local/bin}
@@ -169,7 +169,7 @@ \section{Step 1: The Deployment Area}
but feel free to change this up later if you find a better way.
\begin{code}{Make Deployment Directories}
-<< d['/docs/manual/inputs/make_deployment_directories.sh|pyg|l'] >>
+<< d['inputs/make_deployment_directories.sh|pyg|l'] >>
\end{code}
Hopefully, you're starting to see how you could easily automate this so that you don't
@@ -218,7 +218,7 @@ \section{Step 2: The mongrel2.org Configuration}
did with these commands:
\begin{code}{Testing The Initial Configuration}
-<< d['/docs/manual/inputs/testing_initial_config.sh|pyg|l'] >>
+<< d['inputs/testing_initial_config.sh|pyg|l'] >>
\end{code}
That's enough to make sure it runs, but you've got nothing running,
@@ -240,13 +240,13 @@ \section{Step 3: Setup procer}
and make sure procer can run everything:
\begin{code}{Skeleton procer Setup}
-<< d['/docs/manual/inputs/skeleton_procer_setup.sh|pyg|l'] >>
+<< d['inputs/skeleton_procer_setup.sh|pyg|l'] >>
\end{code}
With all of that, you can then try to run \shell{procer} to watch
it fail but still try to run everything:
-<< d['/docs/manual/inputs/run_procer_first_time.sh|pyg|l'] >>
+<< d['inputs/run_procer_first_time.sh|pyg|l'] >>
This is assuming that you are still in the \file{profiles} directory.
You should see the file \file{error.log} get created and
@@ -290,7 +290,7 @@ \section{Step 3: Setup procer}
Next up, let's get Mongrel2 running inside \shell{procer}:
\begin{code}{procer Config For Mongrel2}
-<< d['/docs/manual/inputs/procer_config_for_mongrel2.sh|pyg|l'] >>
+<< d['inputs/procer_config_for_mongrel2.sh|pyg|l'] >>
\end{code}
Obviously, you don't have to use a series of \shell{echo} commands to
@@ -303,7 +303,7 @@ \section{Step 3: Setup procer}
\begin{code}{Using procer To Run Mongrel2}
-<< d['/docs/manual/inputs/using_procer_to_run_mongrel2.sh|pyg|l'] >>
+<< d['inputs/using_procer_to_run_mongrel2.sh|pyg|l'] >>
\end{code}
To watch \shell{procer} in action, try doing \shell{m2sh stop -db config.sqlite
@@ -322,7 +322,7 @@ \subsection{The Python Examples}
you will change \file{profiles/chat/run} to be like this:
\begin{code}{Run Script For Chat Demo}
-<< d['/docs/manual/inputs/procer_script_for_chat_demo.sh|pyg|l'] >>
+<< d['inputs/procer_script_for_chat_demo.sh|pyg|l'] >>
\end{code}
This little script uses some funky features you might not be familiar
@@ -345,13 +345,13 @@ \subsection{The Python Examples}
When you run this manually, you should see something like this:
-<< d['/docs/manual/inputs/run_procer_chat_demo.sh|pyg|l'] >>
+<< d['inputs/run_procer_chat_demo.sh|pyg|l'] >>
After all that, you can then try out \shell{procer} again to see if it
properly runs the chat demo as well as mongrel2:
\begin{code}{Running procer With Chat Demo}
-<< d['/docs/manual/inputs/running_procer_with_chat_demo.sh|pyg|l'] >>
+<< d['inputs/running_procer_with_chat_demo.sh|pyg|l'] >>
\end{code}
If you go look at \file{profiles/error.log}, you'll see that \shell{procer}
@@ -365,17 +365,17 @@ \subsection{The Python Examples}
\file{profiles/handlertest/run}
\hrule
-<< d['/docs/manual/inputs/procer_handlertest_run.sh|pyg|l'] >>
+<< d['inputs/procer_handlertest_run.sh|pyg|l'] >>
\file{profiles/mp3stream/run}
\hrule
-<< d['/docs/manual/inputs/procer_mp3stream_run.sh|pyg|l'] >>
+<< d['inputs/procer_mp3stream_run.sh|pyg|l'] >>
\file{profiles/web/run}
\hrule
-<< d['/docs/manual/inputs/procer_web_run.sh|pyg|l'] >>
+<< d['inputs/procer_web_run.sh|pyg|l'] >>
\end{code}
@@ -385,7 +385,7 @@ \subsection{Testing The New Setup}
just need to see if things work. Here's some curl commands to try:
\begin{code}{Testing With Curl}
-<< d['/docs/manual/inputs/testing_procer_setup.sh|pyg|l'] >>
+<< d['inputs/testing_procer_setup.sh|pyg|l'] >>
\end{code}
@@ -421,7 +421,7 @@ \section{Step 4: Static Content}
out the chat demo:
\begin{code}{Setting Up Static Content}
-<< d['/docs/manual/inputs/setting_up_static_content.sh|pyg|l'] >>
+<< d['inputs/setting_up_static_content.sh|pyg|l'] >>
\end{code}
If you get a good response then you should be able to go to
73 docs/manual/hacking.tex
View
@@ -337,12 +337,25 @@ \subsection{Complete Message Examples}
That's obviously a much simpler way to specify the request than all those
rules, but it also doesn't tell you why. The above description, while
-boring as hell, tells you why each of these pieces exist.
+boring as hell, tells you why each of these pieces exist. Also remember
+that this is a \emph{strict} format, so to be more precise it's:
+
+\begin{Verbatim}
+Identifier = digit+ ' '?;
+IdentList = (Identifier)**;
+Length = digit+;
+UUID = (alpha | digit | '-')+;
+Targets = Length ':' IdentList ",";
+Request = UUID ' ' Targets ' ';
+\end{Verbatim}
+
+Mongrel2 will strictly enforce this grammar and reject any 0mq messages that
+don't follow it.
To parse this in Python we simply do this:
\begin{code}{Parsing Mongrel2 Requests In Python}
-<< d['/docs/manual/inputs/parsing_mongrel2_reqs.py|pyg|l'] >>
+<< d['inputs/parsing_mongrel2_reqs.py|pyg|l'] >>
\end{code}
This is actually all of the code needed to parse a request, and is
@@ -361,7 +374,7 @@ \subsection{Complete Message Examples}
this is very easy in Python:
\begin{code}{Generating Responses}
-<< d['/docs/manual/inputs/generating_responses.py|pyg|l'] >>
+<< d['inputs/generating_responses.py|pyg|l'] >>
\end{code}
That, again, is all there is to it. The \ident{send} method is the
@@ -406,7 +419,7 @@ \subsection{TNetStrings Alternative Protocol}
\begin{code}{Parsing TNetStrings Requests In Python}
-<< d['/docs/manual/inputs/parsing_reqs_tnetstrings.py|pyg|l'] >>
+<< d['inputs/parsing_reqs_tnetstrings.py|pyg|l'] >>
\end{code}
Our tests also show that TNetStrings are a good compromise between
@@ -468,7 +481,7 @@ \section{Basic Handler Demo}
just syntactic sugar on crafting a decent HTTP response. Here's the actual method that is crafting these replies:
\begin{code}{HTTP Response Python Code}
-<< d['/docs/manual/inputs/http_response_python_code.py|pyg|l'] >>
+<< d['inputs/http_response_python_code.py|pyg|l'] >>
\end{code}
Which is then used by \ident{Connection.reply\_http} and
@@ -594,10 +607,10 @@ \section{Chat Demo}
to look:
\begin{description}
-\item [JavaScript] Look at \file{examples/chat/static/*.js} for the goodies.
+\item [JavaScript] Look at \file{/examples/chat/static/*.js} for the goodies.
The key is to see how \file{chat.js} works with the JSSocket stuff,
and then look at how I did \file{app.js} using \file{fsm.js}.
-\item [Python] Look at the \file{examples/chat/chat.py} file to see how
+\item [Python] Look at the \file{/examples/chat/chat.py} file to see how
the chat states are maintained and how messages are sent around.
\item [config] The configuration you created in the last chapter
actually works with the demo, and if you've been following along
@@ -607,6 +620,50 @@ \section{Chat Demo}
Hopefully, you can figure it out from the code, but if not, let me know.
+\section{Writing A Filter (BETA)}
+
+In Mongrel2 v1.8.0 there was a new addition of the Filter system, which
+lets you intercept the Mongrel2 state machine and fully control how it
+operates. It's still a very new feature, but there's a simple piece of
+demo code you can look at to see how they work. You should also check
+out how to configure them in the Managing section.
+
+Let's just take a look at the code to the \file{tools/filters/null.c}
+filter.
+
+
+\begin{code}{The Basic null Filter}
+<< d['/tools/filters/null.c|pyg|l'] >>
+\end{code}
+
+In this code you are basically creating a .so file that Mongrel2
+will load on the fly when told to. How it works is you make
+two functions, always named \ident{filter\_init} and \ident{filter\_transition}.
+
+The \ident{filter\_init} function sets up a simple array that lists all
+of the events (found in \ident{src/events.h}) that you want to have your
+filter triggered on. It's important that you use the \ident{Filter\_state\_list}
+function to return the actual list or else you'll get the memory allocation
+wrong.
+
+Mongrel2 will load this null.so and call the \ident{filter\_init} function
+and wire it up for each of the events you indicate. Next, when a request
+comes in, the server will go through each event that triggers, and
+call your \ident{filter\_transition} function. This function will
+get the \ident{StateEvent} that is about to happen, the \ident{Connection}
+it's happening on, and finally, the \ident{config} that the user
+set in their \file{config.sqlite} database.
+
+All your \ident{filter\_transition} function has to do is use the
+Mongrel2 APIs to do what it needs, alter the \ident{Connection} and
+work with the \ident{config} to get its work done. When it's done,
+it can then return the next state event that Mongrel2 should work
+with instead of what you were handed (or, just return the same one
+if you aren't changing how Mongrel2 works).
+
+That's all there is to it for now. Later releases will start having
+more filters that you can load and look at the example code to try.
+
\section{Other Language APIs}
There's at least 10 langauges available for Mongrel2, so check out the
@@ -685,7 +742,7 @@ \section{Config From Anything: Experimental}
fourth parameter to the \file{mongrel2} executable:
\begin{code}{Loading The null Config}
-<< d['/docs/manual/inputs/null_config_run.sh|pyg|l'] >>
+<< d['inputs/null_config_run.sh|pyg|l'] >>
\end{code}
In this run, Mongrel2 detected that you gave it a fourth option and
25 docs/manual/inputs/filters.conf
View
@@ -0,0 +1,25 @@
+null = Filter(name="/usr/local/lib/mongrel2/filters/null.so", settings={
+ "extensions": ["*.html", "*.txt"],
+ "min_size": 1000
+ })
+
+main = Server(
+ uuid="f400bf85-4538-4f7a-8908-67e313d515c2",
+ access_log="/logs/access.log",
+ error_log="/logs/error.log",
+ chroot="./",
+ default_host="localhost",
+ name="test",
+ pid_file="/run/mongrel2.pid",
+ port=6767,
+ hosts = [
+ Host(name="localhost", routes={
+ '/tests/': Dir(base='tests/', index_file='index.html',
+ default_ctype='text/plain')
+ '/nulltest/': Proxy(addr='127.0.0.1', port=8080)
+ })
+ ]
+ filters = [null]
+)
+
+servers = [main]
2  docs/manual/inputs/install_procer.sh
View
@@ -1,4 +1,2 @@
cd projects/mongrel2
make clean all && sudo make install
-cd examples/procer
-make clean all && sudo make install
5 docs/manual/inputs/make_deployment_directories.sh
View
@@ -8,6 +8,11 @@ cd deployment/
# fill it with the directories we need
mkdir run tmp logs static profiles
+# Note: On some systems zeromq needs access to /proc from
+# the chroot - on Linux this command should do it (make
+# sure you mount it at boot time as well):
+## mkdir -p proc && sudo mount --bind /proc proc
+
# create the procer profile dirs for each thing
cd profiles/
mkdir chat mp3stream handlertest web mongrel2
24 docs/manual/inputs/makecert.sh
View
@@ -0,0 +1,24 @@
+# First make a certs directory
+
+mkdir certs
+
+# list out your servers so you can get the UUID
+m2sh servers
+
+# go into the certs directory
+
+cd certs
+
+# make a self-signed weak cert to play with
+openssl genrsa -des3 -out server.key 512
+openssl req -new -key server.key -out server.csr
+cp server.key server.key.org
+openssl rsa -in server.key.org -out server.key
+openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
+
+# finally, copy the sesrver.crt and server.key files over to the UUID for that
+# server configuration in your mongrel2.conf
+
+mv server.crt 2f62bd5-9e59-49cd-993c-3b6013c28f05.crt
+mv server.key 2f62bd5-9e59-49cd-993c-3b6013c28f05.key
+
20 docs/manual/inputs/mini_ssl_settings.conf
View
@@ -0,0 +1,20 @@
+main = Server(
+ uuid="2f62bd5-9e59-49cd-993c-3b6013c28f05",
+ use_ssl=1,
+ access_log="/logs/access.log",
+ error_log="/logs/error.log",
+ chroot="./",
+ pid_file="/run/mongrel2.pid",
+ default_host="mongrel2.org",
+ name="main",
+ port=6767,
+ hosts=[mysite]
+)
+
+settings = {
+ "certdir": "./certs/"
+ "ssl_ciphers": "SSL_RSA_RC4_128_SHA"
+}
+
+servers = [main]
+
2  docs/manual/inputs/procer_handlertest_run.sh
View
@@ -7,6 +7,6 @@ SOURCE=/home/YOU/projects/mongrel2
cd $SOURCE/examples/http_0mq
# WARNING: on some systems the nohup doesn't work, like OSX
# try running it without
-nohup python -u http.py 2>&1 > http.log &
+nohup python -u http.py > http.log 2>&1 &
echo $! > $DEPLOY/profiles/handlertest/handlertest.pid
2  docs/manual/inputs/procer_mp3stream_run.sh
View
@@ -7,5 +7,5 @@ SOURCE=/home/YOU/projects/mongrel2
cd $SOURCE/examples/mp3stream
# WARNING: on some systems the nohup doesn't work, like OSX
# try running it without
-nohup python -u handler.py 2>&1 > mp3stream.log &
+nohup python -u handler.py > mp3stream.log 2>&1 &
echo $! > $DEPLOY/profiles/mp3stream/mp3stream.pid
2  docs/manual/inputs/procer_script_for_chat_demo.sh
View
@@ -7,5 +7,5 @@ SOURCE=/home/YOU/projects/mongrel2
cd $SOURCE/examples/chat
# WARNING: on some systems the nohup doesn't work, like OSX
# try running it without
-nohup python -u chat.py 2>&1 > chat.log &
+nohup python -u chat.py > chat.log 2>&1 &
echo $! > $DEPLOY/profiles/chat/chat.pid
2  docs/manual/inputs/procer_web_run.sh
View
@@ -7,6 +7,6 @@ SOURCE=/home/YOU/projects/mongrel2
cd $SOURCE/examples/chat
# WARNING: on some systems the nohup doesn't work, like OSX
# try running it without
-nohup python -u www.py 2>&1 > www.log &
+nohup python -u www.py > www.log 2>&1 &
echo $! > $DEPLOY/profiles/web/web.pid
26 docs/manual/installing.tex
View
@@ -32,13 +32,27 @@ \section{Install Dependencies}
install required packages for your OS, but here's how I did it on my computer:
\begin{code}{Installing Dependencies on ArchLinux}
-<< d['/docs/manual/inputs/install_dependencies.sh|pyg|l'] >>
+<< d['inputs/install_dependencies.sh|pyg|l'] >>
\end{code}
If you run into parts that your OS is missing, which is likely on
Debian and SuSE systems, then you'll have to go and figure out
how to install it.
+Some distributions (like Ubuntu) split ``dev'' and ``runtime'' packages.
+In order to build mongrel2 on these distros, you must install libsqlite3-dev:
+this package contains sqlite3.h, which Mongrel2 needs during compilation.
+
+For the lazy, the command is: \shell{sudo apt-get install libsqlite3-dev}
+
+Other pieces known to be missing on ubuntu-like systems:
+
+\begin{itemize}
+\item uuid-runtime: Needed by m2sh uuid command
+\item You may need to run: \shell{sudo ldconfig -v}
+\end{itemize}
+
+
\section{Building Mongrel2}
If everything went well you should be able to grab the Mongrel2 source
@@ -68,7 +82,7 @@ \subsection{Using git}
Once you have git you can then get the Mongrel2 source and open it up:
\begin{code}{Cloning the Mongrel2 Source}
-<< d['/docs/manual/inputs/cloning_mongrel2_source.sh|pyg|l'] >>
+<< d['inputs/cloning_mongrel2_source.sh|pyg|l'] >>
\end{code}
Make sure you do this in order (just like with every set of instructions you follow)
@@ -113,8 +127,8 @@ \subsection{Other platforms than Linux}
So for example you would probably install zeromq and sqlite3 as ports and then compile it like so:
-\begin{code}{Installing Mongrel2 on FreeNSD}
-<< d['/docs/manual/inputs/install_freebsd.sh|pyg|l'] >>
+\begin{code}{Installing Mongrel2 on FreeBSD}
+<< d['inputs/install_freebsd.sh|pyg|l'] >>
\end{code}
\section{Testing The Installation}
@@ -124,7 +138,7 @@ \section{Testing The Installation}
use to try it out:
\begin{code}{First Test Run}
-<< d['/docs/manual/inputs/first_mongrel2_run.sh|pyg|l'] >>
+<< d['inputs/first_mongrel2_run.sh|pyg|l'] >>
\end{code}
That's it. Just hit CTRL-c for now and we'll get into playing with this
@@ -132,7 +146,7 @@ \section{Testing The Installation}
\section{Upgrading from trunk}
\begin{code}{Update your checkout}
-<< d['/docs/manual/inputs/updating_your_checkout.sh|pyg|l'] >>
+<< d['inputs/updating_your_checkout.sh|pyg|l'] >>
\end{code}
2  docs/manual/introduction.tex
View
@@ -24,7 +24,7 @@ \chapter{Introduction}
\begin{aside}{TL;DR!}
Don't want to read the manual?\footnote{I guess you'll be one of the first people with questions then.}
-You can read \href{http://mongrel2.org/wiki/quick_start.html}{the Getting Started page} available
+You can read \href{http://mongrel2.org/wiki/quick_start.html}{the Getting Started page}, available in
many languages even. It's a fast crash course in getting Mongrel2 up and running.
\end{aside}
129 docs/manual/managing.tex
View
@@ -80,18 +80,27 @@ \section{Trying m2sh}
After you have that, do this:
\begin{code}{Sample m2sh Commands}
-<< d['/docs/manual/inputs/sample_m2sh_commands.sh|pyg|l'] >>
+<< d['inputs/sample_m2sh_commands.sh|pyg|l'] >>
\end{code}
At this point, you should have seen lists of servers and hosts, seen that mongrel2 is
not running, and then started it. You can find out about all the commands and
get help for them with \shell{m2sh help} or \shell{ms2h help command}.
-You can now try doing some simple starting, stopping and reloading using sudo (make sure you CTRL-c
-to exit from the previous start command):
+You can now try doing some simple starting, stopping and reloading Using
+sudo (make sure you CTRL-c to exit from the previous start command):
+
+\begin{aside}{Warning: contents may be broken}
+If \shell{m2sh start} runs fine, but \shell{m2sh start -sudo}
+fails, you may need to link \file{/proc} in your chroot, using
+\shell{mkdir -p proc \&\& sudo mount --bind /proc proc}. You can also try
+installing ZeroMQ from source, if you'd rather avoid putting your \file{/proc}
+where it might get seen.
+\end{aside}
+
\begin{code}{Starting, Stopping, Reloading}
-<< d['/docs/manual/inputs/starting_stopping_reloading.sh|pyg|l'] >>
+<< d['inputs/starting_stopping_reloading.sh|pyg|l'] >>
\end{code}
Awesome, right? Using just this one little management tool you
@@ -151,7 +160,7 @@ \section{A Simple Configuration File}
we would just do this:
\begin{code}{Loading The Simple Config}
-<< d['/docs/manual/inputs/load_simple_config.sh|pyg|l'] >>
+<< d['inputs/load_simple_config.sh|pyg|l'] >>
\end{code}
Notice that we didn't have to tell m2sh that the database was \file{config.sqlite}.
@@ -577,7 +586,7 @@ \subsection{JSON/XML Message Routing Syntax}
full, but the meat of it is:
\begin{code}{BBS Client JSON Socket Handling}
-<< d['/docs/manual/inputs/bbs_client_socket.py|pyg|l'] >>
+<< d['inputs/bbs_client_socket.py|pyg|l'] >>
\end{code}
In that code, notice how (for historical reasons due to Flash sucking) the
@@ -589,7 +598,7 @@ \subsection{JSON/XML Message Routing Syntax}
Finally, here's the grammar rules in the parser for handling these messages:
\begin{code}{JSON/XML Message Grammar}
-<< d['/docs/manual/inputs/json_xml_socket_grammar.py|pyg|l'] >>
+<< d['inputs/json_xml_socket_grammar.py|pyg|l'] >>
\end{code}
If you read that carefully, you'll see you can actually pass query strings
@@ -686,14 +695,14 @@ \section{Control Port}
You then use the control port by running \ident{m2sh}:
-<< d['/docs/manual/inputs/sample_m2sh_run.sh|pyg|l'] >>
+<< d['inputs/sample_m2sh_run.sh|pyg|l'] >>
The protocol to and from the control socket is a simple tnetstring in and out that
any langauge can read. Here's a nearly complete Python client that is using
the control port:
\begin{code}{Python Control Port Example}
-<< d['/docs/manual/inputs/python_control_port.py|pyg|l'] >>
+<< d['inputs/python_control_port.py|pyg|l'] >>
\end{code}
You obviously don't need to do this, but should you want to do
@@ -744,6 +753,8 @@ \section{Multiple Servers}
> m2sh stop -db config.sqlite -every
\end{lstlisting}
+
+
\section{Tweakable Expert Settings}
Many of Mongrel2's internal settings are configurable using the settings system.
@@ -757,7 +768,7 @@ \section{Tweakable Expert Settings}
\begin{code}{Changing Settings}
\begin{lstlisting}
-<< d['/docs/manual/inputs/changing_settings.conf|dexy'] >>
+<< d['inputs/changing_settings.conf|dexy'] >>
\end{lstlisting}
\end{code}
@@ -767,6 +778,7 @@ \section{Tweakable Expert Settings}
\begin{description}
\item[control\_port=ipc://run/control] This is where Mongrel2 will listen with 0MQ for control messages. You should use \verb|ipc://| for the spec, so that only a local user with file access can get at it.
+\item[disable.access\_logging=0] Set this to \verb|1| to turn off access logs. You still have to specify log files but they won't be created.
\item[limits.buffer\_size=2 * 1024] Internal IO buffers, used for things like proxying and handling requests. This is a \emph{very} conservative setting, so if you get HTTP headers greater than this, you'll want to increase this setting. You'll also want to shoot whoever is sending you those requests, because the average is 400-600 bytes.
\item[limits.client\_read\_retries=5] How many times it will attempt to read a complete HTTP header from a client. This prevents attacks where a client trickles an incomplete request at you until you run out of resources.
\item[limits.connection\_stack\_size=32 * 1024] Size of the stack used for connection coroutines. If you're trying to cram a ton of connections into very little RAM, see how low this can go.
@@ -802,7 +814,102 @@ \section{Tweakable Expert Settings}
\begin{code}{Changing Mimetypes}
\begin{lstlisting}
-<< d['/docs/manual/inputs/changing_settings.conf|dexy'] >>
+<< d['inputs/changing_mimetypes.conf|dexy'] >>
+\end{lstlisting}
+\end{code}
+
+
+\section{SSL Configuration}
+
+Mongrel2 now support SSL, with preliminary support for SSL session caching. As of
+v1.8.0 (actually earlier) you can enable SSL very easily for your Mongrel2 server.
+How Mongrel2 configures SSL certs is with two options in \verb|setttings| and then
+a directory of .crt and .key files named after the UUID of the servers that need them.
+
+To get started, you can make a simple self-signed certificate with some weak encryption
+and setup your certs directory:
+
+\begin{code}{Making A Self-Signed Certificate}
+<< d['inputs/makecert.sh|pyg|l'] >>
+\end{code}
+
+I actually have a shell script kind of like this since I can never remember how
+to set this stuff up with openssl. Also, you should really adjust the RSA key
+strength from 512 to something you're comfortable with. I'm using a weak
+key here so you can do performance testing and thrashing and then compare with
+your real key later.
+
+Once you have that done, you just have to add three little settings to your
+mongrel2 conf:
+
+\begin{enumerate}
+\item Add the settings "certsdir" pointed at "./certs/", make sure it has the trailing slash.
+\item Add the \verb|Server.use\_ssl = 1| value to the Server that has this UUID
+ you just created a cert for.
+\item Optionally, set the settings "ssl\_ciphers" to "SSL\_RSA\_RC4\_128\_SHA" so you can
+ play with the performance of a weak cipher. If you unset this then Mongrel2 will
+ use the best one a browser wants.
+\end{enumerate}
+
+After you have those changes your config should look something like this:
+
+\begin{code}{Minimal SSL Configuration}
+\begin{lstlisting}
+<< d['inputs/mini_ssl_settings.conf|dexy'] >>
\end{lstlisting}
\end{code}
+Get that written, rerun \verb|m2sh config| to make the new config, restart
+Mongrel2 (you can't reload to enable SSL), and it should be working.
+
+After you get this working you just have to get your own certificate, put it
+in the certs directory with the right filename, and you should be good to go.
+
+\subsection{Experimental SSL Caching}
+
+We've got experimental SSL caching working, which will try to reuse the
+browser's SSL session if it's there. This is meant to be a trade-off between
+memory and performance, so it can chew a bunch of RAM if you have a lot of
+SSL traffic over a short period of time. We'll be making the caching more
+configurable, but for now, it's working and does speed up SSL clients that
+do it properly.
+
+
+\section{Configuring Filters (BETA)}
+
+The Mongrel2 v1.8.0 release also included working filters that you can
+configure and load dynamically. The filters are very fresh, and the
+only one available is the null filter found in \file{tools/filters/null.c}
+but it does work and you can configure it. It's also currently not
+hooked into the reload gear that we've recently done, so don't expect
+it to work if you do frequently hot reloading.
+
+Configuring a filter is fairly easy, take a look at this example:
+
+\begin{code}{Minimal Filter Configuration}
+\begin{lstlisting}
+<< d['inputs/filters.conf|dexy'] >>
+\end{lstlisting}
+\end{code}
+
+First you can see that we setup the \ident{null} filter with some arbitrary
+settings and point to where the .so file is. Filters can be configured
+with any arbitrarily nested data structure that can fit into a tnetstring,
+so you can pass them pretty much anything that matters. Lists, dicts, numbers,
+strings, are the main ones. You can also use variables in the config file,
+so you could create different servers and share config options for Filters
+and other parts of the files.
+
+After that, there's simply a \ident{Server.filters} which takes a list of
+filters to load. If you don't set this variable, then the filter gear isn't
+even loaded and your server behaves as normal. If you do set this variable,
+then the filters are installed and will work.
+
+If you run this config, you'll see the filter printing out it's config
+as a tnetstring, and then closing the connection, but only if you go
+to \ident{/nulltest/}. If you go to \ident{/tests/sample.html} to
+get at a directory, it'll not even run.
+
+We'll have more documentation on actually writing filters in the
+Hacking section.
+
2  docs/manual/preamble.tex
View
@@ -1,6 +1,5 @@
\documentclass{book}
\usepackage{iwona,palatino}
-<< pygments['pastie.tex'] >>
%\usepackage{palatino}
\usepackage[
pdftitle={Mongrel2 Manual: Installing, Deploying, Hacking},
@@ -20,6 +19,7 @@
\usepackage{parskip}
\usepackage{textcomp}
\usepackage{listings}
+<< pygments['pastie.tex'] >>
\parskip 7.2pt
\lstset{basicstyle=\ttfamily,
0  docs/ru/.nodexy
View
No changes.
4 docs/ru/manual/book.wiki
View
@@ -4974,7 +4974,7 @@
<p class="noindent">The end result is <span class=
"pcrro7t-">procer</span>, which lives in <span class=
- "pcrb7t-">examples/procer</span> and does most of what you need
+ "pcrb7t-">tools/procer</span> and does most of what you need
in a USPM. It works a lot like daemontools or minit, but is much
simpler, with these differences: <!--l. 86-->
@@ -5076,7 +5076,7 @@
<p class="noindent">Installing procer is very easy. It's a
single little binary and it lives in <span class=
- "pcrb7t-">examples/procer</span> in the Mongrel2 source.
+ "pcrb7t-">tools/procer</span> in the Mongrel2 source.
Here's how you'd install it totally from scratch as
if you hadn't even build Mongrel2 yet: <!--l. 136-->
6 docs/ru/manual/deploying.tex
View
@@ -81,7 +81,7 @@ \subsection{Введение в procer}
сделал.
В результате --- \shell{procer}. Вы можете найти эту утилиту в
-\file{examples/procer}. Она делает всё что нам нужно и работает подобно
+\file{tools/procer}. Она делает всё что нам нужно и работает подобно
daemontools или minit, но гораздо проще по своему дизайну. Вот список отличий от
всех приведённых выше аналогов:
@@ -133,14 +133,14 @@ \subsection{Введение в procer}
\subsection{Устанавливаем procer}
Установка очень простая. На выходе --- один бинарный файл. Исходники лежат в
-\file{examples/procer}. Чтобы установить с нуля, выполните все команды по
+\file{tools/procer}. Чтобы установить с нуля, выполните все команды по
списку:
\begin{code}{Install procer}
\begin{lstlisting}
> cd projects/mongrel2
> make clean all && sudo make install
-> cd examples/procer
+> cd tools/procer
> make clean all && sudo make install
\end{lstlisting}
\end{code}
12 docs/site/Makefile
View
@@ -0,0 +1,12 @@
+WEBSITE=$(USER)@mongrel2.org:/var/www/mongrel2.org/
+
+all:
+ rsync -a --delete assets/ output/
+ lua gensite.lua output
+
+clean:
+ rm -rf output
+
+sync: all
+ rsync -avz output/* $(WEBSITE)/
+
BIN  docs/site/assets/assets/aj-125x125.gif
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/automation.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/book_info.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/comment_blue.gif
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/comment_new.gif
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/date.gif
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/icon-16x16.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/icon-32x32.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/icon_info.gif
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/languages.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/modern_design.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/people.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/protocols.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/icons/source_clone.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/placeholder-50x50.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/placeholder-520x340.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/placeholder-58x58.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/placeholder-615x140.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/placeholder-840x320.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  docs/site/assets/assets/tf-125x125.gif
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2,699 docs/site/assets/css/light-green.css
View
@@ -0,0 +1,2699 @@
+/* ----------------------------------
+-------- RESET ----------
+---------------------------------- */
+
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+body {
+ line-height: 1;
+}
+ol, ul {
+ list-style: none;
+}
+blockquote, q {
+ quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+/* ----------------------------------
+--------- TYPOGRAPHY ----------
+---------------------------------- */
+
+body {
+ color: #666666;
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 11px;
+ line-height: 18px;
+ -moz-text-shadow: -1px 1px 0 #ffffff;
+ -webkit-text-shadow: -1px 1px 0 #ffffff;
+ text-shadow: -1px 1px 0 #ffffff;
+}
+
+h1 {
+ color: #4c4c4c;
+ font-family: Georgia, serif;
+ font-size: 28px;
+ font-weight: normal;
+ margin-bottom: 18px;
+ line-height: 36px;
+}
+
+h2,
+h3,
+h4 {
+ color: #4c4c4c;
+ font-family: Trebuchet MS, 'Trebuchet MS', Tahoma, Arial, sans-serif;
+ font-weight: bold;
+}
+
+h2 {
+ font-size: 24px;
+ line-height: 36px;
+ margin-bottom: 18px;
+}
+
+h3 {
+ font-size: 20px;
+ line-height: 36px;
+}
+
+h4 {
+ font-size: 16px;
+ line-height: 36px;
+}
+
+h5 {
+ color: #4c4c4c;
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 13px;
+ font-weight: bold;
+ line-height: 36px;
+ text-transform: uppercase;
+}
+
+h6 {
+ color: #4c4c4c;
+ font-size: 11px;
+ font-weight: bold;
+ line-height: 18px;
+ text-transform: uppercase;
+}
+
+h1 a,
+h2 a,
+h3 a,
+h4 a,
+h5 a,
+h6 a {
+ color: #4c4c4c;
+}
+
+h1 a:hover,
+h2 a:hover,
+h3 a:hover,
+h4 a:hover,
+h5 a:hover,
+h6 a:hover {
+ color: #666666;
+}
+
+h1 a:active,
+h2 a:active,
+h3 a:active,
+h4 a:active,
+h5 a:active,
+h6 a:active {
+ color: #333333;
+}
+
+h1 em,
+h2 em,
+h3 em,
+h4 em {
+ font-family: Georgia, serif;
+ font-weight: normal;
+}
+
+h2 small {
+ display: block;
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 11px;
+ font-weight: normal;
+ line-height: 12px;
+ margin-bottom: -4px;
+ text-transform: uppercase;
+}
+
+h3 small {
+ display: block;
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 11px;
+ font-weight: normal;
+ line-height: 12px;
+ margin-bottom: -4px;
+ text-transform: uppercase;
+}
+
+h4 small {
+ display: block;
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 9px;
+ font-weight: normal;
+ line-height: 12px;
+ margin-bottom: -6px;
+ text-transform: uppercase;
+}
+
+.post-title {
+ font-family: Georgia, serif;
+ font-weight: normal;
+ margin-bottom: 18px;
+}
+
+.post-archive .post-title {
+ float: left;
+ margin-bottom: 0;
+ width: 80%;
+}
+
+p {
+ margin-bottom: 18px;
+}
+
+a {
+ color: #5684b2;
+ cursor: pointer;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #6297cc;
+ text-decoration: underline;
+}
+
+a:active {
+ color: #43688c;
+}
+
+a.more {
+ font-weight: bold;
+}
+
+h1 a,
+h2 a,
+h3 a,
+h4 a,
+h5 a,
+h6 a,
+.button,
+#header a,
+#footer a {
+ background-color: transparent;
+ border-bottom: 0;
+}
+
+.button:hover,
+#header a:hover,
+#footer nav a:hover {
+ text-decoration: none;
+}
+
+ul {
+ line-height: 15px;
+ font-weight: normal;
+ margin-bottom: 18px;
+ text-transform: none;
+}
+
+ol {
+ line-height: 15px;
+ margin-bottom: 18px;
+ list-style-type: decimal;
+}
+
+dl {
+ line-height: 15px;
+ margin-bottom: 18px;
+}
+
+dt {
+ font-weight: bold;
+}
+
+li, dd {
+ margin-bottom: 4px;
+}
+
+.post-content ul,
+.post-content ol,
+.post-content dl {
+ margin-left: 18px;
+ margin-right: 18px;
+}
+
+ul.links,
+.sidebar ul,
+.pagination {
+ font-family: Georgia, serif;
+ font-size: 12px;
+ font-style: italic;
+}
+
+ul.links li a:hover, .sidebar ul li a:hover {
+ background-image: url(../images/light-green/list-item.png);
+ background-repeat: no-repeat;
+ background-position: right bottom;
+ padding-right: 12px;
+}
+
+.sidebar ul li.current a {
+ color: #4c4c4c;
+}
+
+.sidebar ul li.current a:hover {
+ background-image: url(../images/light-green/list-item-current.png);
+}
+
+.sidebar ul li.current ul li a {
+ color: #5684b2;
+}
+
+.sidebar ul li ul li a:hover {
+ color: #6297cc;
+}
+
+.sidebar ul li ul li a:active {
+ color: #43688c;
+}
+
+.sidebar ul li.current ul li a:hover {
+ background-image: url(../images/light-green/list-item.png);
+}
+
+.sidebar ul li.current ul li.current a {
+ color: #4c4c4c;
+}
+
+.sidebar ul li.current ul li.current a:hover {
+ background-image: url(../images/light-green/list-item-current.png);
+}
+
+ul.info {
+ font-style: normal;
+ font-weight: bold;
+}
+
+ul.info li small {
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 10px;
+ font-weight: normal;
+ text-transform: uppercase;
+}
+
+em {
+ font-style: italic;
+}
+
+strong {
+ font-weight: bold;
+}
+
+small {
+ color: #808080;
+ font-size: 10px;
+}
+
+ins {
+ background-color: #f8f8f8;
+}
+
+s,
+del {
+ text-decoration: line-through;
+}
+
+cite,
+q {
+ font-family: Georgia, serif;
+ font-style: italic;
+}
+
+cite {
+ color: #4c4c4c;
+}
+
+abbr,
+acronym {
+ border-bottom: 1px dotted;
+ cursor: help;
+}
+
+dfn {
+ font-style: italic;
+}
+
+time {
+ cursor: help;
+ font-weight: bold;
+}
+
+var {
+ font-family: Georgia, serif;
+ font-style: italic;
+}
+
+sub {
+ font-size: 8px;
+ vertical-align: sub;
+}
+
+sup {
+ font-size: 8px;
+ vertical-align: super;
+}
+
+blockquote {
+ background: transparent url(../images/light-green/quote.png) no-repeat left top;
+ font-family: Georgia, serif;
+ font-size: 12px;
+ font-style: italic;
+ font-weight: normal;
+ margin-bottom: 18px;
+ text-align: center;
+}
+
+.column blockquote {
+ padding: 0 10px;
+}
+
+.third blockquote {
+ padding: 0 20px;
+}
+
+.half blockquote {
+ padding: 0 20px;
+}
+
+blockquote .author {
+ display: block;
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: bold;
+ margin-top: 18px;
+ padding: 0 17px;
+}
+
+blockquote .author .company {
+ font-size: 10px;
+ font-weight: normal;
+}
+
+caption,
+figcaption,
+.caption {
+ font-family: Georgia, serif;
+ font-size: 12px;
+ font-style: italic;
+ margin-bottom: 18px;
+ text-align: center;
+}
+
+figcaption {
+ margin-bottom: 4px;
+}
+
+pre {
+ font-family: "Courier New", monospace;
+}
+
+code,
+samp {
+ font-family: "Courier New", monospace;
+}
+
+label {
+ color: #4c4c4c;
+ font-size: 11px;
+ font-weight: bold;
+ line-height: 14px;
+ margin-top: -1px;
+ text-transform: uppercase;
+}
+
+label small {
+ color: #808080;
+ font-size: 10px;
+ font-weight: normal;
+ text-transform: none;
+}
+
+form, input, textarea {
+ color: #4c4c4c;
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 11px;
+}
+
+#header {
+ color: #fefefe;
+ -moz-text-shadow: -1px 1px 0 rgba(0, 0, 0, .3);
+ -webkit-text-shadow: -1px 1px 0 rgba(0, 0, 0, .3);
+ text-shadow: -1px 1px 0 rgba(0, 0, 0, .3);
+}
+
+#header a {
+ color: #f8fce8;
+}
+
+#header a:hover {
+ color: #ffffff;
+}
+
+#header .current > a {
+ color: #ffffff;
+}
+
+#nav {
+ font-size: 12px;
+ font-style: normal;
+ font-weight: bold;
+ line-height: 1em;
+ text-transform: uppercase;
+}
+
+#footer a {
+ color: #4c4c4c;
+}
+
+#footer-nav {
+ color: #4c4c4c;
+ font-size: 10px;
+ font-style: normal;
+ font-weight: bold;
+ line-height: 18px;
+ margin-bottom: 0;
+ text-transform: uppercase;
+}
+
+.button,
+#submit,
+input[type=submit] {
+ color: #f7f7f7;
+ font-size: 11px;
+ font-weight: bold;
+ -moz-text-shadow: -1px 1px 0 rgba(0, 0, 0, .3);
+ -webkit-text-shadow: -1px 1px 0 rgba(0, 0, 0, .3);
+ text-shadow: -1px 1px 0 rgba(0, 0, 0, .3);
+}
+
+.button:hover,
+#submit:hover,
+input[type=submit]:hover {
+ color: #ffffff;
+}
+
+.post-blog .post-meta,
+.description {
+ color: #4c4c4c;
+ line-height: 18px;
+ text-align: right;
+}
+
+.description {
+ color: #808080;
+ font-size: 10px;
+ line-height: 15px;
+}
+
+.description pre {
+ color: #666666;
+}
+
+.post-meta .date {
+ display: block;
+ font-weight: bold;
+ text-transform: uppercase;
+}
+
+.post-meta .categories-list {
+ font-style: normal;
+ font-weight: bold;
+}
+
+.post-meta .categories-list li {
+ line-height: 18px;
+ margin-bottom: 0;
+}
+
+ul#wiki-topics {
+ font-family: 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif;
+ font-size: 11px;
+ font-style: normal;
+ font-weight: bold;
+ line-height: 16px;
+ text-transform: uppercase;
+}
+
+ul#wiki-topics a {
+ border: 0;
+}
+
+.post-archive .post-content {
+ clear: both;
+}
+
+.post-meta,
+.post-archive .date {
+ color: #4c4c4c;
+ font-weight: bold;
+ text-transform: uppercase;
+}
+
+.post-archive .date {
+ float: right;
+ line-height: 36px;
+}
+
+.post-blog .post-meta {
+ font-weight: normal;
+ text-transform: none;
+}
+
+.post-meta small {
+ color: #808080;
+ font-family: Georgia, serif;
+ font-size: 12px;
+ font-style: italic;
+ font-weight: normal;
+ text-transform: none;
+}
+
+ul#faq {
+ font-style: normal;
+ line-height: 18px;
+}
+
+ul#faq a:first-child {
+ border: 0;
+ color: #4c4c4c;
+ display: block;
+ font-size: 13px;
+ font-style: normal;
+}
+
+ul#faq a:first-child:hover {
+ color: #666666;
+ text-decoration: none;
+}
+
+ul#faq a:first-child:active {
+ color: #333333;
+}
+
+
+
+/* ----------------------------------
+--------- MAIN ----------
+---------------------------------- */
+
+
+html {
+ height: 100%;
+}
+
+body {
+ height: 100%;
+ width: 100%;
+ min-width: 1040px;
+ background: #f5f5f5 url(../images/light-green/background-texture.png) repeat 0 0;
+}
+
+/* Sticky Footer Opera Fix*/
+body:before {
+ content:"";
+ height:100%;
+ float:left;
+ width:0;
+ margin-top:-32767px;
+}
+
+#wrap {
+ min-height: 100%;
+}
+
+.inner-wrap {
+ margin: 0 auto;
+ padding: 0 40px;
+ width: 960px;
+ overflow: hidden;
+}
+
+#header {
+ background: #b8cc70 url(../images/light-green/header-texture.png) repeat 0 0;
+ border-bottom: 1px solid #8a9954;
+ position: relative;
+
+ background: url(../images/light-green/header-texture.png) repeat 0 0, -ms-linear-gradient(
+ top,
+ #a4b664 0%,
+ #b8cc70 100%
+ );
+ background: url(../images/light-green/header-texture.png) repeat 0 0, -moz-linear-gradient(
+ top,
+ #a4b664 0%,
+ #b8cc70 100%
+ );
+ background: url(../images/light-green/header-texture.png) repeat 0 0, -o-linear-gradient(
+ top,
+ #a4b664 0%,
+ #b8cc70 100%
+ );
+ background: url(../images/light-green/header-texture.png) repeat 0 0, -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0, #a4b664),
+ color-stop(1, #b8cc70)
+ );
+ background: url(../images/light-green/header-texture.png) repeat 0 0, -webkit-gradient(
+ top,
+ #a4b664 0%,
+ #b8cc70 100%
+ );
+ background: url(../images/light-green/header-texture.png) repeat 0 0, linear-gradient(
+ top,
+ #a4b664 0%,
+ #b8cc70 100%
+ );
+
+ -moz-box-shadow: inset 0 -3px 3px rgba(0, 0, 0, .07), 0 3px 0 rgba(138, 153, 84, .25);
+ -webkit-box-shadow: inset 0 -3px 3px rgba(0, 0, 0, .07), 0 3px 0 rgba(138, 153, 84, .25);
+ box-shadow: inset 0 -3px 3px rgba(0, 0, 0, .07), 0 3px 0 rgba(138, 153, 84, .25);
+}
+
+#action{
+ background: #ffffff url(../images/light-green/background-texture.png) repeat 0 0;
+ border-top: 1px solid #f0f0f0;
+}
+
+#action .inner-wrap {
+ padding-top: 30px;
+ padding-bottom: 30px;
+}
+
+#action .button {
+ margin-top: 14px;
+ width: 139px;
+}
+
+#featured {
+ background: #fafafa url(../images/light-green/background-texture.png) repeat 0 0;
+}
+
+#featured .inner-wrap {
+ padding-top: 23px;
+ padding-bottom: 20px;
+ position: relative;
+}
+
+.breadcrumb h2,
+.breadcrumb h3,
+.breadcrumb h4,
+.breadcrumb h5 {
+ margin: 0;
+}
+
+.js-ready .preload img {
+ visibility: hidden;
+}
+
+#slider-container {
+ margin: 0 auto;
+ width: 920px;
+ overflow: hidden;
+}
+
+#slider-container.loading {
+ background: transparent url(../images/light-green/ajax-loader.gif) no-repeat center center;
+}
+
+.js-ready .slider {
+ visibility: hidden;
+}
+
+.js-ready .slide {
+ display: none;
+ visibility: hidden;
+}
+
+.js-ready .slide:first-child {
+ display: block;
+}
+
+#slider-container .slide {
+ margin: 0 40px;
+ width: 840px;
+}
+
+.slide.text-left .post-content {
+ float: left;
+ margin-right: 40px;
+ width: 280px;
+}
+
+.slide.text-left .post-image-container {
+ float: left;
+ width: 520px;
+}
+
+.slide.text-right .post-content {
+ float: right;
+ margin-left: 40px;
+ width: 280px;
+}
+
+.slide.text-right .post-image-container {
+ float: right;
+ width: 520px;
+}
+
+.slide.text-center .post-content {
+ margin-bottom: 36px;
+ text-align: center;
+ width: 840px;
+}
+
+.slide.text-center .post-image-container {
+ width: 840px;
+}
+
+.slide .post-content h2 {
+ line-height: 30px;
+}
+
+.slide .post-content h2 small {
+ margin-bottom: 0;
+}
+
+.slide .featured-image {
+ display: block;
+ margin: 0 auto;
+}
+
+.slide img {
+ background: transparent;
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF)"; /* IE8 */
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF); /* IE6 & 7 */
+ zoom: 1;
+}
+
+.fourth #quote-slider .slide {
+ width: 190px;
+}
+
+.half #quote-slider .slide {
+ width: 420px;
+}
+
+.third #quote-slider .slide {
+ width: 254px;
+}
+
+#quote-slider {
+ overflow: hidden;
+}
+
+#quote-slider .prev {
+ background: transparent url(../images/light-green/icons.png) no-repeat left -108px;
+ cursor: pointer;
+ display: block;
+ width: 8px;
+ height: 9px;
+ position: absolute;
+ bottom: 22px;
+ z-index: 20;
+}
+
+#quote-slider .next {
+ background: transparent url(../images/light-green/icons.png) no-repeat right -108px;
+ cursor: pointer;
+ display: block;
+ width: 8px;
+ height: 9px;
+ position: absolute;
+ bottom: 22px;
+ z-index: 20;
+}
+
+.fourth #quote-slider .prev,
+.third #quote-slider .prev {
+ left: 15px;
+}
+
+.fourth #quote-slider .next,
+.third #quote-slider .next {
+ right: 15px;
+}
+
+.half #quote-slider .prev {
+ left: 0;
+}
+
+.half #quote-slider .next {
+ left: 10px;
+}
+
+#quote-slider .prev:active,
+#quote-slider .next:active {
+ bottom: 21px;
+}
+
+.slider-button {
+ cursor: pointer;
+ display: block;
+ height: 18px;
+ width: 20px;
+ margin-top: -9px;
+ padding: 20px 0;
+ position: absolute;
+ top: 50%;
+
+ -ms-transition: background .2s ease-in, opacity .2s ease-in;
+ -moz-transition: background .2s ease-in, opacity .2s ease-in;
+ -o-transition: background .2s ease-in, opacity .2s ease-in;
+ -webkit-transition: background .2s ease-in, opacity .2s ease-in;
+ transition: background .2s ease-in, opacity .2s ease-in;
+}
+
+.slider-button:active {
+ margin-top: -8px;
+}
+
+.slider-button.prev {
+ background: transparent url(../images/light-green/icons.png) no-repeat 7px -280px;
+ left: 40px;
+ opacity: .5;
+}
+
+#featured:hover .slider-button.prev {
+ background: transparent url(../images/light-green/icons.png) no-repeat 0 -280px;
+ opacity: 1;
+}
+
+.slider-button.next {
+ background: transparent url(../images/light-green/icons.png) no-repeat 1px -320px;
+ right: 40px;
+ opacity: .5;
+}
+
+#featured:hover .slider-button.next {
+ background: transparent url(../images/light-green/icons.png) no-repeat 8px -320px;
+ opacity: 1;
+}
+
+#action + #main {
+ border-top: 3px solid #f0f0f0;
+}
+
+#main {
+ background: transparent url(../images/light-green/content-texture-top.png) repeat-x 0 0;
+ border-top: 3px solid #ededed;
+ padding-bottom: 156px; /* Must be the same as footer height */
+}
+
+#main .inner-wrap {
+ padding-top: 36px;
+ padding-bottom: 36px;
+}
+
+.content {
+ width: 627px;
+}
+
+.content-full {
+ width: 100%;
+}
+
+.content-left {
+ float: left;
+ margin-right: 39px;
+}
+
+.content-right {
+ float: right;
+ margin-left: 39px;
+}
+
+.sidebar {
+ width: 294px;
+ float: left;
+}
+
+.sidebar .widget {
+ clear: both;
+}
+
+.sidebar .widget-list {
+ float: left;
+ margin-right: 20px;
+ width: 137px;
+}
+
+.sidebar .widget-list + .widget-list {
+ clear: none;
+ margin-right: 0;
+}
+